mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 05:25:15 +01:00 
			
		
		
		
	Add typescript guideline and typescript-specific eslint plugins and fix issues (#31521)
1. Add some general guidelines how to write our typescript code 2. Add `@typescript-eslint/eslint-plugin`, general typescript rules 3. Add `eslint-plugin-deprecation` to detect deprecated code 4. Fix all new lint issues that came up
This commit is contained in:
		
							parent
							
								
									b270b30aeb
								
							
						
					
					
						commit
						2c92c7c522
					
				
							
								
								
									
										133
									
								
								.eslintrc.yaml
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								.eslintrc.yaml
									
									
									
									
									
								
							@ -13,6 +13,7 @@ parserOptions:
 | 
			
		||||
  ecmaVersion: latest
 | 
			
		||||
  project: true
 | 
			
		||||
  extraFileExtensions: [".vue"]
 | 
			
		||||
  parser: "@typescript-eslint/parser" # for vue plugin - https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
 | 
			
		||||
 | 
			
		||||
settings:
 | 
			
		||||
  import/extensions: [".js", ".ts"]
 | 
			
		||||
@ -24,7 +25,9 @@ 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
 | 
			
		||||
  - eslint-plugin-i
 | 
			
		||||
  - eslint-plugin-no-jquery
 | 
			
		||||
@ -209,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]
 | 
			
		||||
@ -230,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]
 | 
			
		||||
@ -321,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]
 | 
			
		||||
@ -365,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]
 | 
			
		||||
@ -471,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]
 | 
			
		||||
@ -493,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]
 | 
			
		||||
@ -526,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]
 | 
			
		||||
@ -641,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]
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										230
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										230
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -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,7 +2452,35 @@
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
 | 
			
		||||
    "node_modules/@typescript-eslint/type-utils": {
 | 
			
		||||
      "version": "7.14.1",
 | 
			
		||||
      "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/typescript-estree": "7.14.1",
 | 
			
		||||
        "@typescript-eslint/utils": "7.14.1",
 | 
			
		||||
        "debug": "^4.3.4",
 | 
			
		||||
        "ts-api-utils": "^1.3.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^18.18.0 || >=20.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "eslint": "^8.56.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "typescript": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "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==",
 | 
			
		||||
@ -2463,7 +2494,7 @@
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
 | 
			
		||||
    "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==",
 | 
			
		||||
@ -2492,7 +2523,30 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
 | 
			
		||||
    "node_modules/@typescript-eslint/utils": {
 | 
			
		||||
      "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.14.1",
 | 
			
		||||
        "@typescript-eslint/types": "7.14.1",
 | 
			
		||||
        "@typescript-eslint/typescript-estree": "7.14.1"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^18.18.0 || >=20.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "eslint": "^8.56.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/visitor-keys": {
 | 
			
		||||
      "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==",
 | 
			
		||||
@ -2510,148 +2564,12 @@
 | 
			
		||||
        "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",
 | 
			
		||||
        "debug": "^4.3.4",
 | 
			
		||||
        "ts-api-utils": "^1.3.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^18.18.0 || >=20.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "eslint": "^8.56.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "typescript": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "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==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^18.18.0 || >=20.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "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==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/types": "7.13.1",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "7.13.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/utils": {
 | 
			
		||||
      "version": "7.13.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz",
 | 
			
		||||
      "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "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"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^18.18.0 || >=20.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "eslint": "^8.56.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "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==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/types": "7.13.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/visitor-keys/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"
 | 
			
		||||
      },
 | 
			
		||||
@ -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",
 | 
			
		||||
 | 
			
		||||
@ -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",
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -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`});
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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)});
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user