Обновление сборки и исходного кода

This commit is contained in:
root 2025-11-16 14:51:59 +07:00
parent 7d115e1845
commit 14b9165681
32 changed files with 2000 additions and 1234 deletions

View File

@ -19,7 +19,9 @@
"body-parser": "^2.2.0", "body-parser": "^2.2.0",
"codemirror": "^6.0.2", "codemirror": "^6.0.2",
"connect-sqlite3": "^0.9.16", "connect-sqlite3": "^0.9.16",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"csurf": "^1.11.0",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"express": "^5.1.0", "express": "^5.1.0",
"express-rate-limit": "^8.1.0", "express-rate-limit": "^8.1.0",
@ -1713,6 +1715,25 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/cookie-parser": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
"license": "MIT",
"dependencies": {
"cookie": "0.7.2",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT"
},
"node_modules/cookie-signature": { "node_modules/cookie-signature": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
@ -1738,6 +1759,100 @@
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
}, },
"node_modules/csrf": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz",
"integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==",
"license": "MIT",
"dependencies": {
"rndm": "1.2.0",
"tsscmp": "1.0.6",
"uid-safe": "2.1.5"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/csurf": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz",
"integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==",
"deprecated": "This package is archived and no longer maintained. For support, visit https://github.com/expressjs/express/discussions",
"license": "MIT",
"dependencies": {
"cookie": "0.4.0",
"cookie-signature": "1.0.6",
"csrf": "3.1.0",
"http-errors": "~1.7.3"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/csurf/node_modules/cookie": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/csurf/node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT"
},
"node_modules/csurf/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/csurf/node_modules/http-errors": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
"license": "MIT",
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/csurf/node_modules/setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
"license": "ISC"
},
"node_modules/csurf/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/csurf/node_modules/toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
},
"node_modules/data-uri-to-buffer": { "node_modules/data-uri-to-buffer": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
@ -1947,6 +2062,7 @@
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
"peer": true,
"dependencies": { "dependencies": {
"accepts": "^2.0.0", "accepts": "^2.0.0",
"body-parser": "^2.2.0", "body-parser": "^2.2.0",
@ -3437,6 +3553,12 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/rndm": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz",
"integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==",
"license": "MIT"
},
"node_modules/router": { "node_modules/router": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
@ -3952,6 +4074,15 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"node_modules/tsscmp": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
"license": "MIT",
"engines": {
"node": ">=0.6.x"
}
},
"node_modules/tunnel-agent": { "node_modules/tunnel-agent": {
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",

View File

@ -25,7 +25,9 @@
"body-parser": "^2.2.0", "body-parser": "^2.2.0",
"codemirror": "^6.0.2", "codemirror": "^6.0.2",
"connect-sqlite3": "^0.9.16", "connect-sqlite3": "^0.9.16",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"csurf": "^1.11.0",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"express": "^5.1.0", "express": "^5.1.0",
"express-rate-limit": "^8.1.0", "express-rate-limit": "^8.1.0",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -158,8 +158,8 @@
<!-- Manifest --> <!-- Manifest -->
<link rel="manifest" href="/manifest.json" /> <link rel="manifest" href="/manifest.json" />
<script type="module" crossorigin src="/assets/index-BLHAueVj.js"></script> <script type="module" crossorigin src="/assets/index-BeJxT3YH.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-PWucW8RD.css"> <link rel="stylesheet" crossorigin href="/assets/index-By_GFjEF.css">
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head> <link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
<body> <body>
<div id="root"> <div id="root">

View File

@ -1 +1 @@
if(!self.define){let e,n={};const i=(i,c)=>(i=new URL(i+".js",c).href,n[i]||new Promise(n=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=n,document.head.appendChild(e)}else e=i,importScripts(i),n()}).then(()=>{let e=n[i];if(!e)throw new Error(`Module ${i} didnt register its module`);return e}));self.define=(c,s)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(n[o])return;let a={};const r=e=>i(e,o),d={module:{uri:o},exports:a,require:r};n[o]=Promise.all(c.map(e=>d[e]||r(e))).then(e=>(s(...e),a))}}define(["./workbox-40c80ae4"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"assets/index-BLHAueVj.js",revision:"a554119eeb8e2517fbf5b56f3056f821"},{url:"assets/index-PWucW8RD.css",revision:"d9c0b2036bfdcfb70738c2c7fc47cd92"},{url:"icon.svg",revision:"537ae73d8f9e90e6a01816aa6d527d16"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-16x16.png",revision:"101c13808e9fd0956f247bc446a8ac1e"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-32x32.png",revision:"22ee5d42535bc339ab0e19cb496378a5"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"icons/icon-48x48.png",revision:"cfdd3bebd931375f2e0277d638ec8781"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"index.html",revision:"9a7779e0b82393809d2b49570f7f35a0"},{url:"logo.svg",revision:"11616ede8898b4c24203e331b3ec6dc3"},{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"icon.svg",revision:"537ae73d8f9e90e6a01816aa6d527d16"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"manifest.webmanifest",revision:"1c071cadebd7a1b0dc1eeb0270e73fb8"}],{ignoreURLParametersMatching:[/^utm_/,/^fbclid$/]}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api/,/^\/uploads/]})),e.registerRoute(({request:e})=>"navigate"===e.mode,new e.CacheFirst({cacheName:"pages-cache",plugins:[new e.ExpirationPlugin({maxEntries:10,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET"),e.registerRoute(/\.html$/,new e.CacheFirst({cacheName:"html-cache",plugins:[new e.ExpirationPlugin({maxEntries:10,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET"),e.registerRoute(/^https:\/\/api\./,new e.NetworkFirst({cacheName:"api-cache",plugins:[new e.ExpirationPlugin({maxEntries:50,maxAgeSeconds:3600})]}),"GET"),e.registerRoute(/\/api\//,new e.NetworkFirst({cacheName:"api-cache-local",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/uploads\//,new e.CacheFirst({cacheName:"uploads-cache",plugins:[new e.ExpirationPlugin({maxEntries:200,maxAgeSeconds:2592e3})]}),"GET"),e.registerRoute(/\.(?:png|jpg|jpeg|svg|gif|webp)$/,new e.CacheFirst({cacheName:"images-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:2592e3})]}),"GET")}); if(!self.define){let e,n={};const i=(i,c)=>(i=new URL(i+".js",c).href,n[i]||new Promise(n=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=n,document.head.appendChild(e)}else e=i,importScripts(i),n()}).then(()=>{let e=n[i];if(!e)throw new Error(`Module ${i} didnt register its module`);return e}));self.define=(c,s)=>{const a=e||("document"in self?document.currentScript.src:"")||location.href;if(n[a])return;let o={};const d=e=>i(e,a),r={module:{uri:a},exports:o,require:d};n[a]=Promise.all(c.map(e=>r[e]||d(e))).then(e=>(s(...e),o))}}define(["./workbox-40c80ae4"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"assets/index-BeJxT3YH.js",revision:"f4507ca84a94231fa281c54bfb94d3fc"},{url:"assets/index-By_GFjEF.css",revision:"1d226b81e7336346ecda1ed5c10970a1"},{url:"icon.svg",revision:"0ec61aab261526d4c491e887a6f3374e"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-16x16.png",revision:"101c13808e9fd0956f247bc446a8ac1e"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-32x32.png",revision:"22ee5d42535bc339ab0e19cb496378a5"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"icons/icon-48x48.png",revision:"cfdd3bebd931375f2e0277d638ec8781"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"index.html",revision:"375addd678296759444d1a44942d49aa"},{url:"logo.svg",revision:"5962d0d24d9cd26cd8aaff9cb6f54a5a"},{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"icon.svg",revision:"0ec61aab261526d4c491e887a6f3374e"},{url:"icons/icon-192x192.png",revision:"7d86d2d2ada99d7cee015dff0fdcb497"},{url:"icons/icon-512x512.png",revision:"8731edef999b9e7deba310d72a739925"},{url:"icons/icon-72x72.png",revision:"6b3cb1b2537ec91921698260a9c2f47c"},{url:"icons/icon-96x96.png",revision:"7efd757a81217207d981de88ef199d86"},{url:"icons/icon-128x128.png",revision:"fa71db17e345406d5f7d847f88c65ac4"},{url:"icons/icon-144x144.png",revision:"e790ff42758ea1a2a46eb84201630757"},{url:"icons/icon-152x152.png",revision:"88f2400f6617a32cc9cd62c70fb49a05"},{url:"icons/icon-384x384.png",revision:"c601fa602952a903389e5e8f8a699617"},{url:"manifest.webmanifest",revision:"1c071cadebd7a1b0dc1eeb0270e73fb8"}],{ignoreURLParametersMatching:[/^utm_/,/^fbclid$/]}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api/,/^\/uploads/]})),e.registerRoute(({request:e})=>"navigate"===e.mode,new e.CacheFirst({cacheName:"pages-cache",plugins:[new e.ExpirationPlugin({maxEntries:10,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET"),e.registerRoute(/\.html$/,new e.CacheFirst({cacheName:"html-cache",plugins:[new e.ExpirationPlugin({maxEntries:10,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET"),e.registerRoute(/^https:\/\/api\./,new e.NetworkFirst({cacheName:"api-cache",plugins:[new e.ExpirationPlugin({maxEntries:50,maxAgeSeconds:3600})]}),"GET"),e.registerRoute(/\/api\//,new e.NetworkFirst({cacheName:"api-cache-local",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/uploads\//,new e.CacheFirst({cacheName:"uploads-cache",plugins:[new e.ExpirationPlugin({maxEntries:200,maxAgeSeconds:2592e3})]}),"GET"),e.registerRoute(/\.(?:png|jpg|jpeg|svg|gif|webp)$/,new e.CacheFirst({cacheName:"images-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:2592e3})]}),"GET")});

File diff suppressed because one or more lines are too long

18
package-lock.json generated
View File

@ -68,6 +68,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5", "@babel/generator": "^7.28.5",
@ -2672,6 +2673,7 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz",
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==", "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
"devOptional": true, "devOptional": true,
"peer": true,
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
"csstype": "^3.0.2" "csstype": "^3.0.2"
@ -2749,6 +2751,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
"integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/scope-manager": "6.21.0",
"@typescript-eslint/types": "6.21.0", "@typescript-eslint/types": "6.21.0",
@ -2930,6 +2933,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -3195,6 +3199,7 @@
"url": "https://github.com/sponsors/ai" "url": "https://github.com/sponsors/ai"
} }
], ],
"peer": true,
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.8.19", "baseline-browser-mapping": "^2.8.19",
"caniuse-lite": "^1.0.30001751", "caniuse-lite": "^1.0.30001751",
@ -3860,6 +3865,7 @@
"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
@ -5743,6 +5749,7 @@
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
}, },
@ -5754,6 +5761,7 @@
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0", "loose-envify": "^1.1.0",
"scheduler": "^0.23.2" "scheduler": "^0.23.2"
@ -5766,6 +5774,7 @@
"version": "7.65.0", "version": "7.65.0",
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.65.0.tgz", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.65.0.tgz",
"integrity": "sha512-xtOzDz063WcXvGWaHgLNrNzlsdFgtUWcb32E6WFaGTd7kPZG3EeDusjdZfUsPwKCKVXy1ZlntifaHZ4l8pAsmw==", "integrity": "sha512-xtOzDz063WcXvGWaHgLNrNzlsdFgtUWcb32E6WFaGTd7kPZG3EeDusjdZfUsPwKCKVXy1ZlntifaHZ4l8pAsmw==",
"peer": true,
"engines": { "engines": {
"node": ">=18.0.0" "node": ">=18.0.0"
}, },
@ -5781,6 +5790,7 @@
"version": "9.2.0", "version": "9.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
"peer": true,
"dependencies": { "dependencies": {
"@types/use-sync-external-store": "^0.0.6", "@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0" "use-sync-external-store": "^1.4.0"
@ -5841,7 +5851,8 @@
"node_modules/redux": { "node_modules/redux": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"peer": true
}, },
"node_modules/redux-thunk": { "node_modules/redux-thunk": {
"version": "3.1.0", "version": "3.1.0",
@ -6637,6 +6648,7 @@
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
"integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@jridgewell/source-map": "^0.3.3", "@jridgewell/source-map": "^0.3.3",
"acorn": "^8.15.0", "acorn": "^8.15.0",
@ -6807,6 +6819,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@ -6956,6 +6969,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.21.3", "esbuild": "^0.21.3",
"postcss": "^8.4.43", "postcss": "^8.4.43",
@ -7308,6 +7322,7 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1", "fast-uri": "^3.0.1",
@ -7348,6 +7363,7 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
"integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
"dev": true, "dev": true,
"peer": true,
"bin": { "bin": {
"rollup": "dist/bin/rollup" "rollup": "dist/bin/rollup"
}, },

View File

@ -143,14 +143,14 @@ export const GenerateTagsModal: React.FC<GenerateTagsModalProps> = ({
<button <button
className="btn-secondary" className="btn-secondary"
onClick={handleSelectAll} onClick={handleSelectAll}
style={{ fontSize: "12px", padding: "5px 10px", flex: "1 1 auto", minWidth: "100px" }} style={{ fontSize: "12px", padding: "5px 10px", flex: "1 1 auto", minWidth: "100px", textAlign: "center", justifyContent: "center" }}
> >
Выбрать все Выбрать все
</button> </button>
<button <button
className="btn-secondary" className="btn-secondary"
onClick={handleDeselectAll} onClick={handleDeselectAll}
style={{ fontSize: "12px", padding: "5px 10px", flex: "1 1 auto", minWidth: "100px" }} style={{ fontSize: "12px", padding: "5px 10px", flex: "1 1 auto", minWidth: "100px", textAlign: "center", justifyContent: "center" }}
> >
Снять все Снять все
</button> </button>

View File

@ -838,14 +838,15 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
// Предотвращаем появление контекстного меню браузера при выделении текста // Предотвращаем появление контекстного меню браузера при выделении текста
// Но разрешаем его, если редактор пустой (чтобы можно было вставить текст) // Но разрешаем его, если редактор пустой (чтобы можно было вставить текст)
// или если плавающая панель отключена
const handleContextMenu = (e: MouseEvent) => { const handleContextMenu = (e: MouseEvent) => {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
// Проверяем, что событие происходит в textarea // Проверяем, что событие происходит в textarea
if (target === textarea || textarea.contains(target)) { if (target === textarea || textarea.contains(target)) {
const hasText = textarea.value.trim().length > 0; const hasText = textarea.value.trim().length > 0;
const hasSelection = textarea.selectionStart !== textarea.selectionEnd; const hasSelection = textarea.selectionStart !== textarea.selectionEnd;
// Блокируем браузерное меню только если есть текст И есть выделение // Блокируем браузерное меню только если есть текст И есть выделение И плавающая панель включена
if (hasText && hasSelection) { if (floatingToolbarEnabled && hasText && hasSelection) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
@ -1048,13 +1049,14 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
onContextMenu={(e) => { onContextMenu={(e) => {
// Предотвращаем появление контекстного меню браузера при выделении текста // Предотвращаем появление контекстного меню браузера при выделении текста
// Но разрешаем его, если редактор пустой (чтобы можно было вставить текст) // Но разрешаем его, если редактор пустой (чтобы можно было вставить текст)
// или если плавающая панель отключена
const textarea = textareaRef.current; const textarea = textareaRef.current;
if (textarea) { if (textarea) {
const hasText = textarea.value.trim().length > 0; const hasText = textarea.value.trim().length > 0;
const hasSelection = const hasSelection =
textarea.selectionStart !== textarea.selectionEnd; textarea.selectionStart !== textarea.selectionEnd;
// Блокируем браузерное меню только если есть текст И есть выделение // Блокируем браузерное меню только если есть текст И есть выделение И плавающая панель включена
if (hasText && hasSelection) { if (floatingToolbarEnabled && hasText && hasSelection) {
e.preventDefault(); e.preventDefault();
} }
} }

View File

@ -995,14 +995,15 @@ export const NoteItem: React.FC<NoteItemProps> = ({
// Предотвращаем появление контекстного меню браузера при выделении текста // Предотвращаем появление контекстного меню браузера при выделении текста
// Но разрешаем его, если редактор пустой (чтобы можно было вставить текст) // Но разрешаем его, если редактор пустой (чтобы можно было вставить текст)
// или если плавающая панель отключена
const handleContextMenu = (e: MouseEvent) => { const handleContextMenu = (e: MouseEvent) => {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
// Проверяем, что событие происходит в textarea // Проверяем, что событие происходит в textarea
if (target === textarea || textarea.contains(target)) { if (target === textarea || textarea.contains(target)) {
const hasText = textarea.value.trim().length > 0; const hasText = textarea.value.trim().length > 0;
const hasSelection = textarea.selectionStart !== textarea.selectionEnd; const hasSelection = textarea.selectionStart !== textarea.selectionEnd;
// Блокируем браузерное меню только если есть текст И есть выделение // Блокируем браузерное меню только если есть текст И есть выделение И плавающая панель включена
if (hasText && hasSelection) { if (floatingToolbarEnabled && hasText && hasSelection) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
@ -1349,13 +1350,14 @@ export const NoteItem: React.FC<NoteItemProps> = ({
onContextMenu={(e) => { onContextMenu={(e) => {
// Предотвращаем появление контекстного меню браузера при выделении текста // Предотвращаем появление контекстного меню браузера при выделении текста
// Но разрешаем его, если редактор пустой (чтобы можно было вставить текст) // Но разрешаем его, если редактор пустой (чтобы можно было вставить текст)
// или если плавающая панель отключена
const textarea = editTextareaRef.current; const textarea = editTextareaRef.current;
if (textarea) { if (textarea) {
const hasText = textarea.value.trim().length > 0; const hasText = textarea.value.trim().length > 0;
const hasSelection = const hasSelection =
textarea.selectionStart !== textarea.selectionEnd; textarea.selectionStart !== textarea.selectionEnd;
// Блокируем браузерное меню только если есть текст И есть выделение // Блокируем браузерное меню только если есть текст И есть выделение И плавающая панель включена
if (hasText && hasSelection) { if (floatingToolbarEnabled && hasText && hasSelection) {
e.preventDefault(); e.preventDefault();
} }
} }

View File

@ -260,7 +260,7 @@ export const TwoFactorSetup: React.FC<TwoFactorSetupProps> = ({
className="btnSave" className="btnSave"
onClick={handleEnable} onClick={handleEnable}
disabled={isLoading || verificationCode.length !== 6} disabled={isLoading || verificationCode.length !== 6}
style={{ flex: "1 1 auto", minWidth: "120px" }} style={{ flex: "1 1 auto", minWidth: "120px", textAlign: "center", justifyContent: "center" }}
> >
{isLoading ? "Включение..." : "Включить 2FA"} {isLoading ? "Включение..." : "Включить 2FA"}
</button> </button>
@ -271,7 +271,7 @@ export const TwoFactorSetup: React.FC<TwoFactorSetupProps> = ({
setVerificationCode(""); setVerificationCode("");
}} }}
disabled={isLoading} disabled={isLoading}
style={{ flex: "1 1 auto", minWidth: "100px" }} style={{ flex: "1 1 auto", minWidth: "100px", textAlign: "center", justifyContent: "center" }}
> >
Отмена Отмена
</button> </button>
@ -312,7 +312,7 @@ export const TwoFactorSetup: React.FC<TwoFactorSetupProps> = ({
className="btnSave" className="btnSave"
onClick={handleGenerateBackupCodes} onClick={handleGenerateBackupCodes}
disabled={isGeneratingBackupCodes} disabled={isGeneratingBackupCodes}
style={{ flex: "1 1 auto", minWidth: "200px" }} style={{ flex: "1 1 auto", minWidth: "200px", textAlign: "center", justifyContent: "center" }}
> >
{isGeneratingBackupCodes ? ( {isGeneratingBackupCodes ? (
<> <>
@ -327,7 +327,7 @@ export const TwoFactorSetup: React.FC<TwoFactorSetupProps> = ({
<button <button
className="btn-danger" className="btn-danger"
onClick={() => setShowDisableModal(true)} onClick={() => setShowDisableModal(true)}
style={{ flex: "1 1 auto", minWidth: "140px" }} style={{ flex: "1 1 auto", minWidth: "140px", textAlign: "center", justifyContent: "center" }}
> >
<Icon icon="mdi:shield-off" /> Отключить 2FA <Icon icon="mdi:shield-off" /> Отключить 2FA
</button> </button>

View File

@ -277,7 +277,7 @@ const LoginPage: React.FC = () => {
type="submit" type="submit"
className="btnSave" className="btnSave"
disabled={isLoading || !twoFactorCode.trim()} disabled={isLoading || !twoFactorCode.trim()}
style={{ flex: "1 1 auto", minWidth: "120px" }} style={{ flex: "1 1 auto", minWidth: "120px", textAlign: "center", justifyContent: "center" }}
> >
{isLoading ? "Проверка..." : "Продолжить"} {isLoading ? "Проверка..." : "Продолжить"}
</button> </button>
@ -286,7 +286,7 @@ const LoginPage: React.FC = () => {
className="btn-danger" className="btn-danger"
onClick={handleBack} onClick={handleBack}
disabled={isLoading} disabled={isLoading}
style={{ flex: "1 1 auto", minWidth: "100px" }} style={{ flex: "1 1 auto", minWidth: "100px", textAlign: "center", justifyContent: "center" }}
> >
Назад Назад
</button> </button>

View File

@ -513,7 +513,7 @@ const ProfilePage: React.FC = () => {
<div <div
style={{ style={{
display: "flex", display: "flex",
alignItems: "center", flexDirection: "column",
gap: "10px", gap: "10px",
}} }}
> >
@ -522,13 +522,14 @@ const ProfilePage: React.FC = () => {
readOnly readOnly
value={publicProfileLink} value={publicProfileLink}
style={{ style={{
flex: 1,
padding: "8px", padding: "8px",
border: "1px solid var(--border-secondary, #ddd)", border: "1px solid var(--border-secondary, #ddd)",
borderRadius: "4px", borderRadius: "4px",
fontSize: "14px", fontSize: "14px",
backgroundColor: "var(--bg-secondary, #fff)", backgroundColor: "var(--bg-secondary, #fff)",
color: "var(--text-primary, #333)", color: "var(--text-primary, #333)",
width: "100%",
boxSizing: "border-box",
}} }}
/> />
<button <button
@ -537,6 +538,7 @@ const ProfilePage: React.FC = () => {
style={{ style={{
padding: "8px 15px", padding: "8px 15px",
whiteSpace: "nowrap", whiteSpace: "nowrap",
alignSelf: "center",
}} }}
> >
<Icon icon="mdi:content-copy" /> Копировать <Icon icon="mdi:content-copy" /> Копировать