diff --git a/.eslintrc.yaml b/.eslintrc.yaml
index ff62d9cc93..3a906c44cd 100644
--- a/.eslintrc.yaml
+++ b/.eslintrc.yaml
@@ -11,13 +11,8 @@ parserOptions:
 plugins:
   - eslint-plugin-unicorn
   - eslint-plugin-import
-  - eslint-plugin-vue
-  - eslint-plugin-html
   - eslint-plugin-jquery
 
-extends:
-  - plugin:vue/recommended
-
 env:
   es2022: true
   node: true
@@ -25,18 +20,11 @@ env:
 globals:
   __webpack_public_path__: true
 
-settings:
-  html/html-extensions: [".tmpl"]
-
 overrides:
-  - files: ["web_src/**/*.js", "web_src/**/*.vue", "templates/**/*.tmpl"]
+  - files: ["web_src/**/*.js", "docs/**/*.js"]
     env:
       browser: true
       node: false
-  - files: ["templates/**/*.tmpl"]
-    rules:
-      no-tabs: [0]
-      indent: [2, tab, {SwitchCase: 1}]
   - files: ["web_src/**/*worker.js"]
     env:
       worker: true
@@ -502,11 +490,6 @@ rules:
   use-isnan: [2]
   valid-typeof: [2, {requireStringLiterals: true}]
   vars-on-top: [0]
-  vue/attributes-order: [0]
-  vue/component-definition-name-casing: [0]
-  vue/html-closing-bracket-spacing: [0]
-  vue/max-attributes-per-line: [0]
-  vue/one-component-per-file: [0]
   wrap-iife: [2, inside]
   wrap-regex: [0]
   yield-star-spacing: [2, after]
diff --git a/Makefile b/Makefile
index 5536788613..5d1b54e852 100644
--- a/Makefile
+++ b/Makefile
@@ -310,7 +310,7 @@ lint: lint-frontend lint-backend
 
 .PHONY: lint-frontend
 lint-frontend: node_modules
-	npx eslint --color --max-warnings=0 web_src/js build templates *.config.js docs/assets/js
+	npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js
 	npx stylelint --color --max-warnings=0 web_src/less
 	npx spectral lint -q -F hint $(SWAGGER_SPEC)
 
diff --git a/package-lock.json b/package-lock.json
index 5032e50fc5..605134201e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -47,7 +47,6 @@
         "@happy-dom/jest-environment": "4.0.1",
         "@stoplight/spectral-cli": "6.4.1",
         "eslint": "8.15.0",
-        "eslint-plugin-html": "6.2.0",
         "eslint-plugin-import": "2.26.0",
         "eslint-plugin-jquery": "1.5.1",
         "eslint-plugin-unicorn": "42.0.0",
@@ -4839,18 +4838,6 @@
         "node": ">=10.13.0"
       }
     },
-    "node_modules/entities": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
-      "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.12"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/entities?sponsor=1"
-      }
-    },
     "node_modules/envinfo": {
       "version": "7.8.1",
       "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
@@ -5231,15 +5218,6 @@
         "ms": "^2.1.1"
       }
     },
-    "node_modules/eslint-plugin-html": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-6.2.0.tgz",
-      "integrity": "sha512-vi3NW0E8AJombTvt8beMwkL1R/fdRWl4QSNRNMhVQKWm36/X0KF0unGNAY4mqUF06mnwVWZcIcerrCnfn9025g==",
-      "dev": true,
-      "dependencies": {
-        "htmlparser2": "^7.1.2"
-      }
-    },
     "node_modules/eslint-plugin-import": {
       "version": "2.26.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
@@ -6262,25 +6240,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/htmlparser2": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
-      "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
-      "dev": true,
-      "funding": [
-        "https://github.com/fb55/htmlparser2?sponsor=1",
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/fb55"
-        }
-      ],
-      "dependencies": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^4.2.2",
-        "domutils": "^2.8.0",
-        "entities": "^3.0.1"
-      }
-    },
     "node_modules/http-basic": {
       "version": "8.1.3",
       "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz",
@@ -16221,12 +16180,6 @@
         "tapable": "^2.2.0"
       }
     },
-    "entities": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
-      "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
-      "dev": true
-    },
     "envinfo": {
       "version": "7.8.1",
       "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
@@ -16519,15 +16472,6 @@
         }
       }
     },
-    "eslint-plugin-html": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-6.2.0.tgz",
-      "integrity": "sha512-vi3NW0E8AJombTvt8beMwkL1R/fdRWl4QSNRNMhVQKWm36/X0KF0unGNAY4mqUF06mnwVWZcIcerrCnfn9025g==",
-      "dev": true,
-      "requires": {
-        "htmlparser2": "^7.1.2"
-      }
-    },
     "eslint-plugin-import": {
       "version": "2.26.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
@@ -17317,18 +17261,6 @@
       "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==",
       "dev": true
     },
-    "htmlparser2": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
-      "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
-      "dev": true,
-      "requires": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^4.2.2",
-        "domutils": "^2.8.0",
-        "entities": "^3.0.1"
-      }
-    },
     "http-basic": {
       "version": "8.1.3",
       "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz",
diff --git a/package.json b/package.json
index b55da05b3d..afc8d2a374 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,6 @@
     "@happy-dom/jest-environment": "4.0.1",
     "@stoplight/spectral-cli": "6.4.1",
     "eslint": "8.15.0",
-    "eslint-plugin-html": "6.2.0",
     "eslint-plugin-import": "2.26.0",
     "eslint-plugin-jquery": "1.5.1",
     "eslint-plugin-unicorn": "42.0.0",
diff --git a/templates/base/head_script.tmpl b/templates/base/head_script.tmpl
index 2f74b959e2..48a3df693a 100644
--- a/templates/base/head_script.tmpl
+++ b/templates/base/head_script.tmpl
@@ -4,7 +4,6 @@ If you are customizing Gitea, please do not change this file.
 If you introduce mistakes in it, Gitea JavaScript code wouldn't run correctly.
 */}}
 <script>
-	<!-- /* eslint-disable */ -->
 	window.addEventListener('error', function(e) {window._globalHandlerErrors=window._globalHandlerErrors||[]; window._globalHandlerErrors.push(e);});
 	window.config = {
 		appVer: '{{AppVer}}',
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl
index 60fe667a54..be2c8f0c0e 100644
--- a/templates/repo/issue/view_content/pull.tmpl
+++ b/templates/repo/issue/view_content/pull.tmpl
@@ -340,7 +340,6 @@
 						{{end}}
 						<div class="ui divider"></div>
 						<script>
-							<!-- /* eslint-disable */ -->
 							(() => {
 								const defaultMergeTitle = {{.DefaultMergeMessage}};
 								const defaultSquashMergeTitle = {{.DefaultSquashMergeMessage}};
diff --git a/web_src/js/components/.eslintrc.yaml b/web_src/js/components/.eslintrc.yaml
new file mode 100644
index 0000000000..e19bd06637
--- /dev/null
+++ b/web_src/js/components/.eslintrc.yaml
@@ -0,0 +1,16 @@
+plugins:
+  - eslint-plugin-vue
+
+extends:
+  - ../../../.eslintrc.yaml
+  - plugin:vue/recommended
+
+env:
+  browser: true
+
+rules:
+  vue/attributes-order: [0]
+  vue/component-definition-name-casing: [0]
+  vue/html-closing-bracket-spacing: [0]
+  vue/max-attributes-per-line: [0]
+  vue/one-component-per-file: [0]