diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9cc608e..2d3d263 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,11 +5,11 @@ version: 2 updates: - - package-ecosystem: "npm" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: 'npm' # See documentation for possible values + directory: '/' # Location of package manifests schedule: - interval: "monthly" - - package-ecosystem: "github-actions" - directory: "/" + interval: 'monthly' + - package-ecosystem: 'github-actions' + directory: '/' schedule: - interval: "monthly" + interval: 'monthly' diff --git a/.github/workflows/auto-author-assign.yml b/.github/workflows/auto-author-assign.yml new file mode 100644 index 0000000..60adc81 --- /dev/null +++ b/.github/workflows/auto-author-assign.yml @@ -0,0 +1,14 @@ +name: Auto Author Assign + +on: + pull_request_target: + types: [opened, reopened] + +permissions: + pull-requests: write + +jobs: + assign-author: + runs-on: ubuntu-latest + steps: + - uses: toshimaru/auto-author-assign@v2.1.0 diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..f8eb476 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,32 @@ +name: PR Check + +on: + push: + branches-ignore: + - main + +jobs: + pr-check: + name: PR Check + runs-on: ubuntu-latest + env: + HUSKY: 0 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + - name: Install dependencies + run: npm ci + - name: Lint + run: npm run lint + - name: Type check + run: npm run type-check + - name: Build + run: npm run build + # - name: Test + # run: npm run test diff --git a/package-lock.json b/package-lock.json index db28e9c..b528863 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,21 +9,27 @@ "version": "1.0.1", "license": "MIT", "dependencies": { + "@eslint-community/eslint-plugin-eslint-comments": "4.1.0", "@typescript-eslint/eslint-plugin": "7.2.0", "@typescript-eslint/parser": "7.2.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "2.29.1", "eslint-plugin-jsx-a11y": "6.8.0", - "eslint-plugin-react": "7.34.0", + "eslint-plugin-n": "16.6.2", + "eslint-plugin-no-unsanitized": "4.0.2", + "eslint-plugin-react": "7.34.1", "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-unicorn": "51.0.1" + "eslint-plugin-security": "2.1.1", + "eslint-plugin-sonarjs": "0.24.0", + "eslint-plugin-unicorn": "51.0.1", + "eslint-plugin-xss": "0.1.12" }, "devDependencies": { "@commitlint/cli": "19.2.0", "@commitlint/config-conventional": "19.1.0", "@commitlint/types": "19.0.3", "@types/eslint": "8.56.5", - "@types/node": "20.11.27", + "@types/node": "20.11.28", "husky": "9.0.11", "lint-staged": "15.2.2", "prettier": "3.2.5", @@ -480,6 +486,21 @@ "fast-check": "^3.13.2" } }, + "node_modules/@eslint-community/eslint-plugin-eslint-comments": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-4.1.0.tgz", + "integrity": "sha512-B2mwipifrBS5E00vN8vME68laPMZ0h3sNGOEDj5g9iUN9k5EU99Omq0Nc325eKNoFFDnDtiHp3DqIjO+1bstag==", + "dependencies": { + "escape-string-regexp": "^4.0.0", + "ignore": "^5.2.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1389,9 +1410,9 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "node_modules/@types/node": { - "version": "20.11.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.27.tgz", - "integrity": "sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg==", + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -2162,7 +2183,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, "dependencies": { "semver": "^7.0.0" } @@ -3081,7 +3101,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "peer": true, "engines": { "node": ">=10" }, @@ -3144,6 +3163,17 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-compat-utils": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz", + "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==", + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, "node_modules/eslint-config-prettier": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", @@ -3197,6 +3227,25 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-plugin-es-x": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz", + "integrity": "sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.6.0", + "eslint-compat-utils": "^0.1.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, "node_modules/eslint-plugin-import": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", @@ -3288,10 +3337,45 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/eslint-plugin-n": { + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", + "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "builtins": "^5.0.1", + "eslint-plugin-es-x": "^7.5.0", + "get-tsconfig": "^4.7.0", + "globals": "^13.24.0", + "ignore": "^5.2.4", + "is-builtin-module": "^3.2.1", + "is-core-module": "^2.12.1", + "minimatch": "^3.1.2", + "resolve": "^1.22.2", + "semver": "^7.5.3" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-no-unsanitized": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.2.tgz", + "integrity": "sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==", + "peerDependencies": { + "eslint": "^6 || ^7 || ^8" + } + }, "node_modules/eslint-plugin-react": { - "version": "7.34.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.0.tgz", - "integrity": "sha512-MeVXdReleBTdkz/bvcQMSnCXGi+c9kvy51IpinjnJgutl3YTHWsDdke7Z1ufZpGfDG8xduBDKyjtB9JH1eBKIQ==", + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", "dependencies": { "array-includes": "^3.1.7", "array.prototype.findlast": "^1.2.4", @@ -3365,6 +3449,25 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-security": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.1.tgz", + "integrity": "sha512-7cspIGj7WTfR3EhaILzAPcfCo5R9FbeWvbgsPYWivSurTBKW88VQxtP3c4aWMG9Hz/GfJlJVdXEJ3c8LqS+u2w==", + "dependencies": { + "safe-regex": "^2.1.1" + } + }, + "node_modules/eslint-plugin-sonarjs": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.24.0.tgz", + "integrity": "sha512-87zp50mbbNrSTuoEOebdRQBPa0mdejA5UEjyuScyIw8hEpEjfWP89Qhkq5xVZfVyVSRQKZc9alVm7yRKQvvUmg==", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/eslint-plugin-unicorn": { "version": "51.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz", @@ -3531,6 +3634,17 @@ "node": ">=8" } }, + "node_modules/eslint-plugin-xss": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-xss/-/eslint-plugin-xss-0.1.12.tgz", + "integrity": "sha512-L5oYaD//ZE7fKNtWUfVgYTRW19jrZlvaHe2swyFLxXQ5pwVQLivi5m92rtXd/ww8yqg4Drasqyi0hlBmhf9YQg==", + "dependencies": { + "requireindex": "~1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -4125,6 +4239,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -9734,6 +9859,14 @@ "node": ">=0.10.0" } }, + "node_modules/requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==", + "engines": { + "node": ">=0.10.5" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -9759,6 +9892,14 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -9885,6 +10026,14 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", diff --git a/package.json b/package.json index 7a2df0e..f9e2747 100644 --- a/package.json +++ b/package.json @@ -10,25 +10,32 @@ "lint": "prettier --check .", "pre-commit": "lint-staged", "prepare": "husky", - "semantic-release": "semantic-release" + "semantic-release": "semantic-release", + "type-check": "tsc --pretty --noEmit" }, "bugs": "https://github.com/capitnflam/eslint-plugin/issues", "dependencies": { + "@eslint-community/eslint-plugin-eslint-comments": "4.1.0", "@typescript-eslint/eslint-plugin": "7.2.0", "@typescript-eslint/parser": "7.2.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "2.29.1", "eslint-plugin-jsx-a11y": "6.8.0", - "eslint-plugin-react": "7.34.0", + "eslint-plugin-n": "16.6.2", + "eslint-plugin-no-unsanitized": "4.0.2", + "eslint-plugin-react": "7.34.1", "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-unicorn": "51.0.1" + "eslint-plugin-security": "2.1.1", + "eslint-plugin-sonarjs": "0.24.0", + "eslint-plugin-unicorn": "51.0.1", + "eslint-plugin-xss": "0.1.12" }, "devDependencies": { "@commitlint/cli": "19.2.0", "@commitlint/config-conventional": "19.1.0", "@commitlint/types": "19.0.3", "@types/eslint": "8.56.5", - "@types/node": "20.11.27", + "@types/node": "20.11.28", "husky": "9.0.11", "lint-staged": "15.2.2", "prettier": "3.2.5", diff --git a/src/configs/node.ts b/src/configs/node.ts new file mode 100644 index 0000000..141dfb7 --- /dev/null +++ b/src/configs/node.ts @@ -0,0 +1,6 @@ +import { type ESLintConfig } from '../types' + +export const node: ESLintConfig = { + plugins: ['@flaminc'], + extends: ['plugin:n/recommended'], +} diff --git a/src/configs/react.ts b/src/configs/react.ts index c16a139..78d4d51 100644 --- a/src/configs/react.ts +++ b/src/configs/react.ts @@ -3,11 +3,12 @@ import { type ESLintConfig } from '../types' export const react: ESLintConfig = { plugins: ['@flaminc'], extends: [ - 'plugin:@flaminc/recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime', 'plugin:react-hooks/recommended', 'plugin:jsx-a11y/recommended', + 'plugin:xss/recommended', + 'plugin:no-unsanitized/DOM', ], settings: { react: { diff --git a/src/configs/recommended.ts b/src/configs/recommended.ts index 1d8e709..ef710e9 100644 --- a/src/configs/recommended.ts +++ b/src/configs/recommended.ts @@ -4,11 +4,14 @@ export const recommended: ESLintConfig = { plugins: ['@flaminc', '@typescript-eslint'], extends: [ 'eslint:recommended', + 'plugin:@eslint-community/eslint-comments/recommended', 'plugin:@typescript-eslint/recommended-type-checked', 'plugin:@typescript-eslint/stylistic-type-checked', 'plugin:import/recommended', 'plugin:import/typescript', 'plugin:unicorn/recommended', + 'plugin:sonarjs/recommended', + 'plugin:security/recommended-legacy', 'prettier', ], parser: '@typescript-eslint/parser', diff --git a/src/index.ts b/src/index.ts index 251b685..4b91693 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,11 +2,13 @@ import { type ESLint } from 'eslint' import { name, version } from '../package.json' +import { node } from './configs/node' import { react } from './configs/react' import { recommended } from './configs/recommended' const plugin: ESLint.Plugin = { configs: { + node, react, recommended, },