🎨 Update
This commit is contained in:
198
frontend/package-lock.json
generated
198
frontend/package-lock.json
generated
@@ -41,8 +41,10 @@
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vueuse/core": "^13.3.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"colors-named": "^1.0.2",
|
||||
"colors-named-hex": "^1.0.2",
|
||||
"hsl-matcher": "^1.2.4",
|
||||
"pinia": "^3.0.2",
|
||||
"pinia-plugin-persistedstate": "^4.3.0",
|
||||
"sass": "^1.89.1",
|
||||
"uuid": "^11.1.0",
|
||||
"vue": "^3.5.16",
|
||||
@@ -1415,7 +1417,10 @@
|
||||
"version": "3.17.4",
|
||||
"resolved": "https://registry.npmmirror.com/@nuxt/kit/-/kit-3.17.4.tgz",
|
||||
"integrity": "sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"c12": "^3.0.4",
|
||||
"consola": "^3.4.2",
|
||||
@@ -1448,7 +1453,10 @@
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.4.tgz",
|
||||
"integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
@@ -2033,6 +2041,7 @@
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.7.tgz",
|
||||
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
@@ -2608,6 +2617,7 @@
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@@ -2751,7 +2761,10 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/c12/-/c12-3.0.4.tgz",
|
||||
"integrity": "sha512-t5FaZTYbbCtvxuZq9xxIruYydrAGsJ+8UdP0pZzMiK2xl/gNiSOy0OxhLzHUEEb0m1QXYqfzfvyIFEmz/g9lqg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.3",
|
||||
"confbox": "^0.2.2",
|
||||
@@ -2821,7 +2834,10 @@
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmmirror.com/citty/-/citty-0.1.6.tgz",
|
||||
"integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"consola": "^3.2.3"
|
||||
}
|
||||
@@ -2861,6 +2877,30 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/colors-named": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/colors-named/-/colors-named-1.0.2.tgz",
|
||||
"integrity": "sha512-2ANq2r393PV9njYUD66UdfBcxR1slMqRA3QRTWgCx49JoCJ+kOhyfbQYxKJbPZQIhZUcNjVOs5AlyY1WwXec3w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/colors-named-hex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/colors-named-hex/-/colors-named-hex-1.0.2.tgz",
|
||||
"integrity": "sha512-k6kq1e1pUCQvSVwIaGFq2l0LrkAPQZWyeuZn1Z8nOiYSEZiKoFj4qx690h2Kd34DFl9Me0gKS6MUwAMBJj8nuA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -2872,13 +2912,17 @@
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.2.2.tgz",
|
||||
"integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/consola": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmmirror.com/consola/-/consola-3.4.2.tgz",
|
||||
"integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.10.0"
|
||||
}
|
||||
@@ -2970,23 +3014,23 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deep-pick-omit": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/deep-pick-omit/-/deep-pick-omit-1.2.1.tgz",
|
||||
"integrity": "sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/defu": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/defu/-/defu-6.1.4.tgz",
|
||||
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/destr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/destr/-/destr-2.0.5.tgz",
|
||||
"integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "1.0.3",
|
||||
@@ -3005,7 +3049,10 @@
|
||||
"version": "16.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.5.0.tgz",
|
||||
"integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -3029,7 +3076,10 @@
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/errx/-/errx-0.1.0.tgz",
|
||||
"integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.2",
|
||||
@@ -3272,6 +3322,7 @@
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/exsolve/-/exsolve-1.0.5.tgz",
|
||||
"integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
@@ -3418,7 +3469,10 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/giget/-/giget-2.0.0.tgz",
|
||||
"integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"citty": "^0.1.6",
|
||||
"consola": "^3.4.0",
|
||||
@@ -3490,6 +3544,18 @@
|
||||
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/hsl-matcher": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmmirror.com/hsl-matcher/-/hsl-matcher-1.2.4.tgz",
|
||||
"integrity": "sha512-tS7XnJS33Egirm+6cI+Z/kH/aVZt94uxGlJxOZlGql2/yqbAzPg3zHHnTnVN4cVpoJnEYEGq+LE3iXbuUIe8BA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
|
||||
@@ -3602,7 +3668,10 @@
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.4.2.tgz",
|
||||
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
@@ -3611,7 +3680,10 @@
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.1.tgz",
|
||||
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
@@ -3661,7 +3733,10 @@
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz",
|
||||
"integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
@@ -3670,7 +3745,10 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/knitwork/-/knitwork-1.2.0.tgz",
|
||||
"integrity": "sha512-xYSH7AvuQ6nXkq42x0v5S8/Iry+cfulBz/DJQzhIyESdLD7425jXsPy4vn5cCXU+HhRN2kVw51Vd1K6/By4BQg==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/levn": {
|
||||
"version": "0.4.1",
|
||||
@@ -3690,6 +3768,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-1.1.1.tgz",
|
||||
"integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mlly": "^1.7.4",
|
||||
@@ -3789,6 +3868,7 @@
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.4.tgz",
|
||||
"integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.14.0",
|
||||
@@ -3801,12 +3881,14 @@
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz",
|
||||
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mlly/node_modules/pkg-types": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.3.1.tgz",
|
||||
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"confbox": "^0.1.8",
|
||||
@@ -3864,7 +3946,10 @@
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmmirror.com/node-fetch-native/-/node-fetch-native-1.6.6.tgz",
|
||||
"integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
@@ -3893,7 +3978,10 @@
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/nypm/-/nypm-0.6.0.tgz",
|
||||
"integrity": "sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"citty": "^0.1.6",
|
||||
"consola": "^3.4.0",
|
||||
@@ -3912,7 +4000,10 @@
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://registry.npmmirror.com/ohash/-/ohash-2.0.11.tgz",
|
||||
"integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
@@ -4008,6 +4099,7 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz",
|
||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/perfect-debounce": {
|
||||
@@ -4056,34 +4148,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pinia-plugin-persistedstate": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.3.0.tgz",
|
||||
"integrity": "sha512-x9wxpHj6iFDj5ITQJ3rj6+KesEqyRk/vqcE3WE+VGfetleV9Zufqwa9qJ6AkA5wmRSQEp7BTA1us/MDVTRHFFw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nuxt/kit": "^3.17.2",
|
||||
"deep-pick-omit": "^1.2.1",
|
||||
"defu": "^6.1.4",
|
||||
"destr": "^2.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@pinia/nuxt": ">=0.10.0",
|
||||
"pinia": ">=3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@pinia/nuxt": {
|
||||
"optional": true
|
||||
},
|
||||
"pinia": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-types": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-2.1.0.tgz",
|
||||
"integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"confbox": "^0.2.1",
|
||||
@@ -4157,6 +4226,7 @@
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmmirror.com/quansync/-/quansync-0.2.10.tgz",
|
||||
"integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -4194,7 +4264,10 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/rc9/-/rc9-2.1.2.tgz",
|
||||
"integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"defu": "^6.1.4",
|
||||
"destr": "^2.0.3"
|
||||
@@ -4328,12 +4401,16 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
|
||||
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
@@ -4387,7 +4464,10 @@
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.9.0.tgz",
|
||||
"integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
@@ -4406,7 +4486,10 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-3.0.0.tgz",
|
||||
"integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"js-tokens": "^9.0.1"
|
||||
},
|
||||
@@ -4449,12 +4532,16 @@
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-0.3.2.tgz",
|
||||
"integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
|
||||
"license": "MIT"
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.14.tgz",
|
||||
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fdir": "^6.4.4",
|
||||
@@ -4471,6 +4558,7 @@
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.4.tgz",
|
||||
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"picomatch": "^3 || ^4"
|
||||
@@ -4485,6 +4573,7 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -4573,13 +4662,17 @@
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.6.1.tgz",
|
||||
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unctx": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/unctx/-/unctx-2.4.1.tgz",
|
||||
"integrity": "sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.14.0",
|
||||
"estree-walker": "^3.0.3",
|
||||
@@ -4591,7 +4684,10 @@
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0"
|
||||
}
|
||||
@@ -4607,7 +4703,10 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/unimport/-/unimport-5.0.1.tgz",
|
||||
"integrity": "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.14.1",
|
||||
"escape-string-regexp": "^5.0.0",
|
||||
@@ -4632,7 +4731,10 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -4644,7 +4746,10 @@
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0"
|
||||
}
|
||||
@@ -4653,7 +4758,10 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -4665,6 +4773,7 @@
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-2.3.5.tgz",
|
||||
"integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.14.1",
|
||||
@@ -4679,6 +4788,7 @@
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
|
||||
"integrity": "sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pathe": "^2.0.2",
|
||||
@@ -4695,6 +4805,7 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -4794,6 +4905,7 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -4806,7 +4918,10 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/untyped/-/untyped-2.0.0.tgz",
|
||||
"integrity": "sha512-nwNCjxJTjNuLCgFr42fEak5OcLuB3ecca+9ksPFNvtfYSLpjf+iJqSIaSnIile6ZPbKYxI5k2AfXqeopGudK/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"citty": "^0.1.6",
|
||||
"defu": "^6.1.4",
|
||||
@@ -5078,6 +5193,7 @@
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
|
||||
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/which": {
|
||||
|
@@ -45,8 +45,10 @@
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vueuse/core": "^13.3.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"colors-named": "^1.0.2",
|
||||
"colors-named-hex": "^1.0.2",
|
||||
"hsl-matcher": "^1.2.4",
|
||||
"pinia": "^3.0.2",
|
||||
"pinia-plugin-persistedstate": "^4.3.0",
|
||||
"sass": "^1.89.1",
|
||||
"uuid": "^11.1.0",
|
||||
"vue": "^3.5.16",
|
||||
|
@@ -4,10 +4,7 @@ import '@/assets/styles/index.css';
|
||||
import {createPinia} from 'pinia';
|
||||
import i18n from './i18n';
|
||||
import router from './router';
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
|
||||
const pinia = createPinia()
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
const app = createApp(App);
|
||||
app.use(pinia)
|
||||
app.use(i18n);
|
||||
|
@@ -24,9 +24,11 @@ import {defaultKeymap, history, historyKeymap,} from '@codemirror/commands';
|
||||
import {highlightSelectionMatches} from '@codemirror/search';
|
||||
import {autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap} from '@codemirror/autocomplete';
|
||||
import {lintKeymap} from '@codemirror/lint';
|
||||
import { vscodeSearch, customSearchKeymap, searchVisibilityField } from '../plugins/vscodeSearch';
|
||||
import { vscodeSearch, customSearchKeymap, searchVisibilityField } from './vscodeSearch';
|
||||
|
||||
import { hyperLink } from './hyperlink';
|
||||
import { color } from './colorSelector';
|
||||
|
||||
import { hyperLink } from '../plugins/hyperlink';
|
||||
// 基本编辑器设置,包含常用扩展
|
||||
export const createBasicSetup = (): Extension[] => {
|
||||
return [
|
||||
@@ -35,6 +37,7 @@ export const createBasicSetup = (): Extension[] => {
|
||||
searchVisibilityField,
|
||||
|
||||
hyperLink,
|
||||
color,
|
||||
|
||||
// 基础UI
|
||||
lineNumbers(),
|
||||
@@ -67,7 +70,7 @@ export const createBasicSetup = (): Extension[] => {
|
||||
|
||||
// 键盘映射
|
||||
keymap.of([
|
||||
...customSearchKeymap as KeyBinding[],
|
||||
...customSearchKeymap,
|
||||
...closeBracketsKeymap,
|
||||
...defaultKeymap,
|
||||
...historyKeymap,
|
||||
|
301
frontend/src/views/editor/extensions/colorSelector/index.ts
Normal file
301
frontend/src/views/editor/extensions/colorSelector/index.ts
Normal file
@@ -0,0 +1,301 @@
|
||||
import { ViewPlugin, EditorView, ViewUpdate, WidgetType, Decoration, DecorationSet } from '@codemirror/view';
|
||||
import { Extension, Range } from '@codemirror/state';
|
||||
import { syntaxTree } from '@codemirror/language';
|
||||
import colors from 'colors-named';
|
||||
import hexs from 'colors-named-hex';
|
||||
import hslMatcher, { hlsStringToRGB, RGBAColor } from 'hsl-matcher';
|
||||
import { toFullHex, rgbToHex, hexToRgb, RGBToHSL } from './utils';
|
||||
|
||||
export enum ColorType {
|
||||
rgb = 'RGB',
|
||||
hex = 'HEX',
|
||||
named = 'NAMED',
|
||||
hsl = 'HSL',
|
||||
}
|
||||
|
||||
export interface ColorState {
|
||||
from: number;
|
||||
to: number;
|
||||
alpha: string;
|
||||
colorType: ColorType;
|
||||
}
|
||||
|
||||
const colorState = new WeakMap<HTMLInputElement, ColorState>();
|
||||
|
||||
type GetArrayElementType<T extends readonly any[]> = T extends readonly (infer U)[] ? U : never;
|
||||
|
||||
function colorDecorations(view: EditorView) {
|
||||
const widgets: Array<Range<Decoration>> = [];
|
||||
for (const range of view.visibleRanges) {
|
||||
syntaxTree(view.state).iterate({
|
||||
from: range.from,
|
||||
to: range.to,
|
||||
enter: ({ type, from, to }) => {
|
||||
const callExp: string = view.state.doc.sliceString(from, to);
|
||||
/**
|
||||
* ```
|
||||
* rgb(0 107 128, .5); ❌ ❌ ❌
|
||||
* rgb( 0 107 128 ); ✅ ✅ ✅
|
||||
* RGB( 0 107 128 ); ✅ ✅ ✅
|
||||
* Rgb( 0 107 128 ); ✅ ✅ ✅
|
||||
* rgb( 0 107 128 / ); ❌ ❌ ❌
|
||||
* rgb( 0 107 128 / 60%); ✅ ✅ ✅
|
||||
* rgb(0,107,128 / 60%); ❌ ❌ ❌
|
||||
* rgb( 255, 255, 255 ) ✅ ✅ ✅
|
||||
* rgba( 255, 255, 255 ) ✅ ✅ ✅
|
||||
* rgba( 255, 255 , 255, ) ❌ ❌ ❌
|
||||
* rgba( 255, 255 , 255, .5 ) ✅ ✅ ✅
|
||||
* rgba( 255 255 255 / 0.5 ); ✅ ✅ ✅
|
||||
* rgba( 255 255 255 0.5 ); ❌ ❌ ❌
|
||||
* rgba( 255 255 255 / ); ❌ ❌ ❌
|
||||
* ```
|
||||
*/
|
||||
if (type.name === 'CallExpression' && callExp.startsWith('rgb')) {
|
||||
const match =
|
||||
/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,?\s*(\d{1,3})\s*(,\s*\d*\.\d*\s*)?\)/i.exec(callExp) ||
|
||||
/rgba?\(\s*(\d{1,3})\s*(\d{1,3})\s*(\d{1,3})\s*(\/?\s*\d+%)?(\/\s*\d+\.\d\s*)?\)/i.exec(callExp);
|
||||
if (!match) return;
|
||||
const [_, r, g, b, a] = match;
|
||||
const hex = rgbToHex(Number(r), Number(g), Number(b));
|
||||
const widget = Decoration.widget({
|
||||
widget: new ColorWidget({
|
||||
colorType: ColorType.rgb,
|
||||
color: hex,
|
||||
colorRaw: callExp,
|
||||
from,
|
||||
to,
|
||||
alpha: a ? a.replace(/(\/|,)/g, '') : '',
|
||||
}),
|
||||
side: 0,
|
||||
});
|
||||
widgets.push(widget.range(from));
|
||||
} else if (type.name === 'CallExpression' && hslMatcher(callExp)) {
|
||||
/**
|
||||
* # valid
|
||||
* hsl(240, 100%, 50%) // ✅ comma separated
|
||||
* hsl(240, 100%, 50%, 0.1) // ✅ comma separated with opacity
|
||||
* hsl(240, 100%, 50%, 10%) // ✅ comma separated with % opacity
|
||||
* hsl(240,100%,50%,0.1) // ✅ comma separated without spaces
|
||||
* hsl(180deg, 100%, 50%, 0.1) // ✅ hue with 'deg'
|
||||
* hsl(3.14rad, 100%, 50%, 0.1) // ✅ hue with 'rad'
|
||||
* hsl(200grad, 100%, 50%, 0.1) // ✅ hue with 'grad'
|
||||
* hsl(0.5turn, 100%, 50%, 0.1) // ✅ hue with 'turn'
|
||||
* hsl(-240, -100%, -50%, -0.1) // ✅ negative values
|
||||
* hsl(+240, +100%, +50%, +0.1) // ✅ explicit positive sign
|
||||
* hsl(240.5, 99.99%, 49.999%, 0.9999) // ✅ non-integer values
|
||||
* hsl(.9, .99%, .999%, .9999) // ✅ fraction w/o leading zero
|
||||
* hsl(0240, 0100%, 0050%, 01) // ✅ leading zeros
|
||||
* hsl(240.0, 100.00%, 50.000%, 1.0000) // ✅ trailing decimal zeros
|
||||
* hsl(2400, 1000%, 1000%, 10) // ✅ out of range values
|
||||
* hsl(-2400.01deg, -1000.5%, -1000.05%, -100) // ✅ combination of above
|
||||
* hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3) // ✅ scientific notation
|
||||
* hsl(240 100% 50%) // ✅ space separated (CSS Color Level 4)
|
||||
* hsl(240 100% 50% / 0.1) // ✅ space separated with opacity
|
||||
* hsla(240, 100%, 50%) // ✅ hsla() alias
|
||||
* hsla(240, 100%, 50%, 0.1) // ✅ hsla() with opacity
|
||||
* HSL(240Deg, 100%, 50%) // ✅ case insensitive
|
||||
*/
|
||||
const match = hlsStringToRGB(callExp) as RGBAColor;
|
||||
if (!match) return;
|
||||
const { r, g, b } = match;
|
||||
const hex = rgbToHex(Number(r), Number(g), Number(b));
|
||||
const widget = Decoration.widget({
|
||||
widget: new ColorWidget({
|
||||
colorType: ColorType.hsl,
|
||||
color: hex,
|
||||
colorRaw: callExp,
|
||||
from,
|
||||
to,
|
||||
alpha: match.a ? match.a.toString() : '',
|
||||
}),
|
||||
side: 0,
|
||||
});
|
||||
widgets.push(widget.range(from));
|
||||
} else if (type.name === 'ColorLiteral') {
|
||||
const [color, alpha] = toFullHex(callExp);
|
||||
const widget = Decoration.widget({
|
||||
widget: new ColorWidget({
|
||||
colorType: ColorType.hex,
|
||||
color,
|
||||
colorRaw: callExp,
|
||||
from,
|
||||
to,
|
||||
alpha,
|
||||
}),
|
||||
side: 0,
|
||||
});
|
||||
widgets.push(widget.range(from));
|
||||
} else if (type.name === 'ValueName') {
|
||||
const name = callExp as unknown as GetArrayElementType<typeof colors>;
|
||||
if (colors.includes(name)) {
|
||||
const widget = Decoration.widget({
|
||||
widget: new ColorWidget({
|
||||
colorType: ColorType.named,
|
||||
color: hexs[colors.indexOf(name)],
|
||||
colorRaw: callExp,
|
||||
from,
|
||||
to,
|
||||
alpha: '',
|
||||
}),
|
||||
side: 0,
|
||||
});
|
||||
widgets.push(widget.range(from));
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
return Decoration.set(widgets);
|
||||
}
|
||||
|
||||
class ColorWidget extends WidgetType {
|
||||
private readonly state: ColorState;
|
||||
private readonly color: string;
|
||||
private readonly colorRaw: string;
|
||||
|
||||
constructor({
|
||||
color,
|
||||
colorRaw,
|
||||
...state
|
||||
}: ColorState & {
|
||||
color: string;
|
||||
colorRaw: string;
|
||||
}) {
|
||||
super();
|
||||
this.state = state;
|
||||
this.color = color;
|
||||
this.colorRaw = colorRaw;
|
||||
}
|
||||
eq(other: ColorWidget) {
|
||||
return (
|
||||
other.state.colorType === this.state.colorType &&
|
||||
other.color === this.color &&
|
||||
other.state.from === this.state.from &&
|
||||
other.state.to === this.state.to &&
|
||||
other.state.alpha === this.state.alpha
|
||||
);
|
||||
}
|
||||
toDOM() {
|
||||
const picker = document.createElement('input');
|
||||
colorState.set(picker, this.state);
|
||||
picker.type = 'color';
|
||||
picker.value = this.color;
|
||||
picker.dataset['color'] = this.color;
|
||||
picker.dataset['colorraw'] = this.colorRaw;
|
||||
const wrapper = document.createElement('span');
|
||||
wrapper.appendChild(picker);
|
||||
wrapper.dataset['color'] = this.color;
|
||||
wrapper.style.backgroundColor = this.colorRaw;
|
||||
return wrapper;
|
||||
}
|
||||
ignoreEvent() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const colorView = (showPicker: boolean = true) =>
|
||||
ViewPlugin.fromClass(
|
||||
class ColorView {
|
||||
decorations: DecorationSet;
|
||||
constructor(view: EditorView) {
|
||||
this.decorations = colorDecorations(view);
|
||||
}
|
||||
update(update: ViewUpdate) {
|
||||
if (update.docChanged || update.viewportChanged) {
|
||||
this.decorations = colorDecorations(update.view);
|
||||
}
|
||||
const readOnly = update.view.contentDOM.ariaReadOnly === 'true';
|
||||
const editable = update.view.contentDOM.contentEditable === 'true';
|
||||
|
||||
const canBeEdited = readOnly === false && editable;
|
||||
this.changePicker(update.view, canBeEdited);
|
||||
}
|
||||
changePicker(view: EditorView, canBeEdited: boolean) {
|
||||
const doms = view.contentDOM.querySelectorAll('input[type=color]');
|
||||
doms.forEach((inp) => {
|
||||
if (!showPicker) {
|
||||
inp.setAttribute('disabled', '');
|
||||
} else {
|
||||
canBeEdited ? inp.removeAttribute('disabled') : inp.setAttribute('disabled', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
decorations: (v) => v.decorations,
|
||||
eventHandlers: {
|
||||
change: (e, view) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (
|
||||
target.nodeName !== 'INPUT' ||
|
||||
!target.parentElement ||
|
||||
(!target.dataset.color && !target.dataset.colorraw)
|
||||
)
|
||||
return false;
|
||||
const data = colorState.get(target)!;
|
||||
const value = target.value;
|
||||
const rgb = hexToRgb(value);
|
||||
const colorraw = target.dataset.colorraw;
|
||||
const slash = (target.dataset.colorraw || '').indexOf('/') > 4;
|
||||
const comma = (target.dataset.colorraw || '').indexOf(',') > 4;
|
||||
let converted = target.value;
|
||||
if (data.colorType === ColorType.rgb) {
|
||||
let funName = colorraw?.match(/^(rgba?)/) ? colorraw?.match(/^(rgba?)/)![0] : undefined;
|
||||
if (comma) {
|
||||
converted = rgb
|
||||
? `${funName}(${rgb.r}, ${rgb.g}, ${rgb.b}${data.alpha ? ', ' + data.alpha.trim() : ''})`
|
||||
: value;
|
||||
} else if (slash) {
|
||||
converted = rgb
|
||||
? `${funName}(${rgb.r} ${rgb.g} ${rgb.b}${data.alpha ? ' / ' + data.alpha.trim() : ''})`
|
||||
: value;
|
||||
} else {
|
||||
converted = rgb ? `${funName}(${rgb.r} ${rgb.g} ${rgb.b})` : value;
|
||||
}
|
||||
} else if (data.colorType === ColorType.hsl) {
|
||||
const rgb = hexToRgb(value);
|
||||
if (rgb) {
|
||||
const { h, s, l } = RGBToHSL(rgb?.r, rgb?.g, rgb?.b);
|
||||
converted = `hsl(${h}deg ${s}% ${l}%${data.alpha ? ' / ' + data.alpha : ''})`;
|
||||
}
|
||||
}
|
||||
view.dispatch({
|
||||
changes: {
|
||||
from: data.from,
|
||||
to: data.to,
|
||||
insert: converted,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
export const colorTheme = EditorView.baseTheme({
|
||||
'span[data-color]': {
|
||||
width: '12px',
|
||||
height: '12px',
|
||||
display: 'inline-block',
|
||||
borderRadius: '2px',
|
||||
marginRight: '0.5ch',
|
||||
outline: '1px solid #00000040',
|
||||
overflow: 'hidden',
|
||||
verticalAlign: 'middle',
|
||||
marginTop: '-2px',
|
||||
},
|
||||
'span[data-color] input[type="color"]': {
|
||||
background: 'transparent',
|
||||
display: 'block',
|
||||
border: 'none',
|
||||
outline: '0',
|
||||
paddingLeft: '24px',
|
||||
height: '12px',
|
||||
},
|
||||
'span[data-color] input[type="color"]::-webkit-color-swatch': {
|
||||
border: 'none',
|
||||
paddingLeft: '24px',
|
||||
},
|
||||
});
|
||||
|
||||
export const color: Extension = [colorView(), colorTheme];
|
64
frontend/src/views/editor/extensions/colorSelector/utils.ts
Normal file
64
frontend/src/views/editor/extensions/colorSelector/utils.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
export function toFullHex(color: string): string[] {
|
||||
if (color.length === 4) {
|
||||
// 3-char hex
|
||||
return [`#${color[1].repeat(2)}${color[2].repeat(2)}${color[3].repeat(2)}`, ''];
|
||||
}
|
||||
|
||||
if (color.length === 5) {
|
||||
// 4-char hex (alpha)
|
||||
return [`#${color[1].repeat(2)}${color[2].repeat(2)}${color[3].repeat(2)}`, color[4].repeat(2)];
|
||||
}
|
||||
|
||||
if (color.length === 9) {
|
||||
// 8-char hex (alpha)
|
||||
return [`#${color.slice(1, -2)}`, color.slice(-2)];
|
||||
}
|
||||
|
||||
return [color, ''];
|
||||
}
|
||||
/** https://stackoverflow.com/a/5624139/1334703 */
|
||||
export function rgbToHex(r: number, g: number, b: number) {
|
||||
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
||||
}
|
||||
|
||||
/** https://stackoverflow.com/a/5624139/1334703 */
|
||||
export function hexToRgb(hex: string) {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result
|
||||
? {
|
||||
r: parseInt(result[1], 16),
|
||||
g: parseInt(result[2], 16),
|
||||
b: parseInt(result[3], 16),
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
/** https://css-tricks.com/converting-color-spaces-in-javascript/#aa-rgb-to-hsl */
|
||||
export function RGBToHSL(r: number, g: number, b: number) {
|
||||
(r /= 255), (g /= 255), (b /= 255);
|
||||
const max = Math.max(r, g, b),
|
||||
min = Math.min(r, g, b);
|
||||
let h = 0,
|
||||
s,
|
||||
l = (max + min) / 2;
|
||||
|
||||
if (max == min) {
|
||||
h = s = 0; // achromatic
|
||||
} else {
|
||||
const d = max - min;
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
switch (max) {
|
||||
case r:
|
||||
h = (g - b) / d + (g < b ? 6 : 0);
|
||||
break;
|
||||
case g:
|
||||
h = (b - r) / d + 2;
|
||||
break;
|
||||
case b:
|
||||
h = (r - g) / d + 4;
|
||||
break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
return { h: Math.floor(h * 360), s: Math.floor(s * 100), l: Math.floor(l * 100) };
|
||||
}
|
@@ -127,8 +127,8 @@ export class CustomSearchPanel {
|
||||
|
||||
if (query.regexp) {
|
||||
try {
|
||||
this.regexCursor = new RegExpCursor(state.doc, query.search)
|
||||
this.searchCursor = undefined;
|
||||
this.regexCursor = new RegExpCursor(state.doc, query.search)
|
||||
this.searchCursor = undefined;
|
||||
} catch (error) {
|
||||
// 如果正则表达式无效,清空匹配结果并显示错误状态
|
||||
console.warn("Invalid regular expression:", query.search, error);
|
||||
@@ -168,17 +168,17 @@ export class CustomSearchPanel {
|
||||
}
|
||||
else if (this.regexCursor) {
|
||||
try {
|
||||
const matchWord = this.regexpWordTest(state.charCategorizer(state.selection.main.head))
|
||||
const matchWord = this.regexpWordTest(state.charCategorizer(state.selection.main.head))
|
||||
|
||||
while (!this.regexCursor.done) {
|
||||
this.regexCursor.next();
|
||||
while (!this.regexCursor.done) {
|
||||
this.regexCursor.next();
|
||||
|
||||
if (!this.regexCursor.done) {
|
||||
const { from, to, match } = this.regexCursor.value;
|
||||
if (!this.regexCursor.done) {
|
||||
const { from, to, match } = this.regexCursor.value;
|
||||
|
||||
if (!query.wholeWord || matchWord(from, to, match)) {
|
||||
this.matches.push({ from, to });
|
||||
}
|
||||
if (!query.wholeWord || matchWord(from, to, match)) {
|
||||
this.matches.push({ from, to });
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -222,19 +222,19 @@ export class CustomSearchPanel {
|
||||
|
||||
commit() {
|
||||
try {
|
||||
const newQuery = new SearchQuery({
|
||||
search: this.searchField.value,
|
||||
replace: this.replaceField.value,
|
||||
caseSensitive: this.matchCase,
|
||||
regexp: this.useRegex,
|
||||
wholeWord: this.matchWord,
|
||||
})
|
||||
const newQuery = new SearchQuery({
|
||||
search: this.searchField.value,
|
||||
replace: this.replaceField.value,
|
||||
caseSensitive: this.matchCase,
|
||||
regexp: this.useRegex,
|
||||
wholeWord: this.matchWord,
|
||||
})
|
||||
|
||||
let query = getSearchQuery(this.view.state)
|
||||
if (!newQuery.eq(query)) {
|
||||
this.view.dispatch({
|
||||
effects: setSearchQuery.of(newQuery)
|
||||
})
|
||||
let query = getSearchQuery(this.view.state)
|
||||
if (!newQuery.eq(query)) {
|
||||
this.view.dispatch({
|
||||
effects: setSearchQuery.of(newQuery)
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
// 如果创建SearchQuery时出错(通常是无效的正则表达式),记录错误但不中断程序
|
||||
@@ -367,7 +367,7 @@ export class CustomSearchPanel {
|
||||
});
|
||||
|
||||
// 重新查找匹配项
|
||||
this.findMatchesAndSelectClosest(this.view.state);
|
||||
this.findMatchesAndSelectClosest(this.view.state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -392,7 +392,7 @@ export class CustomSearchPanel {
|
||||
});
|
||||
|
||||
// 重新查找匹配项
|
||||
this.findMatchesAndSelectClosest(this.view.state);
|
||||
this.findMatchesAndSelectClosest(this.view.state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,7 +592,7 @@ export class CustomSearchPanel {
|
||||
if (visible) {
|
||||
// 使用 setTimeout 确保DOM已经渲染
|
||||
setTimeout(() => {
|
||||
this.searchField.focus();
|
||||
this.searchField.focus();
|
||||
this.searchField.select();
|
||||
}, 0);
|
||||
}
|
@@ -72,10 +72,10 @@ export const customSearchKeymap: KeyBinding[] = [
|
||||
key: "ArrowLeft",
|
||||
run: searchMoveCursorLeft,
|
||||
scope: 'search'
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
key: "ArrowRight",
|
||||
run: searchMoveCursorRight,
|
||||
scope: 'search'
|
||||
},
|
||||
},
|
||||
];
|
Reference in New Issue
Block a user