From f3b1e505a0c1606b530500af744c5f102ee15bf3 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 28 Jun 2024 18:47:01 +0200 Subject: [PATCH 1/6] Add typescript guideline and typescript-specific eslint plugins and fix issues --- .eslintrc.yaml | 129 +++++++++++++ .../development/hacking-on-gitea.en-us.md | 16 ++ package-lock.json | 176 ++++++------------ package.json | 2 + tests/e2e/example.test.e2e.ts | 24 +-- tests/e2e/utils_e2e.ts | 4 +- 6 files changed, 216 insertions(+), 135 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 55a0f556fc71a..f673d230efbb6 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -25,6 +25,7 @@ plugins: - "@eslint-community/eslint-plugin-eslint-comments" - "@stylistic/eslint-plugin-js" - eslint-plugin-array-func + - eslint-plugin-deprecation - eslint-plugin-github - eslint-plugin-i - eslint-plugin-no-jquery @@ -130,6 +131,134 @@ overrides: plugins: - eslint-plugin-playwright extends: plugin:playwright/recommended + - files: ["**/*.ts"] + plugins: + - "@typescript-eslint/eslint-plugin" + rules: + "@typescript-eslint/adjacent-overload-signatures": [0] + "@typescript-eslint/array-type": [0] + "@typescript-eslint/await-thenable": [2] + "@typescript-eslint/ban-ts-comment": [2, {'ts-expect-error': false, 'ts-ignore': true, 'ts-nocheck': false, 'ts-check': false}] + "@typescript-eslint/ban-tslint-comment": [0] + "@typescript-eslint/ban-types": [2, {extendDefaults: true, types: {Function: false}}] + "@typescript-eslint/class-literal-property-style": [0] + "@typescript-eslint/class-methods-use-this": [0] + "@typescript-eslint/consistent-generic-constructors": [0] + "@typescript-eslint/consistent-indexed-object-style": [0] + "@typescript-eslint/consistent-return": [0] + "@typescript-eslint/consistent-type-assertions": [2, {assertionStyle: as, objectLiteralTypeAssertions: allow}] + "@typescript-eslint/consistent-type-definitions": [2, type] + "@typescript-eslint/consistent-type-exports": [2, {fixMixedExportsWithInlineTypeSpecifier: false}] + "@typescript-eslint/consistent-type-imports": [2, {prefer: type-imports, fixStyle: separate-type-imports, disallowTypeAnnotations: true}] + "@typescript-eslint/default-param-last": [0] + "@typescript-eslint/dot-notation": [0] + "@typescript-eslint/explicit-function-return-type": [0] + "@typescript-eslint/explicit-member-accessibility": [0] + "@typescript-eslint/explicit-module-boundary-types": [0] + "@typescript-eslint/init-declarations": [0] + "@typescript-eslint/max-params": [0] + "@typescript-eslint/member-ordering": [0] + "@typescript-eslint/method-signature-style": [0] + "@typescript-eslint/naming-convention": [0] + "@typescript-eslint/no-array-constructor": [2] + "@typescript-eslint/no-array-delete": [2] + "@typescript-eslint/no-base-to-string": [0] + "@typescript-eslint/no-confusing-non-null-assertion": [2] + "@typescript-eslint/no-confusing-void-expression": [0] + "@typescript-eslint/no-dupe-class-members": [0] + "@typescript-eslint/no-duplicate-enum-values": [2] + "@typescript-eslint/no-duplicate-type-constituents": [2, {ignoreUnions: true}] + "@typescript-eslint/no-dynamic-delete": [0] + "@typescript-eslint/no-empty-function": [0] + "@typescript-eslint/no-empty-interface": [0] + "@typescript-eslint/no-explicit-any": [0] + "@typescript-eslint/no-extra-non-null-assertion": [2] + "@typescript-eslint/no-extraneous-class": [0] + "@typescript-eslint/no-floating-promises": [0] + "@typescript-eslint/no-for-in-array": [2] + "@typescript-eslint/no-implied-eval": [2] + "@typescript-eslint/no-import-type-side-effects": [0] # dupe with consistent-type-imports + "@typescript-eslint/no-inferrable-types": [0] + "@typescript-eslint/no-invalid-this": [0] + "@typescript-eslint/no-invalid-void-type": [0] + "@typescript-eslint/no-loop-func": [0] + "@typescript-eslint/no-loss-of-precision": [2] + "@typescript-eslint/no-magic-numbers": [0] + "@typescript-eslint/no-meaningless-void-operator": [0] + "@typescript-eslint/no-misused-new": [2] + "@typescript-eslint/no-misused-promises": [2, {checksVoidReturn: {attributes: false, arguments: false}}] + "@typescript-eslint/no-mixed-enums": [0] + "@typescript-eslint/no-namespace": [2] + "@typescript-eslint/no-non-null-asserted-nullish-coalescing": [0] + "@typescript-eslint/no-non-null-asserted-optional-chain": [2] + "@typescript-eslint/no-non-null-assertion": [0] + "@typescript-eslint/no-redeclare": [0] + "@typescript-eslint/no-redundant-type-constituents": [2] + "@typescript-eslint/no-require-imports": [0] + "@typescript-eslint/no-restricted-imports": [0] + "@typescript-eslint/no-shadow": [0] + "@typescript-eslint/no-this-alias": [2] + "@typescript-eslint/no-unnecessary-boolean-literal-compare": [0] + "@typescript-eslint/no-unnecessary-condition": [0] + "@typescript-eslint/no-unnecessary-qualifier": [0] + "@typescript-eslint/no-unnecessary-template-expression": [0] + "@typescript-eslint/no-unnecessary-type-arguments": [0] + "@typescript-eslint/no-unnecessary-type-assertion": [2, typesToIgnore: [HTMLElement]] + "@typescript-eslint/no-unnecessary-type-constraint": [2] + "@typescript-eslint/no-unsafe-argument": [0] + "@typescript-eslint/no-unsafe-assignment": [0] + "@typescript-eslint/no-unsafe-call": [0] + "@typescript-eslint/no-unsafe-declaration-merging": [2] + "@typescript-eslint/no-unsafe-enum-comparison": [2] + "@typescript-eslint/no-unsafe-member-access": [0] + "@typescript-eslint/no-unsafe-return": [0] + "@typescript-eslint/no-unsafe-unary-minus": [2] + "@typescript-eslint/no-unused-expressions": [0] + "@typescript-eslint/no-unused-vars": [2, {vars: all, args: all, caughtErrors: all, ignoreRestSiblings: false, argsIgnorePattern: ^_, varsIgnorePattern: "^_[^_]*$", caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_}] + "@typescript-eslint/no-use-before-define": [0] + "@typescript-eslint/no-useless-constructor": [0] + "@typescript-eslint/no-useless-empty-export": [0] + "@typescript-eslint/no-var-requires": [2] + "@typescript-eslint/non-nullable-type-assertion-style": [0] + "@typescript-eslint/only-throw-error": [2] + "@typescript-eslint/parameter-properties": [0] + "@typescript-eslint/prefer-as-const": [2] + "@typescript-eslint/prefer-destructuring": [0] + "@typescript-eslint/prefer-enum-initializers": [0] + "@typescript-eslint/prefer-find": [2] + "@typescript-eslint/prefer-for-of": [2] + "@typescript-eslint/prefer-function-type": [2] + "@typescript-eslint/prefer-includes": [2] + "@typescript-eslint/prefer-literal-enum-member": [0] + "@typescript-eslint/prefer-namespace-keyword": [0] + "@typescript-eslint/prefer-nullish-coalescing": [0] + "@typescript-eslint/prefer-optional-chain": [2, {requireNullish: true}] + "@typescript-eslint/prefer-promise-reject-errors": [0] + "@typescript-eslint/prefer-readonly": [0] + "@typescript-eslint/prefer-readonly-parameter-types": [0] + "@typescript-eslint/prefer-reduce-type-parameter": [0] + "@typescript-eslint/prefer-regexp-exec": [0] + "@typescript-eslint/prefer-return-this-type": [0] + "@typescript-eslint/prefer-string-starts-ends-with": [2, {allowSingleElementEquality: always}] + "@typescript-eslint/promise-function-async": [0] + "@typescript-eslint/require-array-sort-compare": [0] + "@typescript-eslint/require-await": [2] + "@typescript-eslint/restrict-plus-operands": [2] + "@typescript-eslint/restrict-template-expressions": [0] + "@typescript-eslint/return-await": [0] + "@typescript-eslint/strict-boolean-expressions": [0] + "@typescript-eslint/switch-exhaustiveness-check": [0] + "@typescript-eslint/triple-slash-reference": [2] + "@typescript-eslint/typedef": [0] + "@typescript-eslint/unbound-method": [2] + "@typescript-eslint/unified-signatures": [2] + deprecation/deprecation: [2] + no-array-constructor: [0] + no-implied-eval: [0] + no-loss-of-precision: [0] + no-redeclare: [0] # for overloads + no-unused-vars: [0] + require-await: [0] rules: "@eslint-community/eslint-comments/disable-enable-pair": [2] diff --git a/docs/content/development/hacking-on-gitea.en-us.md b/docs/content/development/hacking-on-gitea.en-us.md index 004e803827db6..66f6607a3bb51 100644 --- a/docs/content/development/hacking-on-gitea.en-us.md +++ b/docs/content/development/hacking-on-gitea.en-us.md @@ -191,6 +191,22 @@ Before committing, make sure the linters pass: make lint-frontend ``` +## Typescript + +Gitea is in the process of migrating to type-safe Typescript. Here are some specific guidelines regarding Typescript in the codebase: + +### Use `@ts-expect-error` instead of `@ts-ignore` + +Both annotations should be avoided, but if you have to use them, use `@ts-expect-error` because it will not leave ineffective statements after the issue is fixed. + +### Use type aliases instead of interfaces + +Prefer to use type aliases because they can represent any type and are generally more flexible to use than interfaces. + +### Use explicit type imports and exports + +We use `verbatimModuleSyntax` so type imports and exports must be performed using `export type` and `import type` statements. Imports must be split from other imports from the same file which will then enable the typescript compiler to completely eliminate the statements during compilation. + ### Configuring local ElasticSearch instance Start local ElasticSearch instance using docker: diff --git a/package-lock.json b/package-lock.json index 3102d0223303b..502489e726d0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -69,11 +69,13 @@ "@stoplight/spectral-cli": "6.11.1", "@stylistic/eslint-plugin-js": "2.2.1", "@stylistic/stylelint-plugin": "2.1.2", + "@typescript-eslint/eslint-plugin": "7.14.1", "@typescript-eslint/parser": "7.14.1", "@vitejs/plugin-vue": "5.0.5", "eslint": "8.57.0", "eslint-import-resolver-typescript": "3.6.1", "eslint-plugin-array-func": "4.0.0", + "eslint-plugin-deprecation": "3.0.0", "eslint-plugin-github": "5.0.1", "eslint-plugin-i": "2.29.1", "eslint-plugin-no-jquery": "3.0.1", @@ -2370,16 +2372,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", - "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", + "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/type-utils": "7.13.1", - "@typescript-eslint/utils": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/type-utils": "7.14.1", + "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2431,7 +2434,7 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/scope-manager": { "version": "7.14.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", @@ -2449,105 +2452,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "node_modules/@typescript-eslint/type-utils": { "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", + "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.14.1", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", - "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", - "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.13.1", - "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/utils": "7.14.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2568,10 +2481,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", - "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", + "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -2581,13 +2495,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", - "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", + "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/visitor-keys": "7.13.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2609,15 +2524,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", - "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", + "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.13.1", - "@typescript-eslint/types": "7.13.1", - "@typescript-eslint/typescript-estree": "7.13.1" + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2631,12 +2547,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", - "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", + "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/types": "7.14.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2652,6 +2569,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -5513,6 +5431,22 @@ "eslint": ">=8.40.0" } }, + "node_modules/eslint-plugin-deprecation": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-deprecation/-/eslint-plugin-deprecation-3.0.0.tgz", + "integrity": "sha512-JuVLdNg/uf0Adjg2tpTyYoYaMbwQNn/c78P1HcccokvhtRphgnRjZDKmhlxbxYptppex03zO76f97DD/yQHv7A==", + "dev": true, + "license": "LGPL-3.0-or-later", + "dependencies": { + "@typescript-eslint/utils": "^7.0.0", + "ts-api-utils": "^1.3.0", + "tslib": "^2.3.1" + }, + "peerDependencies": { + "eslint": "^8.0.0", + "typescript": "^4.2.4 || ^5.0.0" + } + }, "node_modules/eslint-plugin-escompat": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/eslint-plugin-escompat/-/eslint-plugin-escompat-3.4.0.tgz", diff --git a/package.json b/package.json index ec1500fb8b0c7..e44415ee320f8 100644 --- a/package.json +++ b/package.json @@ -68,11 +68,13 @@ "@stoplight/spectral-cli": "6.11.1", "@stylistic/eslint-plugin-js": "2.2.1", "@stylistic/stylelint-plugin": "2.1.2", + "@typescript-eslint/eslint-plugin": "7.14.1", "@typescript-eslint/parser": "7.14.1", "@vitejs/plugin-vue": "5.0.5", "eslint": "8.57.0", "eslint-import-resolver-typescript": "3.6.1", "eslint-plugin-array-func": "4.0.0", + "eslint-plugin-deprecation": "3.0.0", "eslint-plugin-github": "5.0.1", "eslint-plugin-i": "2.29.1", "eslint-plugin-no-jquery": "3.0.1", diff --git a/tests/e2e/example.test.e2e.ts b/tests/e2e/example.test.e2e.ts index 32813b3934469..1689f1b8efc7e 100644 --- a/tests/e2e/example.test.e2e.ts +++ b/tests/e2e/example.test.e2e.ts @@ -7,21 +7,21 @@ test.beforeAll(async ({browser}, workerInfo) => { test('homepage', async ({page}) => { const response = await page.goto('/'); - await expect(response?.status()).toBe(200); // Status OK + expect(response?.status()).toBe(200); // Status OK await expect(page).toHaveTitle(/^Gitea: Git with a cup of tea\s*$/); await expect(page.locator('.logo')).toHaveAttribute('src', '/assets/img/logo.svg'); }); test('register', async ({page}, workerInfo) => { const response = await page.goto('/user/sign_up'); - await expect(response?.status()).toBe(200); // Status OK - await page.type('input[name=user_name]', `e2e-test-${workerInfo.workerIndex}`); - await page.type('input[name=email]', `e2e-test-${workerInfo.workerIndex}@test.com`); - await page.type('input[name=password]', 'test123test123'); - await page.type('input[name=retype]', 'test123test123'); + expect(response?.status()).toBe(200); // Status OK + await page.locator('input[name=user_name]').fill(`e2e-test-${workerInfo.workerIndex}`); + await page.locator('input[name=email]').fill(`e2e-test-${workerInfo.workerIndex}@test.com`); + await page.locator('input[name=password]').fill('test123test123'); + await page.locator('input[name=retype]').fill('test123test123'); await page.click('form button.ui.primary.button:visible'); // Make sure we routed to the home page. Else login failed. - await expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`); + expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`); await expect(page.locator('.secondary-nav span>img.ui.avatar')).toBeVisible(); await expect(page.locator('.ui.positive.message.flash-success')).toHaveText('Account was successfully created. Welcome!'); @@ -30,15 +30,15 @@ test('register', async ({page}, workerInfo) => { test('login', async ({page}, workerInfo) => { const response = await page.goto('/user/login'); - await expect(response?.status()).toBe(200); // Status OK + expect(response?.status()).toBe(200); // Status OK - await page.type('input[name=user_name]', `user2`); - await page.type('input[name=password]', `password`); + await page.locator('input[name=user_name]').fill(`user2`); + await page.locator('input[name=password]').fill(`password`); await page.click('form button.ui.primary.button:visible'); await page.waitForLoadState('networkidle'); // eslint-disable-line playwright/no-networkidle - await expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`); + expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`); save_visual(page); }); @@ -50,7 +50,7 @@ test('logged in user', async ({browser}, workerInfo) => { await page.goto('/'); // Make sure we routed to the home page. Else login failed. - await expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`); + expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`); save_visual(page); }); diff --git a/tests/e2e/utils_e2e.ts b/tests/e2e/utils_e2e.ts index 5678c9c9d0eee..14ec836600a78 100644 --- a/tests/e2e/utils_e2e.ts +++ b/tests/e2e/utils_e2e.ts @@ -14,7 +14,7 @@ export async function login_user(browser, workerInfo, user) { // Route to login page // Note: this could probably be done more quickly with a POST const response = await page.goto('/user/login'); - await expect(response?.status()).toBe(200); // Status OK + expect(response?.status()).toBe(200); // Status OK // Fill out form await page.type('input[name=user_name]', user); @@ -23,7 +23,7 @@ export async function login_user(browser, workerInfo, user) { await page.waitForLoadState('networkidle'); // eslint-disable-line playwright/no-networkidle - await expect(page.url(), {message: `Failed to login user ${user}`}).toBe(`${workerInfo.project.use.baseURL}/`); + expect(page.url(), {message: `Failed to login user ${user}`}).toBe(`${workerInfo.project.use.baseURL}/`); // Save state await context.storageState({path: `${ARTIFACTS_PATH}/state-${user}-${workerInfo.workerIndex}.json`}); From 322d2b12128811a7aab5ea59b86e09c95ba78d05 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 28 Jun 2024 18:55:46 +0200 Subject: [PATCH 2/6] remove exclusion for HTMLElement --- .eslintrc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index f673d230efbb6..146999989527c 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -203,7 +203,7 @@ overrides: "@typescript-eslint/no-unnecessary-qualifier": [0] "@typescript-eslint/no-unnecessary-template-expression": [0] "@typescript-eslint/no-unnecessary-type-arguments": [0] - "@typescript-eslint/no-unnecessary-type-assertion": [2, typesToIgnore: [HTMLElement]] + "@typescript-eslint/no-unnecessary-type-assertion": [2] "@typescript-eslint/no-unnecessary-type-constraint": [2] "@typescript-eslint/no-unsafe-argument": [0] "@typescript-eslint/no-unsafe-assignment": [0] From b5431b15729329efed8f096d4876fdd52e9d41f8 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 28 Jun 2024 21:25:09 +0200 Subject: [PATCH 3/6] doc tweaks --- docs/content/development/hacking-on-gitea.en-us.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/content/development/hacking-on-gitea.en-us.md b/docs/content/development/hacking-on-gitea.en-us.md index 66f6607a3bb51..d10c4e83f02b8 100644 --- a/docs/content/development/hacking-on-gitea.en-us.md +++ b/docs/content/development/hacking-on-gitea.en-us.md @@ -195,17 +195,17 @@ make lint-frontend Gitea is in the process of migrating to type-safe Typescript. Here are some specific guidelines regarding Typescript in the codebase: -### Use `@ts-expect-error` instead of `@ts-ignore` - -Both annotations should be avoided, but if you have to use them, use `@ts-expect-error` because it will not leave ineffective statements after the issue is fixed. - ### Use type aliases instead of interfaces Prefer to use type aliases because they can represent any type and are generally more flexible to use than interfaces. -### Use explicit type imports and exports +### Use separate type imports -We use `verbatimModuleSyntax` so type imports and exports must be performed using `export type` and `import type` statements. Imports must be split from other imports from the same file which will then enable the typescript compiler to completely eliminate the statements during compilation. +We use `verbatimModuleSyntax` so type imports and non-type imports from the same file must be split into two `import type` statements. This enables the typescript compiler to completely eliminate the type import statements during compilation. + +### Use `@ts-expect-error` instead of `@ts-ignore` + +Both annotations should be avoided, but if you have to use them, use `@ts-expect-error` because it will not leave ineffective statements after the issue is fixed. ### Configuring local ElasticSearch instance From 708d9a8df63b01fed94aa93921d8ba778528f79b Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 30 Jun 2024 19:26:25 +0200 Subject: [PATCH 4/6] move guide to guidelines-frontend.en-us.md --- .../contributing/guidelines-frontend.en-us.md | 16 ++++++++++++++++ .../development/hacking-on-gitea.en-us.md | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/content/contributing/guidelines-frontend.en-us.md b/docs/content/contributing/guidelines-frontend.en-us.md index a08098a93152b..5539532c52e84 100644 --- a/docs/content/contributing/guidelines-frontend.en-us.md +++ b/docs/content/contributing/guidelines-frontend.en-us.md @@ -79,6 +79,22 @@ We use htmx for simple interactions. You can see an example for simple interacti Although mixing different frameworks is discouraged, it should also work if the mixing is necessary and the code is well-designed and maintainable. +### Typescript + +Gitea is in the process of migrating to type-safe Typescript. Here are some specific guidelines regarding Typescript in the codebase: + +#### Use type aliases instead of interfaces + +Prefer to use type aliases because they can represent any type and are generally more flexible to use than interfaces. + +#### Use separate type imports + +We use `verbatimModuleSyntax` so type and non-type imports from the same file must be split into two `import type` statements. This enables the typescript compiler to completely eliminate the type import statements during compilation. + +#### Use `@ts-expect-error` instead of `@ts-ignore` + +Both annotations should be avoided, but if you have to use them, use `@ts-expect-error` because it will not leave ineffective statements after the issue is fixed. + ### `async` Functions Only mark a function as `async` if and only if there are `await` calls diff --git a/docs/content/development/hacking-on-gitea.en-us.md b/docs/content/development/hacking-on-gitea.en-us.md index d10c4e83f02b8..004e803827db6 100644 --- a/docs/content/development/hacking-on-gitea.en-us.md +++ b/docs/content/development/hacking-on-gitea.en-us.md @@ -191,22 +191,6 @@ Before committing, make sure the linters pass: make lint-frontend ``` -## Typescript - -Gitea is in the process of migrating to type-safe Typescript. Here are some specific guidelines regarding Typescript in the codebase: - -### Use type aliases instead of interfaces - -Prefer to use type aliases because they can represent any type and are generally more flexible to use than interfaces. - -### Use separate type imports - -We use `verbatimModuleSyntax` so type imports and non-type imports from the same file must be split into two `import type` statements. This enables the typescript compiler to completely eliminate the type import statements during compilation. - -### Use `@ts-expect-error` instead of `@ts-ignore` - -Both annotations should be avoided, but if you have to use them, use `@ts-expect-error` because it will not leave ineffective statements after the issue is fixed. - ### Configuring local ElasticSearch instance Start local ElasticSearch instance using docker: From 13b8659afb08e5063907b2a0e5c7bf7154443401 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 30 Jun 2024 19:44:15 +0200 Subject: [PATCH 5/6] Run ts lint on js, fix issues and regression --- .eslintrc.yaml | 260 +++++++++++------------ web_src/js/components/RepoActionView.vue | 4 +- web_src/js/features/repo-code.js | 4 +- web_src/js/features/repo-findfile.js | 4 +- web_src/js/features/repo-home.js | 8 +- web_src/js/utils/dom.js | 2 +- 6 files changed, 138 insertions(+), 144 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 146999989527c..f01ff892b15c0 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -13,6 +13,7 @@ parserOptions: ecmaVersion: latest project: true extraFileExtensions: [".vue"] + parser: "@typescript-eslint/parser" settings: import/extensions: [".js", ".ts"] @@ -24,6 +25,7 @@ settings: plugins: - "@eslint-community/eslint-plugin-eslint-comments" - "@stylistic/eslint-plugin-js" + - "@typescript-eslint/eslint-plugin" - eslint-plugin-array-func - eslint-plugin-deprecation - eslint-plugin-github @@ -131,134 +133,6 @@ overrides: plugins: - eslint-plugin-playwright extends: plugin:playwright/recommended - - files: ["**/*.ts"] - plugins: - - "@typescript-eslint/eslint-plugin" - rules: - "@typescript-eslint/adjacent-overload-signatures": [0] - "@typescript-eslint/array-type": [0] - "@typescript-eslint/await-thenable": [2] - "@typescript-eslint/ban-ts-comment": [2, {'ts-expect-error': false, 'ts-ignore': true, 'ts-nocheck': false, 'ts-check': false}] - "@typescript-eslint/ban-tslint-comment": [0] - "@typescript-eslint/ban-types": [2, {extendDefaults: true, types: {Function: false}}] - "@typescript-eslint/class-literal-property-style": [0] - "@typescript-eslint/class-methods-use-this": [0] - "@typescript-eslint/consistent-generic-constructors": [0] - "@typescript-eslint/consistent-indexed-object-style": [0] - "@typescript-eslint/consistent-return": [0] - "@typescript-eslint/consistent-type-assertions": [2, {assertionStyle: as, objectLiteralTypeAssertions: allow}] - "@typescript-eslint/consistent-type-definitions": [2, type] - "@typescript-eslint/consistent-type-exports": [2, {fixMixedExportsWithInlineTypeSpecifier: false}] - "@typescript-eslint/consistent-type-imports": [2, {prefer: type-imports, fixStyle: separate-type-imports, disallowTypeAnnotations: true}] - "@typescript-eslint/default-param-last": [0] - "@typescript-eslint/dot-notation": [0] - "@typescript-eslint/explicit-function-return-type": [0] - "@typescript-eslint/explicit-member-accessibility": [0] - "@typescript-eslint/explicit-module-boundary-types": [0] - "@typescript-eslint/init-declarations": [0] - "@typescript-eslint/max-params": [0] - "@typescript-eslint/member-ordering": [0] - "@typescript-eslint/method-signature-style": [0] - "@typescript-eslint/naming-convention": [0] - "@typescript-eslint/no-array-constructor": [2] - "@typescript-eslint/no-array-delete": [2] - "@typescript-eslint/no-base-to-string": [0] - "@typescript-eslint/no-confusing-non-null-assertion": [2] - "@typescript-eslint/no-confusing-void-expression": [0] - "@typescript-eslint/no-dupe-class-members": [0] - "@typescript-eslint/no-duplicate-enum-values": [2] - "@typescript-eslint/no-duplicate-type-constituents": [2, {ignoreUnions: true}] - "@typescript-eslint/no-dynamic-delete": [0] - "@typescript-eslint/no-empty-function": [0] - "@typescript-eslint/no-empty-interface": [0] - "@typescript-eslint/no-explicit-any": [0] - "@typescript-eslint/no-extra-non-null-assertion": [2] - "@typescript-eslint/no-extraneous-class": [0] - "@typescript-eslint/no-floating-promises": [0] - "@typescript-eslint/no-for-in-array": [2] - "@typescript-eslint/no-implied-eval": [2] - "@typescript-eslint/no-import-type-side-effects": [0] # dupe with consistent-type-imports - "@typescript-eslint/no-inferrable-types": [0] - "@typescript-eslint/no-invalid-this": [0] - "@typescript-eslint/no-invalid-void-type": [0] - "@typescript-eslint/no-loop-func": [0] - "@typescript-eslint/no-loss-of-precision": [2] - "@typescript-eslint/no-magic-numbers": [0] - "@typescript-eslint/no-meaningless-void-operator": [0] - "@typescript-eslint/no-misused-new": [2] - "@typescript-eslint/no-misused-promises": [2, {checksVoidReturn: {attributes: false, arguments: false}}] - "@typescript-eslint/no-mixed-enums": [0] - "@typescript-eslint/no-namespace": [2] - "@typescript-eslint/no-non-null-asserted-nullish-coalescing": [0] - "@typescript-eslint/no-non-null-asserted-optional-chain": [2] - "@typescript-eslint/no-non-null-assertion": [0] - "@typescript-eslint/no-redeclare": [0] - "@typescript-eslint/no-redundant-type-constituents": [2] - "@typescript-eslint/no-require-imports": [0] - "@typescript-eslint/no-restricted-imports": [0] - "@typescript-eslint/no-shadow": [0] - "@typescript-eslint/no-this-alias": [2] - "@typescript-eslint/no-unnecessary-boolean-literal-compare": [0] - "@typescript-eslint/no-unnecessary-condition": [0] - "@typescript-eslint/no-unnecessary-qualifier": [0] - "@typescript-eslint/no-unnecessary-template-expression": [0] - "@typescript-eslint/no-unnecessary-type-arguments": [0] - "@typescript-eslint/no-unnecessary-type-assertion": [2] - "@typescript-eslint/no-unnecessary-type-constraint": [2] - "@typescript-eslint/no-unsafe-argument": [0] - "@typescript-eslint/no-unsafe-assignment": [0] - "@typescript-eslint/no-unsafe-call": [0] - "@typescript-eslint/no-unsafe-declaration-merging": [2] - "@typescript-eslint/no-unsafe-enum-comparison": [2] - "@typescript-eslint/no-unsafe-member-access": [0] - "@typescript-eslint/no-unsafe-return": [0] - "@typescript-eslint/no-unsafe-unary-minus": [2] - "@typescript-eslint/no-unused-expressions": [0] - "@typescript-eslint/no-unused-vars": [2, {vars: all, args: all, caughtErrors: all, ignoreRestSiblings: false, argsIgnorePattern: ^_, varsIgnorePattern: "^_[^_]*$", caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_}] - "@typescript-eslint/no-use-before-define": [0] - "@typescript-eslint/no-useless-constructor": [0] - "@typescript-eslint/no-useless-empty-export": [0] - "@typescript-eslint/no-var-requires": [2] - "@typescript-eslint/non-nullable-type-assertion-style": [0] - "@typescript-eslint/only-throw-error": [2] - "@typescript-eslint/parameter-properties": [0] - "@typescript-eslint/prefer-as-const": [2] - "@typescript-eslint/prefer-destructuring": [0] - "@typescript-eslint/prefer-enum-initializers": [0] - "@typescript-eslint/prefer-find": [2] - "@typescript-eslint/prefer-for-of": [2] - "@typescript-eslint/prefer-function-type": [2] - "@typescript-eslint/prefer-includes": [2] - "@typescript-eslint/prefer-literal-enum-member": [0] - "@typescript-eslint/prefer-namespace-keyword": [0] - "@typescript-eslint/prefer-nullish-coalescing": [0] - "@typescript-eslint/prefer-optional-chain": [2, {requireNullish: true}] - "@typescript-eslint/prefer-promise-reject-errors": [0] - "@typescript-eslint/prefer-readonly": [0] - "@typescript-eslint/prefer-readonly-parameter-types": [0] - "@typescript-eslint/prefer-reduce-type-parameter": [0] - "@typescript-eslint/prefer-regexp-exec": [0] - "@typescript-eslint/prefer-return-this-type": [0] - "@typescript-eslint/prefer-string-starts-ends-with": [2, {allowSingleElementEquality: always}] - "@typescript-eslint/promise-function-async": [0] - "@typescript-eslint/require-array-sort-compare": [0] - "@typescript-eslint/require-await": [2] - "@typescript-eslint/restrict-plus-operands": [2] - "@typescript-eslint/restrict-template-expressions": [0] - "@typescript-eslint/return-await": [0] - "@typescript-eslint/strict-boolean-expressions": [0] - "@typescript-eslint/switch-exhaustiveness-check": [0] - "@typescript-eslint/triple-slash-reference": [2] - "@typescript-eslint/typedef": [0] - "@typescript-eslint/unbound-method": [2] - "@typescript-eslint/unified-signatures": [2] - deprecation/deprecation: [2] - no-array-constructor: [0] - no-implied-eval: [0] - no-loss-of-precision: [0] - no-redeclare: [0] # for overloads - no-unused-vars: [0] - require-await: [0] rules: "@eslint-community/eslint-comments/disable-enable-pair": [2] @@ -338,6 +212,123 @@ rules: "@stylistic/js/wrap-iife": [2, inside] "@stylistic/js/wrap-regex": [0] "@stylistic/js/yield-star-spacing": [2, after] + "@typescript-eslint/adjacent-overload-signatures": [0] + "@typescript-eslint/array-type": [0] + "@typescript-eslint/await-thenable": [2] + "@typescript-eslint/ban-ts-comment": [2, {'ts-expect-error': false, 'ts-ignore': true, 'ts-nocheck': false, 'ts-check': false}] + "@typescript-eslint/ban-tslint-comment": [0] + "@typescript-eslint/ban-types": [2, {extendDefaults: true, types: {Function: false}}] + "@typescript-eslint/class-literal-property-style": [0] + "@typescript-eslint/class-methods-use-this": [0] + "@typescript-eslint/consistent-generic-constructors": [0] + "@typescript-eslint/consistent-indexed-object-style": [0] + "@typescript-eslint/consistent-return": [0] + "@typescript-eslint/consistent-type-assertions": [2, {assertionStyle: as, objectLiteralTypeAssertions: allow}] + "@typescript-eslint/consistent-type-definitions": [2, type] + "@typescript-eslint/consistent-type-exports": [2, {fixMixedExportsWithInlineTypeSpecifier: false}] + "@typescript-eslint/consistent-type-imports": [2, {prefer: type-imports, fixStyle: separate-type-imports, disallowTypeAnnotations: true}] + "@typescript-eslint/default-param-last": [0] + "@typescript-eslint/dot-notation": [0] + "@typescript-eslint/explicit-function-return-type": [0] + "@typescript-eslint/explicit-member-accessibility": [0] + "@typescript-eslint/explicit-module-boundary-types": [0] + "@typescript-eslint/init-declarations": [0] + "@typescript-eslint/max-params": [0] + "@typescript-eslint/member-ordering": [0] + "@typescript-eslint/method-signature-style": [0] + "@typescript-eslint/naming-convention": [0] + "@typescript-eslint/no-array-constructor": [2] + "@typescript-eslint/no-array-delete": [2] + "@typescript-eslint/no-base-to-string": [0] + "@typescript-eslint/no-confusing-non-null-assertion": [2] + "@typescript-eslint/no-confusing-void-expression": [0] + "@typescript-eslint/no-dupe-class-members": [0] + "@typescript-eslint/no-duplicate-enum-values": [2] + "@typescript-eslint/no-duplicate-type-constituents": [2, {ignoreUnions: true}] + "@typescript-eslint/no-dynamic-delete": [0] + "@typescript-eslint/no-empty-function": [0] + "@typescript-eslint/no-empty-interface": [0] + "@typescript-eslint/no-explicit-any": [0] + "@typescript-eslint/no-extra-non-null-assertion": [2] + "@typescript-eslint/no-extraneous-class": [0] + "@typescript-eslint/no-floating-promises": [0] + "@typescript-eslint/no-for-in-array": [2] + "@typescript-eslint/no-implied-eval": [2] + "@typescript-eslint/no-import-type-side-effects": [0] # dupe with consistent-type-imports + "@typescript-eslint/no-inferrable-types": [0] + "@typescript-eslint/no-invalid-this": [0] + "@typescript-eslint/no-invalid-void-type": [0] + "@typescript-eslint/no-loop-func": [0] + "@typescript-eslint/no-loss-of-precision": [2] + "@typescript-eslint/no-magic-numbers": [0] + "@typescript-eslint/no-meaningless-void-operator": [0] + "@typescript-eslint/no-misused-new": [2] + "@typescript-eslint/no-misused-promises": [2, {checksVoidReturn: {attributes: false, arguments: false}}] + "@typescript-eslint/no-mixed-enums": [0] + "@typescript-eslint/no-namespace": [2] + "@typescript-eslint/no-non-null-asserted-nullish-coalescing": [0] + "@typescript-eslint/no-non-null-asserted-optional-chain": [2] + "@typescript-eslint/no-non-null-assertion": [0] + "@typescript-eslint/no-redeclare": [0] + "@typescript-eslint/no-redundant-type-constituents": [2] + "@typescript-eslint/no-require-imports": [0] + "@typescript-eslint/no-restricted-imports": [0] + "@typescript-eslint/no-shadow": [0] + "@typescript-eslint/no-this-alias": [0] # handled by unicorn/no-this-assignment + "@typescript-eslint/no-unnecessary-boolean-literal-compare": [0] + "@typescript-eslint/no-unnecessary-condition": [0] + "@typescript-eslint/no-unnecessary-qualifier": [0] + "@typescript-eslint/no-unnecessary-template-expression": [0] + "@typescript-eslint/no-unnecessary-type-arguments": [0] + "@typescript-eslint/no-unnecessary-type-assertion": [2] + "@typescript-eslint/no-unnecessary-type-constraint": [2] + "@typescript-eslint/no-unsafe-argument": [0] + "@typescript-eslint/no-unsafe-assignment": [0] + "@typescript-eslint/no-unsafe-call": [0] + "@typescript-eslint/no-unsafe-declaration-merging": [2] + "@typescript-eslint/no-unsafe-enum-comparison": [2] + "@typescript-eslint/no-unsafe-member-access": [0] + "@typescript-eslint/no-unsafe-return": [0] + "@typescript-eslint/no-unsafe-unary-minus": [2] + "@typescript-eslint/no-unused-expressions": [0] + "@typescript-eslint/no-unused-vars": [2, {vars: all, args: all, caughtErrors: all, ignoreRestSiblings: false, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_}] + "@typescript-eslint/no-use-before-define": [0] + "@typescript-eslint/no-useless-constructor": [0] + "@typescript-eslint/no-useless-empty-export": [0] + "@typescript-eslint/no-var-requires": [2] + "@typescript-eslint/non-nullable-type-assertion-style": [0] + "@typescript-eslint/only-throw-error": [2] + "@typescript-eslint/parameter-properties": [0] + "@typescript-eslint/prefer-as-const": [2] + "@typescript-eslint/prefer-destructuring": [0] + "@typescript-eslint/prefer-enum-initializers": [0] + "@typescript-eslint/prefer-find": [2] + "@typescript-eslint/prefer-for-of": [2] + "@typescript-eslint/prefer-function-type": [2] + "@typescript-eslint/prefer-includes": [2] + "@typescript-eslint/prefer-literal-enum-member": [0] + "@typescript-eslint/prefer-namespace-keyword": [0] + "@typescript-eslint/prefer-nullish-coalescing": [0] + "@typescript-eslint/prefer-optional-chain": [2, {requireNullish: true}] + "@typescript-eslint/prefer-promise-reject-errors": [0] + "@typescript-eslint/prefer-readonly": [0] + "@typescript-eslint/prefer-readonly-parameter-types": [0] + "@typescript-eslint/prefer-reduce-type-parameter": [0] + "@typescript-eslint/prefer-regexp-exec": [0] + "@typescript-eslint/prefer-return-this-type": [0] + "@typescript-eslint/prefer-string-starts-ends-with": [2, {allowSingleElementEquality: always}] + "@typescript-eslint/promise-function-async": [0] + "@typescript-eslint/require-array-sort-compare": [0] + "@typescript-eslint/require-await": [0] + "@typescript-eslint/restrict-plus-operands": [2] + "@typescript-eslint/restrict-template-expressions": [0] + "@typescript-eslint/return-await": [0] + "@typescript-eslint/strict-boolean-expressions": [0] + "@typescript-eslint/switch-exhaustiveness-check": [0] + "@typescript-eslint/triple-slash-reference": [2] + "@typescript-eslint/typedef": [0] + "@typescript-eslint/unbound-method": [2] + "@typescript-eslint/unified-signatures": [2] accessor-pairs: [2] array-callback-return: [2, {checkForEach: true}] array-func/avoid-reverse: [2] @@ -359,6 +350,7 @@ rules: default-case-last: [2] default-case: [0] default-param-last: [0] + deprecation/deprecation: [2] dot-notation: [0] eqeqeq: [2] for-direction: [2] @@ -450,7 +442,7 @@ rules: multiline-comment-style: [2, separate-lines] new-cap: [0] no-alert: [0] - no-array-constructor: [2] + no-array-constructor: [0] # handled by @typescript-eslint/no-array-constructor no-async-promise-executor: [0] no-await-in-loop: [0] no-bitwise: [0] @@ -494,7 +486,7 @@ rules: no-global-assign: [2] no-implicit-coercion: [2] no-implicit-globals: [0] - no-implied-eval: [2] + no-implied-eval: [0] # handled by @typescript-eslint/no-implied-eval no-import-assign: [2] no-inline-comments: [0] no-inner-declarations: [2] @@ -600,7 +592,7 @@ rules: no-lone-blocks: [2] no-lonely-if: [0] no-loop-func: [0] - no-loss-of-precision: [2] + no-loss-of-precision: [0] # handled by @typescript-eslint/no-loss-of-precision no-magic-numbers: [0] no-misleading-character-class: [2] no-multi-assign: [0] @@ -622,7 +614,7 @@ rules: no-promise-executor-return: [0] no-proto: [2] no-prototype-builtins: [2] - no-redeclare: [2] + no-redeclare: [0] # must be disabled for typescript overloads no-regex-spaces: [2] no-restricted-exports: [0] no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, location, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, self, status, statusbar, stop, toolbar, top, __dirname, __filename] @@ -655,7 +647,7 @@ rules: no-unused-expressions: [2] no-unused-labels: [2] no-unused-private-class-members: [2] - no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_, ignoreRestSiblings: false}] + no-unused-vars: [0] # handled by @typescript-eslint/no-unused-vars no-use-before-define: [2, {functions: false, classes: true, variables: true, allowNamedExports: true}] no-use-extend-native/no-use-extend-native: [2] no-useless-backreference: [2] @@ -770,7 +762,7 @@ rules: regexp/unicode-escape: [0] regexp/use-ignore-case: [0] require-atomic-updates: [0] - require-await: [0] + require-await: [0] # handled by @typescript-eslint/require-await require-unicode-regexp: [0] require-yield: [2] sonarjs/cognitive-complexity: [0] diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index 97dc0d950f01e..e751018f90be3 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -89,7 +89,9 @@ const sfc = { // load job data and then auto-reload periodically // need to await first loadJob so this.currentJobStepsStates is initialized and can be used in hashChangeListener await this.loadJob(); - this.intervalID = setInterval(this.loadJob, 1000); + this.intervalID = setInterval(() => { + this.loadJob(); + }, 1000); document.body.addEventListener('click', this.closeDropdown); this.hashChangeListener(); window.addEventListener('hashchange', this.hashChangeListener); diff --git a/web_src/js/features/repo-code.js b/web_src/js/features/repo-code.js index f0f4ead125f73..658fa7e11c608 100644 --- a/web_src/js/features/repo-code.js +++ b/web_src/js/features/repo-code.js @@ -153,7 +153,7 @@ export function initRepoCodeView() { }); $(window).on('hashchange', () => { - let m = rangeAnchorRegex.exec(window.location.hash.match); + let m = rangeAnchorRegex.exec(window.location.hash); const $linesEls = $(getLineEls()); let $first; if (m) { @@ -170,7 +170,7 @@ export function initRepoCodeView() { return; } } - m = singleAnchorRegex.exec(window.location.hash.match); + m = singleAnchorRegex.exec(window.location.hash); if (m) { $first = $linesEls.filter(`[rel=L${m[2]}]`); if ($first.length) { diff --git a/web_src/js/features/repo-findfile.js b/web_src/js/features/repo-findfile.js index 945eeeceffe71..828acfa65c8ac 100644 --- a/web_src/js/features/repo-findfile.js +++ b/web_src/js/features/repo-findfile.js @@ -55,8 +55,8 @@ export function filterRepoFilesWeighted(files, filter) { const filterLower = filter.toLowerCase(); // TODO: for large repo, this loop could be slow, maybe there could be one more limit: // ... && filterResult.length < threshold * 20, wait for more feedbacks - for (let i = 0; i < files.length; i++) { - const res = strSubMatch(files[i], filterLower); + for (const file of files) { + const res = strSubMatch(file, filterLower); if (res.length > 1) { // length==1 means unmatched, >1 means having matched sub strings filterResult.push({matchResult: res, matchWeight: calcMatchedWeight(res)}); } diff --git a/web_src/js/features/repo-home.js b/web_src/js/features/repo-home.js index f48c1b1bb303e..3a8e41bde185f 100644 --- a/web_src/js/features/repo-home.js +++ b/web_src/js/features/repo-home.js @@ -102,16 +102,16 @@ export function initRepoTopicBar() { if (res.topics) { let found = false; - for (let i = 0; i < res.topics.length; i++) { + for (const {topic_name} of res.topics) { // skip currently added tags - if (current_topics.includes(res.topics[i].topic_name)) { + if (current_topics.includes(topic_name)) { continue; } - if (res.topics[i].topic_name.toLowerCase() === query.toLowerCase()) { + if (topic_name.toLowerCase() === query.toLowerCase()) { found_query = true; } - formattedResponse.results.push({description: res.topics[i].topic_name, 'data-value': res.topics[i].topic_name}); + formattedResponse.results.push({description: topic_name, 'data-value': topic_name}); found = true; } formattedResponse.success = found; diff --git a/web_src/js/utils/dom.js b/web_src/js/utils/dom.js index 9bdb2332362a8..8d75c724ded80 100644 --- a/web_src/js/utils/dom.js +++ b/web_src/js/utils/dom.js @@ -270,7 +270,7 @@ export function replaceTextareaSelection(textarea, text) { textarea.contentEditable = 'true'; try { - success = document.execCommand('insertText', false, text); + success = document.execCommand('insertText', false, text); // eslint-disable-line deprecation/deprecation } catch { success = false; } From e9e627b8a2f3561650d44500e23d87db1f66ba6c Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 30 Jun 2024 19:59:09 +0200 Subject: [PATCH 6/6] add comment --- .eslintrc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index f01ff892b15c0..293d435b11b9d 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -13,7 +13,7 @@ parserOptions: ecmaVersion: latest project: true extraFileExtensions: [".vue"] - parser: "@typescript-eslint/parser" + parser: "@typescript-eslint/parser" # for vue plugin - https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser settings: import/extensions: [".js", ".ts"]