✨ Use guesslang to detect the language

This commit is contained in:
landaiqing committed 2025-06-19 16:55:02 +08:00
1 parent f2894b2a89
commit 25858cb42b
12 files changed
+724 -790

No files matched your search

+208 -208
View File
@@ -21,7 +21,7 @@
"@codemirror/lang-less": "^6.0.2",
"@codemirror/lang-lezer": "^6.0.1",
"@codemirror/lang-liquid": "^6.2.3",
"@codemirror/lang-markdown": "^6.3.2",
"@codemirror/lang-markdown": "^6.3.3",
"@codemirror/lang-php": "^6.0.1",
"@codemirror/lang-python": "^6.2.1",
"@codemirror/lang-rust": "^6.0.1",
@@ -37,7 +37,7 @@
"@codemirror/lint": "^6.8.5",
"@codemirror/search": "^6.5.11",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.37.1",
"@codemirror/view": "^6.37.2",
"@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.2",
"@types/uuid": "^10.0.0",
@@ -48,24 +48,24 @@
"colors-named-hex": "^1.0.2",
"hsl-matcher": "^1.2.4",
"lezer": "^0.13.5",
"pinia": "^3.0.2",
"sass": "^1.89.1",
"pinia": "^3.0.3",
"sass": "^1.89.2",
"uuid": "^11.1.0",
"vue": "^3.5.16",
"vue-i18n": "^11.1.5",
"vue": "^3.5.17",
"vue-i18n": "^11.1.6",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@eslint/js": "^9.28.0",
"@eslint/js": "^9.29.0",
"@lezer/generator": "^1.7.3",
"@types/node": "^22.15.29",
"@types/node": "^24.0.3",
"@vitejs/plugin-vue": "^5.2.4",
"@wailsio/runtime": "latest",
"eslint": "^9.28.0",
"eslint-plugin-vue": "^10.1.0",
"eslint": "^9.29.0",
"eslint-plugin-vue": "^10.2.0",
"globals": "^16.2.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.33.1",
"typescript-eslint": "^8.34.1",
"unplugin-vue-components": "^28.7.0",
"vite": "^6.3.5",
"vue-eslint-parser": "^10.1.3",
@@ -91,12 +91,12 @@
}
},
"node_modules/@babel/parser": {
"version": "7.27.2",
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.2.tgz",
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
"version": "7.27.5",
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.5.tgz",
"integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.27.1"
"@babel/types": "^7.27.3"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -106,9 +106,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.1.tgz",
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
"version": "7.27.6",
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.6.tgz",
"integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@@ -286,9 +286,9 @@
}
},
"node_modules/@codemirror/lang-markdown": {
"version": "6.3.2",
"resolved": "https://registry.npmmirror.com/@codemirror/lang-markdown/-/lang-markdown-6.3.2.tgz",
"integrity": "sha512-c/5MYinGbFxYl4itE9q/rgN/sMTjOr8XL5OWnC+EaRMLfCbVUmmubTJfdgpfcSS2SCaT7b+Q+xi3l6CgoE+BsA==",
"version": "6.3.3",
"resolved": "https://registry.npmmirror.com/@codemirror/lang-markdown/-/lang-markdown-6.3.3.tgz",
"integrity": "sha512-1fn1hQAPWlSSMCvnF810AkhWpNLkJpl66CRfIy3vVl20Sl4NwChkorCHqpMtNbXr1EuMJsrDnhEpjZxKZ2UX3A==",
"license": "MIT",
"dependencies": {
"@codemirror/autocomplete": "^6.7.1",
@@ -503,9 +503,9 @@
}
},
"node_modules/@codemirror/view": {
"version": "6.37.1",
"resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.37.1.tgz",
"integrity": "sha512-Qy4CAUwngy/VQkEz0XzMKVRcckQuqLYWKqVpDDDghBe5FSXSqfVrJn49nw3ePZHxRUz4nRmb05Lgi+9csWo4eg==",
"version": "6.37.2",
"resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.37.2.tgz",
"integrity": "sha512-XD3LdgQpxQs5jhOOZ2HRVT+Rj59O4Suc7g2ULvZ+Yi8eCkickrkZ5JFuoDhs2ST1mNI5zSsNYgR3NGa4OUrbnw==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.5.0",
@@ -982,9 +982,9 @@
}
},
"node_modules/@eslint/config-array": {
"version": "0.20.0",
"resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.20.0.tgz",
"integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
"version": "0.20.1",
"resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.20.1.tgz",
"integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1057,9 +1057,9 @@
}
},
"node_modules/@eslint/js": {
"version": "9.28.0",
"resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.28.0.tgz",
"integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==",
"version": "9.29.0",
"resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.29.0.tgz",
"integrity": "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1160,13 +1160,13 @@
}
},
"node_modules/@intlify/core-base": {
"version": "11.1.5",
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-11.1.5.tgz",
"integrity": "sha512-xGRkISwV/2Trqb8yVQevlHm5roaQqy+75qwUzEQrviaQF0o4c5VDhjBW7WEGEoKFx09HSgq7NkvK/DAyuerTDg==",
"version": "11.1.6",
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-11.1.6.tgz",
"integrity": "sha512-gfMLnoWGiQkA1BwK6Qbrog/e3I6Lnkhqk08XObJb0lMq6sLG1Ggl2MazVaMfGnv/E1Td8pCS5UwR54Ys+fOxmQ==",
"license": "MIT",
"dependencies": {
"@intlify/message-compiler": "11.1.5",
"@intlify/shared": "11.1.5"
"@intlify/message-compiler": "11.1.6",
"@intlify/shared": "11.1.6"
},
"engines": {
"node": ">= 16"
@@ -1176,12 +1176,12 @@
}
},
"node_modules/@intlify/message-compiler": {
"version": "11.1.5",
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-11.1.5.tgz",
"integrity": "sha512-YLSBbjD7qUdShe3ZAat9Hnf9E8FRpN6qmNFD/x5Xg5JVXjsks0kJ90Zj6aAuyoppJQA/YJdWZ8/bB7k3dg2TjQ==",
"version": "11.1.6",
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-11.1.6.tgz",
"integrity": "sha512-w0LYo5sqgQZF3vEmjLlx+5PYk5EEiB+uigsBkka/DKoAIH2c5xlXcjAxhTgSw35Vrck+GOGriahFsfbHL+ZjPw==",
"license": "MIT",
"dependencies": {
"@intlify/shared": "11.1.5",
"@intlify/shared": "11.1.6",
"source-map-js": "^1.0.2"
},
"engines": {
@@ -1192,9 +1192,9 @@
}
},
"node_modules/@intlify/shared": {
"version": "11.1.5",
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-11.1.5.tgz",
"integrity": "sha512-+I4vRzHm38VjLr/CAciEPJhGYFzWWW4HMTm+6H3WqknXLh0ozNX9oC8ogMUwTSXYR/wGUb1/lTpNziiCH5MybQ==",
"version": "11.1.6",
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-11.1.6.tgz",
"integrity": "sha512-G1Pe4UILhiGOItuehRW+Pk9/NlnRaMFsdnhZ1fwBjiHvrzitmPNZdLx7Eo3GPfRrsk1mdkilZSfgH8SnM419vA==",
"license": "MIT",
"engines": {
"node": ">= 16"
@@ -2093,13 +2093,13 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.15.29",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.15.29.tgz",
"integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==",
"version": "24.0.3",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-24.0.3.tgz",
"integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
"undici-types": "~7.8.0"
}
},
"node_modules/@types/uuid": {
@@ -2115,17 +2115,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz",
"integrity": "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.1.tgz",
"integrity": "sha512-STXcN6ebF6li4PxwNeFnqF8/2BNDvBupf2OPx2yWNzr6mKNGF7q49VM00Pz5FaomJyqvbXpY6PhO+T9w139YEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.33.1",
"@typescript-eslint/type-utils": "8.33.1",
"@typescript-eslint/utils": "8.33.1",
"@typescript-eslint/visitor-keys": "8.33.1",
"@typescript-eslint/scope-manager": "8.34.1",
"@typescript-eslint/type-utils": "8.34.1",
"@typescript-eslint/utils": "8.34.1",
"@typescript-eslint/visitor-keys": "8.34.1",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
@@ -2139,7 +2139,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.33.1",
"@typescript-eslint/parser": "^8.34.1",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
@@ -2155,16 +2155,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.33.1.tgz",
"integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.34.1.tgz",
"integrity": "sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.33.1",
"@typescript-eslint/types": "8.33.1",
"@typescript-eslint/typescript-estree": "8.33.1",
"@typescript-eslint/visitor-keys": "8.33.1",
"@typescript-eslint/scope-manager": "8.34.1",
"@typescript-eslint/types": "8.34.1",
"@typescript-eslint/typescript-estree": "8.34.1",
"@typescript-eslint/visitor-keys": "8.34.1",
"debug": "^4.3.4"
},
"engines": {
@@ -2180,14 +2180,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.33.1.tgz",
"integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.34.1.tgz",
"integrity": "sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.33.1",
"@typescript-eslint/types": "^8.33.1",
"@typescript-eslint/tsconfig-utils": "^8.34.1",
"@typescript-eslint/types": "^8.34.1",
"debug": "^4.3.4"
},
"engines": {
@@ -2202,14 +2202,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz",
"integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.34.1.tgz",
"integrity": "sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.33.1",
"@typescript-eslint/visitor-keys": "8.33.1"
"@typescript-eslint/types": "8.34.1",
"@typescript-eslint/visitor-keys": "8.34.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2220,9 +2220,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz",
"integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.1.tgz",
"integrity": "sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2237,14 +2237,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz",
"integrity": "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.34.1.tgz",
"integrity": "sha512-Tv7tCCr6e5m8hP4+xFugcrwTOucB8lshffJ6zf1mF1TbU67R+ntCc6DzLNKM+s/uzDyv8gLq7tufaAhIBYeV8g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/typescript-estree": "8.33.1",
"@typescript-eslint/utils": "8.33.1",
"@typescript-eslint/typescript-estree": "8.34.1",
"@typescript-eslint/utils": "8.34.1",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
@@ -2261,9 +2261,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.33.1.tgz",
"integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.34.1.tgz",
"integrity": "sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2275,16 +2275,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz",
"integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.1.tgz",
"integrity": "sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.33.1",
"@typescript-eslint/tsconfig-utils": "8.33.1",
"@typescript-eslint/types": "8.33.1",
"@typescript-eslint/visitor-keys": "8.33.1",
"@typescript-eslint/project-service": "8.34.1",
"@typescript-eslint/tsconfig-utils": "8.34.1",
"@typescript-eslint/types": "8.34.1",
"@typescript-eslint/visitor-keys": "8.34.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -2304,9 +2304,9 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2330,16 +2330,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.33.1.tgz",
"integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.34.1.tgz",
"integrity": "sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.33.1",
"@typescript-eslint/types": "8.33.1",
"@typescript-eslint/typescript-estree": "8.33.1"
"@typescript-eslint/scope-manager": "8.34.1",
"@typescript-eslint/types": "8.34.1",
"@typescript-eslint/typescript-estree": "8.34.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2354,14 +2354,14 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz",
"integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.1.tgz",
"integrity": "sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.33.1",
"eslint-visitor-keys": "^4.2.0"
"@typescript-eslint/types": "8.34.1",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2415,53 +2415,53 @@
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.16.tgz",
"integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.17.tgz",
"integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.27.2",
"@vue/shared": "3.5.16",
"@babel/parser": "^7.27.5",
"@vue/shared": "3.5.17",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz",
"integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz",
"integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==",
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.16",
"@vue/shared": "3.5.16"
"@vue/compiler-core": "3.5.17",
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz",
"integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz",
"integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.27.2",
"@vue/compiler-core": "3.5.16",
"@vue/compiler-dom": "3.5.16",
"@vue/compiler-ssr": "3.5.16",
"@vue/shared": "3.5.16",
"@babel/parser": "^7.27.5",
"@vue/compiler-core": "3.5.17",
"@vue/compiler-dom": "3.5.17",
"@vue/compiler-ssr": "3.5.17",
"@vue/shared": "3.5.17",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.17",
"postcss": "^8.5.3",
"postcss": "^8.5.6",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz",
"integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz",
"integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.16",
"@vue/shared": "3.5.16"
"@vue/compiler-dom": "3.5.17",
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/compiler-vue2": {
@@ -2560,53 +2560,53 @@
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.16.tgz",
"integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.17.tgz",
"integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.5.16"
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.16.tgz",
"integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.17.tgz",
"integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.16",
"@vue/shared": "3.5.16"
"@vue/reactivity": "3.5.17",
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz",
"integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz",
"integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.16",
"@vue/runtime-core": "3.5.16",
"@vue/shared": "3.5.16",
"@vue/reactivity": "3.5.17",
"@vue/runtime-core": "3.5.17",
"@vue/shared": "3.5.17",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.16.tgz",
"integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.17.tgz",
"integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.5.16",
"@vue/shared": "3.5.16"
"@vue/compiler-ssr": "3.5.17",
"@vue/shared": "3.5.17"
},
"peerDependencies": {
"vue": "3.5.16"
"vue": "3.5.17"
}
},
"node_modules/@vue/shared": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.16.tgz",
"integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.17.tgz",
"integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==",
"license": "MIT"
},
"node_modules/@vueuse/core": {
@@ -2655,9 +2655,9 @@
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"version": "8.15.0",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"bin": {
@@ -3186,19 +3186,19 @@
}
},
"node_modules/eslint": {
"version": "9.28.0",
"resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.28.0.tgz",
"integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==",
"version": "9.29.0",
"resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.29.0.tgz",
"integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.20.0",
"@eslint/config-array": "^0.20.1",
"@eslint/config-helpers": "^0.2.1",
"@eslint/core": "^0.14.0",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.28.0",
"@eslint/js": "9.29.0",
"@eslint/plugin-kit": "^0.3.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
@@ -3210,9 +3210,9 @@
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
"eslint-scope": "^8.3.0",
"eslint-visitor-keys": "^4.2.0",
"espree": "^10.3.0",
"eslint-scope": "^8.4.0",
"eslint-visitor-keys": "^4.2.1",
"espree": "^10.4.0",
"esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -3247,9 +3247,9 @@
}
},
"node_modules/eslint-plugin-vue": {
"version": "10.1.0",
"resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-10.1.0.tgz",
"integrity": "sha512-/VTiJ1eSfNLw6lvG9ENySbGmcVvz6wZ9nA7ZqXlLBY2RkaF15iViYKxglWiIch12KiLAj0j1iXPYU6W4wTROFA==",
"version": "10.2.0",
"resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-10.2.0.tgz",
"integrity": "sha512-tl9s+KN3z0hN2b8fV2xSs5ytGl7Esk1oSCxULLwFcdaElhZ8btYYZFrWxvh4En+czrSDtuLCeCOGa8HhEZuBdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3269,9 +3269,9 @@
}
},
"node_modules/eslint-scope": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.3.0.tgz",
"integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
"version": "8.4.0",
"resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz",
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -3286,9 +3286,9 @@
}
},
"node_modules/eslint-visitor-keys": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -3299,15 +3299,15 @@
}
},
"node_modules/espree": {
"version": "10.3.0",
"resolved": "https://registry.npmmirror.com/espree/-/espree-10.3.0.tgz",
"integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
"version": "10.4.0",
"resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz",
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"acorn": "^8.14.0",
"acorn": "^8.15.0",
"acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^4.2.0"
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -4204,9 +4204,9 @@
}
},
"node_modules/pinia": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.2.tgz",
"integrity": "sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==",
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.3.tgz",
"integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^7.7.2"
@@ -4237,9 +4237,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.3",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.3.tgz",
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
"version": "8.5.6",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"funding": [
{
"type": "opencollective",
@@ -4256,7 +4256,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.8",
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -4454,9 +4454,9 @@
}
},
"node_modules/sass": {
"version": "1.89.1",
"resolved": "https://registry.npmmirror.com/sass/-/sass-1.89.1.tgz",
"integrity": "sha512-eMLLkl+qz7tx/0cJ9wI+w09GQ2zodTkcE/aVfywwdlRcI3EO19xGnbmJwg/JMIm+5MxVJ6outddLZ4Von4E++Q==",
"version": "1.89.2",
"resolved": "https://registry.npmmirror.com/sass/-/sass-1.89.2.tgz",
"integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
"license": "MIT",
"dependencies": {
"chokidar": "^4.0.0",
@@ -4712,15 +4712,15 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.33.1",
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.33.1.tgz",
"integrity": "sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A==",
"version": "8.34.1",
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.34.1.tgz",
"integrity": "sha512-XjS+b6Vg9oT1BaIUfkW3M3LvqZE++rbzAMEHuccCfO/YkP43ha6w3jTEMilQxMF92nVOYCcdjv1ZUhAa1D/0ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.33.1",
"@typescript-eslint/parser": "8.33.1",
"@typescript-eslint/utils": "8.33.1"
"@typescript-eslint/eslint-plugin": "8.34.1",
"@typescript-eslint/parser": "8.34.1",
"@typescript-eslint/utils": "8.34.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -4769,9 +4769,9 @@
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"version": "7.8.0",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.8.0.tgz",
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
"dev": true,
"license": "MIT"
},
@@ -5150,16 +5150,16 @@
"license": "MIT"
},
"node_modules/vue": {
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.16.tgz",
"integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==",
"version": "3.5.17",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.17.tgz",
"integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.16",
"@vue/compiler-sfc": "3.5.16",
"@vue/runtime-dom": "3.5.16",
"@vue/server-renderer": "3.5.16",
"@vue/shared": "3.5.16"
"@vue/compiler-dom": "3.5.17",
"@vue/compiler-sfc": "3.5.17",
"@vue/runtime-dom": "3.5.17",
"@vue/server-renderer": "3.5.17",
"@vue/shared": "3.5.17"
},
"peerDependencies": {
"typescript": "*"
@@ -5196,13 +5196,13 @@
}
},
"node_modules/vue-i18n": {
"version": "11.1.5",
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-11.1.5.tgz",
"integrity": "sha512-XCwuaEA5AF97g1frvH/EI1zI9uo1XKTf2/OCFgts7NvUWRsjlgeHPrkJV+a3gpzai2pC4quZ4AnOHFO8QK9hsg==",
"version": "11.1.6",
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-11.1.6.tgz",
"integrity": "sha512-+IbsW/sTZHj7U1w0rPOYJbuSB0/7DeO1nvUo3BxvO20OQgHs+ukJ3QeLqvoUA6DiLk+8SA9+djRmKC9+FC6cAg==",
"license": "MIT",
"dependencies": {
"@intlify/core-base": "11.1.5",
"@intlify/shared": "11.1.5",
"@intlify/core-base": "11.1.6",
"@intlify/shared": "11.1.6",
"@vue/devtools-api": "^6.5.0"
},
"engines": {
+11 -11
View File
@@ -25,7 +25,7 @@
"@codemirror/lang-less": "^6.0.2",
"@codemirror/lang-lezer": "^6.0.1",
"@codemirror/lang-liquid": "^6.2.3",
"@codemirror/lang-markdown": "^6.3.2",
"@codemirror/lang-markdown": "^6.3.3",
"@codemirror/lang-php": "^6.0.1",
"@codemirror/lang-python": "^6.2.1",
"@codemirror/lang-rust": "^6.0.1",
@@ -41,7 +41,7 @@
"@codemirror/lint": "^6.8.5",
"@codemirror/search": "^6.5.11",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.37.1",
"@codemirror/view": "^6.37.2",
"@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.2",
"@types/uuid": "^10.0.0",
@@ -52,24 +52,24 @@
"colors-named-hex": "^1.0.2",
"hsl-matcher": "^1.2.4",
"lezer": "^0.13.5",
"pinia": "^3.0.2",
"sass": "^1.89.1",
"pinia": "^3.0.3",
"sass": "^1.89.2",
"uuid": "^11.1.0",
"vue": "^3.5.16",
"vue-i18n": "^11.1.5",
"vue": "^3.5.17",
"vue-i18n": "^11.1.6",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@eslint/js": "^9.28.0",
"@eslint/js": "^9.29.0",
"@lezer/generator": "^1.7.3",
"@types/node": "^22.15.29",
"@types/node": "^24.0.3",
"@vitejs/plugin-vue": "^5.2.4",
"@wailsio/runtime": "latest",
"eslint": "^9.28.0",
"eslint-plugin-vue": "^10.1.0",
"eslint": "^9.29.0",
"eslint-plugin-vue": "^10.2.0",
"globals": "^16.2.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.33.1",
"typescript-eslint": "^8.34.1",
"unplugin-vue-components": "^28.7.0",
"vite": "^6.3.5",
"vue-eslint-parser": "^10.1.3",
+28
View File
@@ -0,0 +1,28 @@
/*! guesslang.min.js v0.0.3 */
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function n(e){throw e;}var p=void 0,aa=this;function t(e,b){var d=e.split("."),c=aa;!(d[0]in c)&&c.execScript&&c.execScript("var "+d[0]);for(var a;d.length&&(a=d.shift());)!d.length&&b!==p?c[a]=b:c=c[a]?c[a]:c[a]={}};var x="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;new (x?Uint8Array:Array)(256);var y;for(y=0;256>y;++y)for(var A=y,ba=7,A=A>>>1;A;A>>>=1)--ba;function B(e,b,d){var c,a="number"===typeof b?b:b=0,f="number"===typeof d?d:e.length;c=-1;for(a=f&7;a--;++b)c=c>>>8^C[(c^e[b])&255];for(a=f>>3;a--;b+=8)c=c>>>8^C[(c^e[b])&255],c=c>>>8^C[(c^e[b+1])&255],c=c>>>8^C[(c^e[b+2])&255],c=c>>>8^C[(c^e[b+3])&255],c=c>>>8^C[(c^e[b+4])&255],c=c>>>8^C[(c^e[b+5])&255],c=c>>>8^C[(c^e[b+6])&255],c=c>>>8^C[(c^e[b+7])&255];return(c^4294967295)>>>0}
var D=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],C=x?new Uint32Array(D):D;function E(){}E.prototype.getName=function(){return this.name};E.prototype.getData=function(){return this.data};E.prototype.G=function(){return this.H};function G(e){var b=e.length,d=0,c=Number.POSITIVE_INFINITY,a,f,k,l,m,r,q,g,h,v;for(g=0;g<b;++g)e[g]>d&&(d=e[g]),e[g]<c&&(c=e[g]);a=1<<d;f=new (x?Uint32Array:Array)(a);k=1;l=0;for(m=2;k<=d;){for(g=0;g<b;++g)if(e[g]===k){r=0;q=l;for(h=0;h<k;++h)r=r<<1|q&1,q>>=1;v=k<<16|g;for(h=r;h<a;h+=m)f[h]=v;++l}++k;l<<=1;m<<=1}return[f,d,c]};var J=[],K;for(K=0;288>K;K++)switch(!0){case 143>=K:J.push([K+48,8]);break;case 255>=K:J.push([K-144+400,9]);break;case 279>=K:J.push([K-256+0,7]);break;case 287>=K:J.push([K-280+192,8]);break;default:n("invalid literal: "+K)}
var ca=function(){function e(a){switch(!0){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:n("invalid length: "+a)}}var b=[],d,c;for(d=3;258>=d;d++)c=e(d),b[d]=c[2]<<24|c[1]<<
16|c[0];return b}();x&&new Uint32Array(ca);function L(e,b){this.i=[];this.j=32768;this.d=this.f=this.c=this.n=0;this.input=x?new Uint8Array(e):e;this.o=!1;this.k=M;this.w=!1;if(b||!(b={}))b.index&&(this.c=b.index),b.bufferSize&&(this.j=b.bufferSize),b.bufferType&&(this.k=b.bufferType),b.resize&&(this.w=b.resize);switch(this.k){case N:this.a=32768;this.b=new (x?Uint8Array:Array)(32768+this.j+258);break;case M:this.a=0;this.b=new (x?Uint8Array:Array)(this.j);this.e=this.D;this.q=this.A;this.l=this.C;break;default:n(Error("invalid inflate mode"))}}
var N=0,M=1;
L.prototype.g=function(){for(;!this.o;){var e=P(this,3);e&1&&(this.o=!0);e>>>=1;switch(e){case 0:var b=this.input,d=this.c,c=this.b,a=this.a,f=b.length,k=p,l=p,m=c.length,r=p;this.d=this.f=0;d+1>=f&&n(Error("invalid uncompressed block header: LEN"));k=b[d++]|b[d++]<<8;d+1>=f&&n(Error("invalid uncompressed block header: NLEN"));l=b[d++]|b[d++]<<8;k===~l&&n(Error("invalid uncompressed block header: length verify"));d+k>b.length&&n(Error("input buffer is broken"));switch(this.k){case N:for(;a+k>c.length;){r=
m-a;k-=r;if(x)c.set(b.subarray(d,d+r),a),a+=r,d+=r;else for(;r--;)c[a++]=b[d++];this.a=a;c=this.e();a=this.a}break;case M:for(;a+k>c.length;)c=this.e({t:2});break;default:n(Error("invalid inflate mode"))}if(x)c.set(b.subarray(d,d+k),a),a+=k,d+=k;else for(;k--;)c[a++]=b[d++];this.c=d;this.a=a;this.b=c;break;case 1:this.l(da,ea);break;case 2:for(var q=P(this,5)+257,g=P(this,5)+1,h=P(this,4)+4,v=new (x?Uint8Array:Array)(Q.length),s=p,F=p,H=p,w=p,z=p,O=p,I=p,u=p,Z=p,u=0;u<h;++u)v[Q[u]]=P(this,3);if(!x){u=
h;for(h=v.length;u<h;++u)v[Q[u]]=0}s=G(v);w=new (x?Uint8Array:Array)(q+g);u=0;for(Z=q+g;u<Z;)switch(z=R(this,s),z){case 16:for(I=3+P(this,2);I--;)w[u++]=O;break;case 17:for(I=3+P(this,3);I--;)w[u++]=0;O=0;break;case 18:for(I=11+P(this,7);I--;)w[u++]=0;O=0;break;default:O=w[u++]=z}F=x?G(w.subarray(0,q)):G(w.slice(0,q));H=x?G(w.subarray(q)):G(w.slice(q));this.l(F,H);break;default:n(Error("unknown BTYPE: "+e))}}return this.q()};
var S=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Q=x?new Uint16Array(S):S,fa=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],ga=x?new Uint16Array(fa):fa,ha=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],T=x?new Uint8Array(ha):ha,ia=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ja=x?new Uint16Array(ia):ia,ka=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,
11,12,12,13,13],U=x?new Uint8Array(ka):ka,V=new (x?Uint8Array:Array)(288),W,la;W=0;for(la=V.length;W<la;++W)V[W]=143>=W?8:255>=W?9:279>=W?7:8;var da=G(V),X=new (x?Uint8Array:Array)(30),Y,ma;Y=0;for(ma=X.length;Y<ma;++Y)X[Y]=5;var ea=G(X);function P(e,b){for(var d=e.f,c=e.d,a=e.input,f=e.c,k=a.length,l;c<b;)f>=k&&n(Error("input buffer is broken")),d|=a[f++]<<c,c+=8;l=d&(1<<b)-1;e.f=d>>>b;e.d=c-b;e.c=f;return l}
function R(e,b){for(var d=e.f,c=e.d,a=e.input,f=e.c,k=a.length,l=b[0],m=b[1],r,q;c<m&&!(f>=k);)d|=a[f++]<<c,c+=8;r=l[d&(1<<m)-1];q=r>>>16;q>c&&n(Error("invalid code length: "+q));e.f=d>>q;e.d=c-q;e.c=f;return r&65535}
L.prototype.l=function(e,b){var d=this.b,c=this.a;this.r=e;for(var a=d.length-258,f,k,l,m;256!==(f=R(this,e));)if(256>f)c>=a&&(this.a=c,d=this.e(),c=this.a),d[c++]=f;else{k=f-257;m=ga[k];0<T[k]&&(m+=P(this,T[k]));f=R(this,b);l=ja[f];0<U[f]&&(l+=P(this,U[f]));c>=a&&(this.a=c,d=this.e(),c=this.a);for(;m--;)d[c]=d[c++-l]}for(;8<=this.d;)this.d-=8,this.c--;this.a=c};
L.prototype.C=function(e,b){var d=this.b,c=this.a;this.r=e;for(var a=d.length,f,k,l,m;256!==(f=R(this,e));)if(256>f)c>=a&&(d=this.e(),a=d.length),d[c++]=f;else{k=f-257;m=ga[k];0<T[k]&&(m+=P(this,T[k]));f=R(this,b);l=ja[f];0<U[f]&&(l+=P(this,U[f]));c+m>a&&(d=this.e(),a=d.length);for(;m--;)d[c]=d[c++-l]}for(;8<=this.d;)this.d-=8,this.c--;this.a=c};
L.prototype.e=function(){var e=new (x?Uint8Array:Array)(this.a-32768),b=this.a-32768,d,c,a=this.b;if(x)e.set(a.subarray(32768,e.length));else{d=0;for(c=e.length;d<c;++d)e[d]=a[d+32768]}this.i.push(e);this.n+=e.length;if(x)a.set(a.subarray(b,b+32768));else for(d=0;32768>d;++d)a[d]=a[b+d];this.a=32768;return a};
L.prototype.D=function(e){var b,d=this.input.length/this.c+1|0,c,a,f,k=this.input,l=this.b;e&&("number"===typeof e.t&&(d=e.t),"number"===typeof e.z&&(d+=e.z));2>d?(c=(k.length-this.c)/this.r[2],f=258*(c/2)|0,a=f<l.length?l.length+f:l.length<<1):a=l.length*d;x?(b=new Uint8Array(a),b.set(l)):b=l;return this.b=b};
L.prototype.q=function(){var e=0,b=this.b,d=this.i,c,a=new (x?Uint8Array:Array)(this.n+(this.a-32768)),f,k,l,m;if(0===d.length)return x?this.b.subarray(32768,this.a):this.b.slice(32768,this.a);f=0;for(k=d.length;f<k;++f){c=d[f];l=0;for(m=c.length;l<m;++l)a[e++]=c[l]}f=32768;for(k=this.a;f<k;++f)a[e++]=b[f];this.i=[];return this.buffer=a};
L.prototype.A=function(){var e,b=this.a;x?this.w?(e=new Uint8Array(b),e.set(this.b.subarray(0,b))):e=this.b.subarray(0,b):(this.b.length>b&&(this.b.length=b),e=this.b);return this.buffer=e};function $(e){this.input=e;this.c=0;this.m=[];this.s=!1}$.prototype.F=function(){this.s||this.g();return this.m.slice()};
$.prototype.g=function(){for(var e=this.input.length;this.c<e;){var b=new E,d=p,c=p,a=p,f=p,k=p,l=p,m=p,r=p,q=p,g=this.input,h=this.c;b.u=g[h++];b.v=g[h++];(31!==b.u||139!==b.v)&&n(Error("invalid file signature:"+b.u+","+b.v));b.p=g[h++];switch(b.p){case 8:break;default:n(Error("unknown compression method: "+b.p))}b.h=g[h++];r=g[h++]|g[h++]<<8|g[h++]<<16|g[h++]<<24;b.H=new Date(1E3*r);b.N=g[h++];b.M=g[h++];0<(b.h&4)&&(b.I=g[h++]|g[h++]<<8,h+=b.I);if(0<(b.h&8)){m=[];for(l=0;0<(k=g[h++]);)m[l++]=String.fromCharCode(k);
b.name=m.join("")}if(0<(b.h&16)){m=[];for(l=0;0<(k=g[h++]);)m[l++]=String.fromCharCode(k);b.J=m.join("")}0<(b.h&2)&&(b.B=B(g,0,h)&65535,b.B!==(g[h++]|g[h++]<<8)&&n(Error("invalid header crc16")));d=g[g.length-4]|g[g.length-3]<<8|g[g.length-2]<<16|g[g.length-1]<<24;g.length-h-4-4<512*d&&(f=d);c=new L(g,{index:h,bufferSize:f});b.data=a=c.g();h=c.c;b.K=q=(g[h++]|g[h++]<<8|g[h++]<<16|g[h++]<<24)>>>0;B(a,p,p)!==q&&n(Error("invalid CRC-32 checksum: 0x"+B(a,p,p).toString(16)+" / 0x"+q.toString(16)));b.L=
d=(g[h++]|g[h++]<<8|g[h++]<<16|g[h++]<<24)>>>0;(a.length&4294967295)!==d&&n(Error("invalid input size: "+(a.length&4294967295)+" / "+d));this.m.push(b);this.c=h}this.s=!0;var v=this.m,s,F,H=0,w=0,z;s=0;for(F=v.length;s<F;++s)w+=v[s].data.length;if(x){z=new Uint8Array(w);for(s=0;s<F;++s)z.set(v[s].data,H),H+=v[s].data.length}else{z=[];for(s=0;s<F;++s)z[s]=v[s].data;z=Array.prototype.concat.apply([],z)}return z};t("Zlib.Gunzip",$);t("Zlib.Gunzip.prototype.decompress",$.prototype.g);t("Zlib.Gunzip.prototype.getMembers",$.prototype.F);t("Zlib.GunzipMember",E);t("Zlib.GunzipMember.prototype.getName",E.prototype.getName);t("Zlib.GunzipMember.prototype.getData",E.prototype.getData);t("Zlib.GunzipMember.prototype.getMtime",E.prototype.G);}).call(this);
Function(new TextDecoder('utf-8').decode((new Zlib.Gunzip(atob('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 Line truncated
+48
View File
@@ -0,0 +1,48 @@
importScripts("guesslang.min.js")
const LANGUAGES = ["json", "py", "html", "sql", "md", "java", "php", "css", "xml", "cpp", "rs", "cs", "rb", "sh", "yaml", "toml", "go", "clj", "ex", "erl", "js", "ts", "swift", "kt", "groovy", "ps1", "dart", "scala"]
const guessLang = new self.GuessLang()
function sendResult(language, confidence, idx) {
postMessage({language, confidence, idx})
}
onmessage = (event) => {
const {content, idx} = event.data
// JSON 快速检测
const trimmed = content.trim()
if ((trimmed.startsWith("{") && trimmed.endsWith("}")) ||
(trimmed.startsWith("[") && trimmed.endsWith("]"))) {
try {
if (typeof JSON.parse(trimmed) === "object") {
sendResult("json", 1.0, idx)
return
}
} catch (e) {
}
}
guessLang.runModel(content).then((result) => {
if (result.length > 0) {
const lang = result[0]
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.15) {
sendResult(lang.languageId, lang.confidence, idx)
return
}
}
for (let lang of result) {
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.5) {
sendResult(lang.languageId, lang.confidence, idx)
return
}
}
sendResult("text", 0.0, idx)
}).catch(() => {
sendResult("text", 0.0, idx)
})
}
@@ -13,28 +13,71 @@ const searchInputRef = ref<HTMLInputElement>();
// 语言别名映射
const LANGUAGE_ALIASES: Record<SupportedLanguage, string> = {
text: 'txt',
javascript: 'js',
typescript: 'ts',
python: 'py',
html: 'htm',
css: '',
json: '',
markdown: 'md',
shell: 'sh',
sql: '',
yaml: 'yml',
xml: '',
php: '',
java: '',
json: 'JSON',
py: 'python',
html: 'HTML',
sql: 'SQL',
md: 'markdown',
java: 'Java',
php: 'PHP',
css: 'CSS',
xml: 'XML',
cpp: 'c++',
c: '',
go: '',
rust: 'rs',
ruby: 'rb'
rs: 'rust',
cs: 'c#',
rb: 'ruby',
sh: 'shell',
yaml: 'yml',
toml: 'TOML',
go: 'Go',
clj: 'clojure',
ex: 'elixir',
erl: 'erlang',
js: 'javascript',
ts: 'typescript',
swift: 'Swift',
kt: 'kotlin',
groovy: 'Groovy',
ps1: 'powershell',
dart: 'Dart',
scala: 'Scala'
};
// 语言显示名称映射
const LANGUAGE_NAMES: Record<SupportedLanguage, string> = {
text: 'Plain Text',
json: 'JSON',
py: 'Python',
html: 'HTML',
sql: 'SQL',
md: 'Markdown',
java: 'Java',
php: 'PHP',
css: 'CSS',
xml: 'XML',
cpp: 'C++',
rs: 'Rust',
cs: 'C#',
rb: 'Ruby',
sh: 'Shell',
yaml: 'YAML',
toml: 'TOML',
go: 'Go',
clj: 'Clojure',
ex: 'Elixir',
erl: 'Erlang',
js: 'JavaScript',
ts: 'TypeScript',
swift: 'Swift',
kt: 'Kotlin',
groovy: 'Groovy',
ps1: 'PowerShell',
dart: 'Dart',
scala: 'Scala'
};
// 当前选中的语言
const currentLanguage = ref<SupportedLanguage>('javascript');
const currentLanguage = ref<SupportedLanguage>('text');
// 过滤后的语言列表
const filteredLanguages = computed(() => {
@@ -44,8 +87,10 @@ const filteredLanguages = computed(() => {
const query = searchQuery.value.toLowerCase();
return SUPPORTED_LANGUAGES.filter(langId => {
const name = LANGUAGE_NAMES[langId];
const alias = LANGUAGE_ALIASES[langId];
return langId.toLowerCase().includes(query) ||
(name && name.toLowerCase().includes(query)) ||
(alias && alias.toLowerCase().includes(query));
});
});
@@ -96,7 +141,7 @@ onUnmounted(() => {
// 获取当前语言的显示名称
const getCurrentLanguageName = computed(() => {
return currentLanguage.value;
return LANGUAGE_NAMES[currentLanguage.value] || currentLanguage.value;
});
</script>
@@ -143,8 +188,8 @@ const getCurrentLanguageName = computed(() => {
:class="{ 'active': currentLanguage === language }"
@click="selectLanguage(language)"
>
<span class="language-name">{{ language }}</span>
<span class="language-alias" v-if="LANGUAGE_ALIASES[language]">{{ LANGUAGE_ALIASES[language] }}</span>
<span class="language-name">{{ LANGUAGE_NAMES[language] || language }}</span>
<span class="language-alias">{{ language }}</span>
</div>
<!-- 无结果提示 -->
@@ -1,33 +1,32 @@
/**
* CodeBlock 扩展主入口
*
*
* 配置说明:
* - showBackground: 控制是否显示代码块的背景色区分
* - enableAutoDetection: 控制是否启用内容的语言自动检测功能
* - defaultLanguage: 新建代码块时使用的默认语言(也是自动检测的回退语言)
* - defaultAutoDetect: 新建代码块时是否默认添加-a标记启用自动检测
*
*
* 注意:defaultLanguage 和 defaultAutoDetect 是配合使用的:
* - 如果 defaultAutoDetect=true,新建块会是 ∞∞∞javascript-a(会根据内容自动检测语言)
* - 如果 defaultAutoDetect=false,新建块会是 ∞∞∞javascript(固定使用指定语言)
*/
import {Extension} from '@codemirror/state';
import {keymap} from '@codemirror/view';
import {keymap, lineNumbers} from '@codemirror/view';
// 导入核心模块
import {blockState} from './state';
import {getBlockDecorationExtensions} from './decorations';
import * as commands from './commands';
import {selectAll, getBlockSelectExtensions} from './selectAll';
import {getBlockSelectExtensions, selectAll} from './selectAll';
import {getCopyPasteExtensions, getCopyPasteKeymap} from './copyPaste';
import {deleteLineCommand} from './deleteLine';
import {moveLineUp, moveLineDown} from './moveLines';
import {moveLineDown, moveLineUp} from './moveLines';
import {transposeChars} from './transposeChars';
import {getCodeBlockLanguageExtension} from './lang-parser';
import {createLanguageDetection} from './language-detection';
import {EditorOptions, SupportedLanguage} from './types';
import {lineNumbers} from '@codemirror/view';
/**
* 代码块扩展配置选项
@@ -38,10 +37,10 @@ export interface CodeBlockOptions {
/** 是否启用语言自动检测功能 */
enableAutoDetection?: boolean;
/** 新建块时的默认语言 */
defaultLanguage?: SupportedLanguage;
/** 新建块时是否默认启用自动检测(添加-a标记) */
defaultAutoDetect?: boolean;
}
@@ -52,10 +51,10 @@ export interface CodeBlockOptions {
function getBlockLineFromPos(state: any, pos: number) {
const line = state.doc.lineAt(pos);
const blocks = state.field(blockState);
const block = blocks.find((block: any) =>
const block = blocks.find((block: any) =>
block.content.from <= line.from && block.content.to >= line.from
);
if (block) {
const firstBlockLine = state.doc.lineAt(block.content.from).number;
return {
@@ -112,8 +111,8 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
// 语言自动检测(如果启用)
...(enableAutoDetection ? [createLanguageDetection({
defaultLanguage: defaultLanguage,
confidenceThreshold: 0.3,
minContentLength: 8,
confidenceThreshold: 0.15,
minContentLength: 8
})] : []),
// 视觉装饰系统
@@ -297,14 +296,12 @@ export {
createLanguageDetection,
detectLanguage,
detectLanguages,
detectLanguageHeuristic,
getSupportedDetectionLanguages,
levenshteinDistance,
type LanguageDetectionResult
} from './language-detection';
// 行号相关
export { getBlockLineFromPos, blockLineNumbers };
export {getBlockLineFromPos, blockLineNumbers};
/**
* 默认导出
@@ -14,12 +14,21 @@ import { cssLanguage } from "@codemirror/lang-css";
import { cppLanguage } from "@codemirror/lang-cpp";
import { xmlLanguage } from "@codemirror/lang-xml";
import { rustLanguage } from "@codemirror/lang-rust";
import { yamlLanguage } from "@codemirror/lang-yaml";
import { StreamLanguage } from "@codemirror/language";
import { ruby } from "@codemirror/legacy-modes/mode/ruby";
import { shell } from "@codemirror/legacy-modes/mode/shell";
import { go } from "@codemirror/legacy-modes/mode/go";
import { yamlLanguage } from "@codemirror/lang-yaml";
import { csharp } from "@codemirror/legacy-modes/mode/clike";
import { clojure } from "@codemirror/legacy-modes/mode/clojure";
import { erlang } from "@codemirror/legacy-modes/mode/erlang";
import { swift } from "@codemirror/legacy-modes/mode/swift";
import { kotlin } from "@codemirror/legacy-modes/mode/clike";
import { groovy } from "@codemirror/legacy-modes/mode/groovy";
import { powerShell } from "@codemirror/legacy-modes/mode/powershell";
import { scala } from "@codemirror/legacy-modes/mode/clike";
import { toml } from "@codemirror/legacy-modes/mode/toml";
import { SupportedLanguage } from '../types';
@@ -30,34 +39,43 @@ export class LanguageInfo {
constructor(
public token: SupportedLanguage,
public name: string,
public parser: any,
public guesslang?: string | null
public parser: any
) {}
}
/**
* 支持的语言列表
* 支持的语言列表(与 Worker 中的 LANGUAGES 对应)
*/
export const LANGUAGES: LanguageInfo[] = [
new LanguageInfo("text", "Plain Text", null),
new LanguageInfo("json", "JSON", jsonLanguage.parser, "json"),
new LanguageInfo("python", "Python", pythonLanguage.parser, "py"),
new LanguageInfo("javascript", "JavaScript", javascriptLanguage.parser, "js"),
new LanguageInfo("typescript", "TypeScript", typescriptLanguage.parser, "ts"),
new LanguageInfo("html", "HTML", htmlLanguage.parser, "html"),
new LanguageInfo("css", "CSS", cssLanguage.parser, "css"),
new LanguageInfo("sql", "SQL", StandardSQL.language.parser, "sql"),
new LanguageInfo("markdown", "Markdown", markdownLanguage.parser, "md"),
new LanguageInfo("java", "Java", javaLanguage.parser, "java"),
new LanguageInfo("php", "PHP", phpLanguage.configure({top:"Program"}).parser, "php"),
new LanguageInfo("xml", "XML", xmlLanguage.parser, "xml"),
new LanguageInfo("cpp", "C++", cppLanguage.parser, "cpp"),
new LanguageInfo("c", "C", cppLanguage.parser, "c"),
new LanguageInfo("rust", "Rust", rustLanguage.parser, "rs"),
new LanguageInfo("ruby", "Ruby", StreamLanguage.define(ruby).parser, "rb"),
new LanguageInfo("shell", "Shell", StreamLanguage.define(shell).parser, "sh"),
new LanguageInfo("yaml", "YAML", yamlLanguage.parser, "yaml"),
new LanguageInfo("go", "Go", StreamLanguage.define(go).parser, "go"),
new LanguageInfo("json", "JSON", jsonLanguage.parser),
new LanguageInfo("py", "Python", pythonLanguage.parser),
new LanguageInfo("html", "HTML", htmlLanguage.parser),
new LanguageInfo("sql", "SQL", StandardSQL.language.parser),
new LanguageInfo("md", "Markdown", markdownLanguage.parser),
new LanguageInfo("java", "Java", javaLanguage.parser),
new LanguageInfo("php", "PHP", phpLanguage.configure({top:"Program"}).parser),
new LanguageInfo("css", "CSS", cssLanguage.parser),
new LanguageInfo("xml", "XML", xmlLanguage.parser),
new LanguageInfo("cpp", "C++", cppLanguage.parser),
new LanguageInfo("rs", "Rust", rustLanguage.parser),
new LanguageInfo("cs", "C#", StreamLanguage.define(csharp).parser),
new LanguageInfo("rb", "Ruby", StreamLanguage.define(ruby).parser),
new LanguageInfo("sh", "Shell", StreamLanguage.define(shell).parser),
new LanguageInfo("yaml", "YAML", yamlLanguage.parser),
new LanguageInfo("toml", "TOML", StreamLanguage.define(toml).parser),
new LanguageInfo("go", "Go", StreamLanguage.define(go).parser),
new LanguageInfo("clj", "Clojure", StreamLanguage.define(clojure).parser),
new LanguageInfo("ex", "Elixir", null), // 暂无解析器
new LanguageInfo("erl", "Erlang", StreamLanguage.define(erlang).parser),
new LanguageInfo("js", "JavaScript", javascriptLanguage.parser),
new LanguageInfo("ts", "TypeScript", typescriptLanguage.parser),
new LanguageInfo("swift", "Swift", StreamLanguage.define(swift).parser),
new LanguageInfo("kt", "Kotlin", StreamLanguage.define(kotlin).parser),
new LanguageInfo("groovy", "Groovy", StreamLanguage.define(groovy).parser),
new LanguageInfo("ps1", "PowerShell", StreamLanguage.define(powerShell).parser),
new LanguageInfo("dart", "Dart", null), // 暂无解析器
new LanguageInfo("scala", "Scala", StreamLanguage.define(scala).parser),
];
/**
@@ -79,4 +97,4 @@ export function getLanguage(token: SupportedLanguage): LanguageInfo | undefined
*/
export function getLanguageTokens(): SupportedLanguage[] {
return LANGUAGES.map(lang => lang.token);
}
}
@@ -1,62 +1,92 @@
/**
* 自动语言检测
* 基于内容变化自动检测和更新代码块语言
* 基于 Web Worker 的语言自动检测
*/
import { EditorState, Annotation } from '@codemirror/state';
import { EditorView, ViewPlugin } from '@codemirror/view';
import { blockState, getActiveNoteBlock } from '../state';
import { blockState } from '../state';
import { levenshteinDistance } from './levenshtein';
import { detectLanguageHeuristic, LanguageDetectionResult } from './heuristics';
import { LANGUAGES } from '../lang-parser/languages';
import { SupportedLanguage, Block } from '../types';
// ===== 类型定义 =====
/**
* 语言检测配置
* 语言检测配置选项
*/
interface LanguageDetectionConfig {
/** 最小内容长度阈值 */
minContentLength: number;
/** 变化阈值比例 */
changeThreshold: number;
/** 检测置信度阈值 */
confidenceThreshold: number;
/** 空闲检测延迟 (ms) */
idleDelay: number;
/** 默认语言 */
defaultLanguage: SupportedLanguage;
export interface LanguageDetectionConfig {
minContentLength?: number;
confidenceThreshold?: number;
idleDelay?: number;
defaultLanguage?: SupportedLanguage;
}
/**
* 语言检测结果
*/
export interface LanguageDetectionResult {
language: SupportedLanguage;
confidence: number;
}
/**
* Worker 消息接口
*/
interface WorkerMessage {
content: string;
idx: number;
}
/**
* Worker 响应接口
*/
interface WorkerResponse {
language: string;
confidence: number;
idx: number;
}
// ===== 常量配置 =====
/**
* 默认配置
*/
const DEFAULT_CONFIG: LanguageDetectionConfig = {
minContentLength: 8,
changeThreshold: 0.1,
confidenceThreshold: 0.3,
const DEFAULT_CONFIG = {
minContentLength: 20,
confidenceThreshold: 0.15,
idleDelay: 1000,
defaultLanguage: 'text',
defaultLanguage: 'text' as SupportedLanguage,
};
/**
* 语言标记映射
* 将检测结果映射到我们的语言标记
* 支持的语言列表
*/
const DETECTION_TO_TOKEN = Object.fromEntries(
LANGUAGES.map(l => [l.token, l.token])
);
const SUPPORTED_LANGUAGES = new Set([
"json", "py", "html", "sql", "md", "java", "php", "css", "xml",
"cpp", "rs", "cs", "rb", "sh", "yaml", "toml", "go", "clj",
"ex", "erl", "js", "ts", "swift", "kt", "groovy", "ps1", "dart", "scala"
]);
/**
* 兼容性函数
* 语言标记映射表
*/
function requestIdleCallbackCompat(cb: () => void): number {
const LANGUAGE_MAP = new Map(LANGUAGES.map(lang => [lang.token, lang.token]));
// ===== 工具函数 =====
/**
* 兼容性函数:requestIdleCallback
*/
function requestIdleCallbackCompat(callback: () => void): number {
if (typeof window !== 'undefined' && window.requestIdleCallback) {
return window.requestIdleCallback(cb);
} else {
return setTimeout(cb, 0) as any;
return window.requestIdleCallback(callback);
}
return setTimeout(callback, 0) as any;
}
/**
* 兼容性函数:cancelIdleCallback
*/
function cancelIdleCallbackCompat(id: number): void {
if (typeof window !== 'undefined' && window.cancelIdleCallback) {
window.cancelIdleCallback(id);
@@ -71,167 +101,192 @@ function cancelIdleCallbackCompat(id: number): void {
const languageChangeAnnotation = Annotation.define<boolean>();
/**
* 语言更改命令
* 简化版本,直接更新块的语言标记
* 更新代码块语言
*/
function changeLanguageTo(
function updateBlockLanguage(
state: EditorState,
dispatch: (tr: any) => void,
dispatch: (transaction: any) => void,
block: Block,
newLanguage: SupportedLanguage,
isAuto: boolean
newLanguage: SupportedLanguage
): void {
// 构建新的分隔符文本
const autoSuffix = isAuto ? '-a' : '';
const newDelimiter = `\n∞∞∞${newLanguage}${autoSuffix}\n`;
// 创建事务来替换分隔符
const newDelimiter = `\n∞∞∞${newLanguage}-a\n`;
const transaction = state.update({
changes: {
from: block.delimiter.from,
to: block.delimiter.to,
insert: newDelimiter,
},
annotations: [
languageChangeAnnotation.of(true)
]
annotations: [languageChangeAnnotation.of(true)]
});
dispatch(transaction);
}
// ===== Web Worker 管理器 =====
/**
* 语言检测 Worker 管理器
* 负责 Worker 的生命周期管理和消息通信
*/
class LanguageDetectionWorker {
private worker: Worker | null = null;
private pendingRequests = new Map<number, {
resolve: (result: LanguageDetectionResult) => void;
reject: (error: Error) => void;
}>();
private requestId = 0;
constructor() {
this.initWorker();
}
/**
* 初始化 Worker
*/
private initWorker(): void {
try {
this.worker = new Worker('/langdetect-worker.js');
this.worker.onmessage = (event) => {
const response: WorkerResponse = event.data;
const request = this.pendingRequests.get(response.idx);
if (request) {
this.pendingRequests.delete(response.idx);
if (response.language) {
request.resolve({
language: response.language as SupportedLanguage,
confidence: response.confidence
});
} else {
request.reject(new Error('No detection result'));
}
}
};
this.worker.onerror = () => {
this.pendingRequests.forEach(request => request.reject(new Error('Worker error')));
this.pendingRequests.clear();
};
} catch (error) {
console.error('Failed to initialize worker:', error);
}
}
/**
* 检测语言
*/
async detectLanguage(content: string): Promise<LanguageDetectionResult> {
if (!this.worker) {
throw new Error('Worker not initialized');
}
return new Promise((resolve, reject) => {
const id = ++this.requestId;
this.pendingRequests.set(id, { resolve, reject });
this.worker!.postMessage({ content, idx: id } as WorkerMessage);
// 5秒超时
setTimeout(() => {
if (this.pendingRequests.has(id)) {
this.pendingRequests.delete(id);
reject(new Error('Detection timeout'));
}
}, 5000);
});
}
/**
* 销毁 Worker
*/
destroy(): void {
if (this.worker) {
this.worker.terminate();
this.worker = null;
}
this.pendingRequests.clear();
}
}
// ===== 语言检测插件 =====
/**
* 创建语言检测插件
*/
export function createLanguageDetection(
config: Partial<LanguageDetectionConfig> = {}
): ViewPlugin<any> {
export function createLanguageDetection(config: LanguageDetectionConfig = {}): ViewPlugin<any> {
const finalConfig = { ...DEFAULT_CONFIG, ...config };
const previousBlockContent: Record<number, string> = {};
const contentCache = new Map<number, string>();
let idleCallbackId: number | null = null;
let worker: LanguageDetectionWorker | null = null;
return ViewPlugin.fromClass(
class LanguageDetectionPlugin {
constructor(public view: EditorView) {}
constructor(public view: EditorView) {
worker = new LanguageDetectionWorker();
}
update(update: any) {
if (update.docChanged) {
// 取消之前的检测
if (update.docChanged && !update.transactions.some((tr: any) =>
tr.annotation(languageChangeAnnotation))) {
if (idleCallbackId !== null) {
cancelIdleCallbackCompat(idleCallbackId);
idleCallbackId = null;
}
// 安排新的检测
idleCallbackId = requestIdleCallbackCompat(() => {
idleCallbackId = null;
this.performLanguageDetection(update);
this.performDetection(update.state);
});
}
}
private performLanguageDetection(update: any) {
const range = update.state.selection.asSingle().ranges[0];
const blocks = update.state.field(blockState);
private performDetection(state: EditorState): void {
const selection = state.selection.asSingle().ranges[0];
const blocks = state.field(blockState);
let block: Block | null = null;
let blockIndex: number | null = null;
const block = blocks.find(b =>
b.content.from <= selection.from && b.content.to >= selection.from
);
if (!block || !block.language.auto) return;
// 找到当前块
for (let i = 0; i < blocks.length; i++) {
if (blocks[i].content.from <= range.from && blocks[i].content.to >= range.from) {
block = blocks[i];
blockIndex = i;
break;
}
}
const blockIndex = blocks.indexOf(block);
const content = state.doc.sliceString(block.content.from, block.content.to);
if (block === null || blockIndex === null) {
return;
}
// 如果不是自动检测模式,清除缓存并返回
if (!block.language.auto) {
delete previousBlockContent[blockIndex];
return;
}
const content = update.state.doc.sliceString(block.content.from, block.content.to);
// 如果内容为空,重置为默认语言
// 内容为空时重置为默认语言
if (content === "") {
if (block.language.name !== finalConfig.defaultLanguage) {
changeLanguageTo(
update.state,
this.view.dispatch,
block,
finalConfig.defaultLanguage,
true
);
updateBlockLanguage(state, this.view.dispatch, block, finalConfig.defaultLanguage);
}
delete previousBlockContent[blockIndex];
contentCache.delete(blockIndex);
return;
}
// 内容太短,跳过检测
if (content.length <= finalConfig.minContentLength) {
// 内容太短则跳过
if (content.length <= finalConfig.minContentLength) return;
// 检查内容变化
const cachedContent = contentCache.get(blockIndex);
if (cachedContent && levenshteinDistance(cachedContent, content) < content.length * 0.1) {
return;
}
// 检查内容是否有显著变化
const threshold = content.length * finalConfig.changeThreshold;
const previousContent = previousBlockContent[blockIndex];
if (!previousContent) {
// 执行语言检测
this.detectAndUpdateLanguage(content, block, blockIndex, update.state);
previousBlockContent[blockIndex] = content;
} else {
const distance = levenshteinDistance(previousContent, content);
if (distance >= threshold) {
// 执行语言检测
this.detectAndUpdateLanguage(content, block, blockIndex, update.state);
previousBlockContent[blockIndex] = content;
}
}
this.detectAndUpdate(content, block, blockIndex, state);
}
private detectAndUpdateLanguage(
content: string,
block: any,
blockIndex: number,
state: EditorState
) {
private async detectAndUpdate(content: string, block: Block, blockIndex: number, state: EditorState): Promise<void> {
if (!worker) return;
// 使用启发式检测
const detectionResult = detectLanguageHeuristic(content);
// 检查置信度和语言变化
if (detectionResult.confidence >= finalConfig.confidenceThreshold &&
detectionResult.language !== block.language.name &&
DETECTION_TO_TOKEN[detectionResult.language]) {
try {
const result = await worker.detectLanguage(content);
// 验证内容未显著变化
const currentContent = state.doc.sliceString(block.content.from, block.content.to);
const threshold = currentContent.length * finalConfig.changeThreshold;
const contentDistance = levenshteinDistance(content, currentContent);
if (contentDistance <= threshold) {
// 内容未显著变化,安全更新语言
changeLanguageTo(
state,
this.view.dispatch,
block,
detectionResult.language,
true
);
if (result.confidence >= finalConfig.confidenceThreshold &&
result.language !== block.language.name &&
SUPPORTED_LANGUAGES.has(result.language) &&
LANGUAGE_MAP.has(result.language)) {
updateBlockLanguage(state, this.view.dispatch, block, result.language);
}
contentCache.set(blockIndex, content);
} catch (error) {
console.warn('Language detection failed:', error);
}
}
@@ -239,21 +294,38 @@ export function createLanguageDetection(
if (idleCallbackId !== null) {
cancelIdleCallbackCompat(idleCallbackId);
}
if (worker) {
worker.destroy();
worker = null;
}
contentCache.clear();
}
}
);
}
// ===== 公共 API =====
/**
* 手动检测语言
* 手动检测单个内容的语言
*/
export function detectLanguage(content: string): LanguageDetectionResult {
return detectLanguageHeuristic(content);
export async function detectLanguage(content: string): Promise<LanguageDetectionResult> {
const worker = new LanguageDetectionWorker();
try {
return await worker.detectLanguage(content);
} finally {
worker.destroy();
}
}
/**
* 批量检测多个内容块的语言
* 批量检测多个内容的语言
*/
export function detectLanguages(contents: string[]): LanguageDetectionResult[] {
return contents.map(content => detectLanguageHeuristic(content));
export async function detectLanguages(contents: string[]): Promise<LanguageDetectionResult[]> {
const worker = new LanguageDetectionWorker();
try {
return await Promise.all(contents.map(content => worker.detectLanguage(content)));
} finally {
worker.destroy();
}
}
@@ -1,269 +0,0 @@
/**
* 基于启发式规则的语言检测
* 用于快速识别常见的编程语言模式
*/
import { SupportedLanguage } from '../types';
/**
* 语言检测结果
*/
export interface LanguageDetectionResult {
language: SupportedLanguage;
confidence: number;
}
/**
* 语言模式定义
*/
interface LanguagePattern {
patterns: RegExp[];
weight: number;
}
/**
* 语言检测规则映射
*/
const LANGUAGE_PATTERNS: Record<string, LanguagePattern> = {
javascript: {
patterns: [
/\b(function|const|let|var|class|extends|import|export|async|await)\b/g,
/\b(console\.log|document\.|window\.)\b/g,
/=>\s*[{(]/g,
/\b(require|module\.exports)\b/g,
],
weight: 1.0,
},
typescript: {
patterns: [
/\b(interface|type|enum|namespace|implements|declare)\b/g,
/:\s*(string|number|boolean|object|any)\b/g,
/<[A-Z][a-zA-Z0-9<>,\s]*>/g,
/\b(public|private|protected|readonly)\b/g,
],
weight: 1.2,
},
python: {
patterns: [
/\b(def|class|import|from|if __name__|print|len|range)\b/g,
/^\s*#.*$/gm,
/\b(True|False|None)\b/g,
/:\s*$/gm,
],
weight: 1.0,
},
java: {
patterns: [
/\b(public|private|protected|static|final|class|interface)\b/g,
/\b(System\.out\.println|String|int|void)\b/g,
/import\s+[a-zA-Z0-9_.]+;/g,
/\b(extends|implements)\b/g,
],
weight: 1.0,
},
html: {
patterns: [
/<\/?[a-zA-Z][^>]*>/g,
/<!DOCTYPE\s+html>/gi,
/<(div|span|p|h[1-6]|body|head|html)\b/g,
/\s(class|id|src|href)=/g,
],
weight: 1.5,
},
css: {
patterns: [
/[.#][a-zA-Z][\w-]*\s*{/g,
/\b(color|background|margin|padding|font-size):\s*[^;]+;/g,
/@(media|keyframes|import)\b/g,
/\{[^}]*\}/g,
],
weight: 1.3,
},
json: {
patterns: [
/^\s*[{\[][\s\S]*[}\]]\s*$/,
/"[^"]*":\s*(".*"|[\d.]+|true|false|null)/g,
/,\s*$/gm,
],
weight: 2.0,
},
sql: {
patterns: [
/\b(SELECT|FROM|WHERE|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\b/gi,
/\b(JOIN|LEFT|RIGHT|INNER|OUTER|ON|GROUP BY|ORDER BY)\b/gi,
/;\s*$/gm,
/\b(TABLE|DATABASE|INDEX)\b/gi,
],
weight: 1.4,
},
shell: {
patterns: [
/^#!/g,
/\b(echo|cd|ls|grep|awk|sed|cat|chmod)\b/g,
/\$\{?\w+\}?/g,
/\|\s*\w+/g,
],
weight: 1.2,
},
markdown: {
patterns: [
/^#+\s+/gm,
/\*\*.*?\*\*/g,
/\[.*?\]\(.*?\)/g,
/^```/gm,
],
weight: 1.1,
},
php: {
patterns: [
/<\?php/g,
/\$\w+/g,
/\b(function|class|extends|implements)\b/g,
/echo\s+/g,
],
weight: 1.3,
},
cpp: {
patterns: [
/#include\s*<.*>/g,
/\b(int|char|float|double|void|class|struct)\b/g,
/std::/g,
/cout\s*<<|cin\s*>>/g,
],
weight: 1.1,
},
rust: {
patterns: [
/\bfn\s+\w+/g,
/\b(let|mut|struct|enum|impl|trait)\b/g,
/println!\(/g,
/::\w+/g,
],
weight: 1.2,
},
go: {
patterns: [
/\bfunc\s+\w+/g,
/\b(var|const|type|package|import)\b/g,
/fmt\.\w+/g,
/:=\s*/g,
],
weight: 1.1,
},
ruby: {
patterns: [
/\b(def|class|module|end)\b/g,
/\b(puts|print|require)\b/g,
/@\w+/g,
/\|\w+\|/g,
],
weight: 1.0,
},
yaml: {
patterns: [
/^\s*\w+:\s*.*$/gm, // key: value 模式
/^\s*-\s+\w+/gm, // 列表项
/^---\s*$/gm, // 文档分隔符
/^\s*\w+:\s*\|/gm, // 多行字符串
/^\s*\w+:\s*>/gm, // 折叠字符串
/^\s*#.*$/gm, // 注释
/:\s*\[.*\]/g, // 内联数组
/:\s*\{.*\}/g, // 内联对象
],
weight: 1.5,
},
xml: {
patterns: [
/<\?xml/g,
/<\/\w+>/g,
/<\w+[^>]*\/>/g,
/\s\w+="[^"]*"/g,
],
weight: 1.3,
},
};
/**
* JSON 特殊检测
* 使用更严格的规则检测 JSON
*/
function detectJSON(content: string): LanguageDetectionResult | null {
const trimmed = content.trim();
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
(trimmed.startsWith('[') && trimmed.endsWith(']'))) {
try {
JSON.parse(trimmed);
return {
language: 'json',
confidence: 1.0,
};
} catch (e) {
// JSON 解析失败,继续其他检测
}
}
return null;
}
/**
* 计算文本与语言模式的匹配分数
*/
function calculateScore(content: string, pattern: LanguagePattern): number {
let score = 0;
const contentLength = Math.max(content.length, 1);
for (const regex of pattern.patterns) {
const matches = content.match(regex);
if (matches) {
score += matches.length;
}
}
// 根据内容长度和权重标准化分数
return (score * pattern.weight) / (contentLength / 100);
}
/**
* 基于启发式规则检测语言
*/
export function detectLanguageHeuristic(content: string): LanguageDetectionResult {
if (!content.trim()) {
return { language: 'text', confidence: 1.0 };
}
// 首先尝试 JSON 特殊检测
const jsonResult = detectJSON(content);
if (jsonResult) {
return jsonResult;
}
const scores: Record<string, number> = {};
// 计算每种语言的匹配分数
for (const [language, pattern] of Object.entries(LANGUAGE_PATTERNS)) {
scores[language] = calculateScore(content, pattern);
}
// 找到最高分的语言
const sortedScores = Object.entries(scores)
.sort(([, a], [, b]) => b - a)
.filter(([, score]) => score > 0);
if (sortedScores.length > 0) {
const [bestLanguage, bestScore] = sortedScores[0];
return {
language: bestLanguage as SupportedLanguage,
confidence: Math.min(bestScore, 1.0),
};
}
return { language: 'text', confidence: 1.0 };
}
/**
* 获取所有支持的检测语言
*/
export function getSupportedDetectionLanguages(): SupportedLanguage[] {
return Object.keys(LANGUAGE_PATTERNS) as SupportedLanguage[];
}
@@ -1,26 +1,14 @@
/**
* 语言检测模块入口
* 导出所有语言检测相关的功能
* 语言检测模块
*/
// 主要检测功能
export {
createLanguageDetection,
detectLanguage,
detectLanguages
detectLanguages,
type LanguageDetectionResult,
type LanguageDetectionConfig
} from './autodetect';
// 启发式检测
export {
detectLanguageHeuristic,
getSupportedDetectionLanguages,
type LanguageDetectionResult
} from './heuristics';
// 工具函数
export {
levenshteinDistance
} from './levenshtein';
// 重新导出类型
export type { SupportedLanguage } from '../types';
export { levenshteinDistance } from './levenshtein';
export type { SupportedLanguage } from '../types';
@@ -1,78 +1,70 @@
/**
* Levenshtein 距离算法
* 用于计算两个字符串之间的编辑距离
*/
/**
* 内部最小值计算函数
* 用于计算编辑距离的最小成本
*
* @param d0 - 对角线上的距离
* @param d1 - 左侧的距离
* @param d2 - 上方的距离
* @param bx - 字符串 b 的当前字符
* @param ay - 字符串 a 的当前字符
* @returns 最小编辑距离
*/
function _min(d0: number, d1: number, d2: number, bx: number, ay: number): number {
function min(d0: number, d1: number, d2: number, bx: number, ay: number): number {
return d0 < d1 || d2 < d1
? d0 > d2
? d2 + 1
: d0 + 1
: bx === ay
? d1
: d1 + 1;
? d0 > d2 ? d2 + 1 : d0 + 1
: bx === ay ? d1 : d1 + 1;
}
/**
* 计算两个字符串之间的 Levenshtein 距离
* @param a 第一个字符串
* @param b 第二个字符串
* @returns 编辑距离
*
* 该实现使用了多项优化:
* 1. 确保较短的字符串作为第一个参数
* 2. 跳过公共前缀和后缀
* 3. 使用滚动数组减少空间复杂度
* 4. 批量处理以提高性能
*
* @param stringA - 第一个字符串
* @param stringB - 第二个字符串
* @returns 编辑距离(非负整数)
*/
export function levenshteinDistance(a: string, b: string): number {
if (a === b) {
return 0;
}
if (a === b) return 0;
if (a.length > b.length) {
const tmp = a;
a = b;
b = tmp;
[a, b] = [b, a];
}
let la = a.length;
let lb = b.length;
while (la > 0 && (a.charCodeAt(la - 1) === b.charCodeAt(lb - 1))) {
// 跳过公共后缀
while (la > 0 && a.charCodeAt(la - 1) === b.charCodeAt(lb - 1)) {
la--;
lb--;
}
let offset = 0;
while (offset < la && (a.charCodeAt(offset) === b.charCodeAt(offset))) {
// 跳过公共前缀
while (offset < la && a.charCodeAt(offset) === b.charCodeAt(offset)) {
offset++;
}
la -= offset;
lb -= offset;
if (la === 0 || lb < 3) {
return lb;
}
if (la === 0 || lb < 3) return lb;
let x = 0;
let y: number;
let d0: number;
let d1: number;
let d2: number;
let d3: number;
let dd = 0;
let dy: number;
let ay: number;
let bx0: number;
let bx1: number;
let bx2: number;
let bx3: number;
let x = 0, y: number, d0: number, d1: number, d2: number, d3: number;
let dd = 0, dy: number, ay: number, bx0: number, bx1: number, bx2: number, bx3: number;
const vector: number[] = [];
for (y = 0; y < la; y++) {
vector.push(y + 1);
vector.push(a.charCodeAt(offset + y));
vector.push(y + 1, a.charCodeAt(offset + y));
}
const len = vector.length - 1;
@@ -84,18 +76,16 @@ export function levenshteinDistance(a: string, b: string): number {
bx3 = b.charCodeAt(offset + (d3 = x + 3));
x += 4;
dd = x;
for (y = 0; y < len; y += 2) {
dy = vector[y];
ay = vector[y + 1];
d0 = _min(dy, d0, d1, bx0, ay);
d1 = _min(d0, d1, d2, bx1, ay);
d2 = _min(d1, d2, d3, bx2, ay);
dd = _min(d2, d3, dd, bx3, ay);
d0 = min(dy, d0, d1, bx0, ay);
d1 = min(d0, d1, d2, bx1, ay);
d2 = min(d1, d2, d3, bx2, ay);
dd = min(d2, d3, dd, bx3, ay);
vector[y] = dd;
d3 = d2;
d2 = d1;
d1 = d0;
d0 = dy;
d3 = d2; d2 = d1; d1 = d0; d0 = dy;
}
}
@@ -104,7 +94,7 @@ export function levenshteinDistance(a: string, b: string): number {
dd = ++x;
for (y = 0; y < len; y += 2) {
dy = vector[y];
vector[y] = dd = _min(dy, d0, dd, bx0, vector[y + 1]);
vector[y] = dd = min(dy, d0, dd, bx0, vector[y + 1]);
d0 = dy;
}
}
@@ -25,48 +25,68 @@ export interface Block {
*/
export type SupportedLanguage =
| 'text'
| 'javascript'
| 'typescript'
| 'python'
| 'html'
| 'css'
| 'json'
| 'markdown'
| 'shell'
| 'py' // Python
| 'html'
| 'sql'
| 'yaml'
| 'xml'
| 'php'
| 'md' // Markdown
| 'java'
| 'cpp'
| 'c'
| 'php'
| 'css'
| 'xml'
| 'cpp' // C++
| 'rs' // Rust
| 'cs' // C#
| 'rb' // Ruby
| 'sh' // Shell
| 'yaml'
| 'toml'
| 'go'
| 'rust'
| 'ruby';
| 'clj' // Clojure
| 'ex' // Elixir
| 'erl' // Erlang
| 'js' // JavaScript
| 'ts' // TypeScript
| 'swift'
| 'kt' // Kotlin
| 'groovy'
| 'ps1' // PowerShell
| 'dart'
| 'scala';
/**
* 支持的语言列表
*/
export const SUPPORTED_LANGUAGES: SupportedLanguage[] = [
'text',
'javascript',
'typescript',
'python',
'html',
'css',
'json',
'markdown',
'shell',
'py',
'html',
'sql',
'yaml',
'xml',
'php',
'md',
'java',
'php',
'css',
'xml',
'cpp',
'c',
'rs',
'cs',
'rb',
'sh',
'yaml',
'toml',
'go',
'rust',
'ruby'
'clj',
'ex',
'erl',
'js',
'ts',
'swift',
'kt',
'groovy',
'ps1',
'dart',
'scala'
];
/**
@@ -134,9 +154,6 @@ export interface BlockStateUpdate {
operation?: BlockOperation;
}
// 块导航方向
export type NavigationDirection = 'next' | 'previous' | 'first' | 'last';
// 语言检测结果
export interface LanguageDetectionResult {
language: SupportedLanguage;