├── .gitignore ├── .prettierrc.json ├── README.md ├── package-lock.json ├── package.json └── src ├── main ├── attatchIpcListeners.js └── main.js └── renderer └── pages ├── editor ├── editor.css ├── editor.html ├── scripts │ ├── commentMenu.js │ ├── editor.js │ ├── optionMenu.js │ ├── save.js │ ├── selection.js │ └── shortcuts.js └── util │ └── pxToNumber.js ├── menu ├── menu.css ├── menu.html └── menu.js └── view ├── view.css ├── view.html └── view.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /projects -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuickScript 2 | 3 | A program that makes scripting videos easier. Scripts can be written using only the keyboard. 4 | 5 | ## Installation 6 | 7 | - Clone/fork the repository 8 | - Install packages with `npm i ` 9 | - Run `npm start` 10 | 11 | ## Usage 12 | 13 | | Shortcut | Action | 14 | | ----------------- | ------------------------------- | 15 | | `ALT+S` | Select the current sentence | 16 | | `ALT+Right Arrow` | Select the next sentence | 17 | | `ALT+Left Arrow` | Select the previous sentence | 18 | | `ALT+O` | Open menu for current selection | 19 | | `Down Arrow` | Navigate down in menu | 20 | | `Up Arrow` | Navigate up in menu | 21 | | `ALT+M` | Toggle View/Edit mode | 22 | | `ALT+C` | View comments in view mode | 23 | | `CTRL++` | Zoom in | 24 | | `CTRL+-` | Zoom out | 25 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "QuickScript", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "devDependencies": { 8 | "electron": "^17.1.0" 9 | } 10 | }, 11 | "node_modules/@electron/get": { 12 | "version": "1.13.1", 13 | "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.13.1.tgz", 14 | "integrity": "sha512-U5vkXDZ9DwXtkPqlB45tfYnnYBN8PePp1z/XDCupnSpdrxT8/ThCv9WCwPLf9oqiSGZTkH6dx2jDUPuoXpjkcA==", 15 | "dev": true, 16 | "dependencies": { 17 | "debug": "^4.1.1", 18 | "env-paths": "^2.2.0", 19 | "fs-extra": "^8.1.0", 20 | "got": "^9.6.0", 21 | "progress": "^2.0.3", 22 | "semver": "^6.2.0", 23 | "sumchecker": "^3.0.1" 24 | }, 25 | "engines": { 26 | "node": ">=8.6" 27 | }, 28 | "optionalDependencies": { 29 | "global-agent": "^3.0.0", 30 | "global-tunnel-ng": "^2.7.1" 31 | } 32 | }, 33 | "node_modules/@sindresorhus/is": { 34 | "version": "0.14.0", 35 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 36 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 37 | "dev": true, 38 | "engines": { 39 | "node": ">=6" 40 | } 41 | }, 42 | "node_modules/@szmarczak/http-timer": { 43 | "version": "1.1.2", 44 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 45 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 46 | "dev": true, 47 | "dependencies": { 48 | "defer-to-connect": "^1.0.1" 49 | }, 50 | "engines": { 51 | "node": ">=6" 52 | } 53 | }, 54 | "node_modules/@types/node": { 55 | "version": "14.18.12", 56 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", 57 | "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", 58 | "dev": true 59 | }, 60 | "node_modules/boolean": { 61 | "version": "3.2.0", 62 | "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", 63 | "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", 64 | "dev": true, 65 | "optional": true 66 | }, 67 | "node_modules/buffer-crc32": { 68 | "version": "0.2.13", 69 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 70 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 71 | "dev": true, 72 | "engines": { 73 | "node": "*" 74 | } 75 | }, 76 | "node_modules/buffer-from": { 77 | "version": "1.1.2", 78 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 79 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 80 | "dev": true 81 | }, 82 | "node_modules/cacheable-request": { 83 | "version": "6.1.0", 84 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 85 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 86 | "dev": true, 87 | "dependencies": { 88 | "clone-response": "^1.0.2", 89 | "get-stream": "^5.1.0", 90 | "http-cache-semantics": "^4.0.0", 91 | "keyv": "^3.0.0", 92 | "lowercase-keys": "^2.0.0", 93 | "normalize-url": "^4.1.0", 94 | "responselike": "^1.0.2" 95 | }, 96 | "engines": { 97 | "node": ">=8" 98 | } 99 | }, 100 | "node_modules/cacheable-request/node_modules/get-stream": { 101 | "version": "5.2.0", 102 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 103 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 104 | "dev": true, 105 | "dependencies": { 106 | "pump": "^3.0.0" 107 | }, 108 | "engines": { 109 | "node": ">=8" 110 | }, 111 | "funding": { 112 | "url": "https://github.com/sponsors/sindresorhus" 113 | } 114 | }, 115 | "node_modules/cacheable-request/node_modules/lowercase-keys": { 116 | "version": "2.0.0", 117 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 118 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 119 | "dev": true, 120 | "engines": { 121 | "node": ">=8" 122 | } 123 | }, 124 | "node_modules/clone-response": { 125 | "version": "1.0.2", 126 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 127 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 128 | "dev": true, 129 | "dependencies": { 130 | "mimic-response": "^1.0.0" 131 | } 132 | }, 133 | "node_modules/concat-stream": { 134 | "version": "1.6.2", 135 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 136 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 137 | "dev": true, 138 | "engines": [ 139 | "node >= 0.8" 140 | ], 141 | "dependencies": { 142 | "buffer-from": "^1.0.0", 143 | "inherits": "^2.0.3", 144 | "readable-stream": "^2.2.2", 145 | "typedarray": "^0.0.6" 146 | } 147 | }, 148 | "node_modules/config-chain": { 149 | "version": "1.1.13", 150 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", 151 | "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", 152 | "dev": true, 153 | "optional": true, 154 | "dependencies": { 155 | "ini": "^1.3.4", 156 | "proto-list": "~1.2.1" 157 | } 158 | }, 159 | "node_modules/core-util-is": { 160 | "version": "1.0.3", 161 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 162 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 163 | "dev": true 164 | }, 165 | "node_modules/debug": { 166 | "version": "4.3.3", 167 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 168 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 169 | "dev": true, 170 | "dependencies": { 171 | "ms": "2.1.2" 172 | }, 173 | "engines": { 174 | "node": ">=6.0" 175 | }, 176 | "peerDependenciesMeta": { 177 | "supports-color": { 178 | "optional": true 179 | } 180 | } 181 | }, 182 | "node_modules/decompress-response": { 183 | "version": "3.3.0", 184 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 185 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 186 | "dev": true, 187 | "dependencies": { 188 | "mimic-response": "^1.0.0" 189 | }, 190 | "engines": { 191 | "node": ">=4" 192 | } 193 | }, 194 | "node_modules/defer-to-connect": { 195 | "version": "1.1.3", 196 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 197 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 198 | "dev": true 199 | }, 200 | "node_modules/define-properties": { 201 | "version": "1.1.3", 202 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 203 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 204 | "dev": true, 205 | "optional": true, 206 | "dependencies": { 207 | "object-keys": "^1.0.12" 208 | }, 209 | "engines": { 210 | "node": ">= 0.4" 211 | } 212 | }, 213 | "node_modules/detect-node": { 214 | "version": "2.1.0", 215 | "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", 216 | "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", 217 | "dev": true, 218 | "optional": true 219 | }, 220 | "node_modules/duplexer3": { 221 | "version": "0.1.4", 222 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 223 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 224 | "dev": true 225 | }, 226 | "node_modules/electron": { 227 | "version": "17.1.0", 228 | "resolved": "https://registry.npmjs.org/electron/-/electron-17.1.0.tgz", 229 | "integrity": "sha512-X/qdldmQ8lA15NmeraubWCTtMeTO8K9Ser0wtSCgOXVh53Sr1Ea0VQQ7Q9LuGgWRVz4qtr40cntuEdM8icdmTw==", 230 | "dev": true, 231 | "hasInstallScript": true, 232 | "dependencies": { 233 | "@electron/get": "^1.13.0", 234 | "@types/node": "^14.6.2", 235 | "extract-zip": "^1.0.3" 236 | }, 237 | "bin": { 238 | "electron": "cli.js" 239 | }, 240 | "engines": { 241 | "node": ">= 8.6" 242 | } 243 | }, 244 | "node_modules/encodeurl": { 245 | "version": "1.0.2", 246 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 247 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 248 | "dev": true, 249 | "optional": true, 250 | "engines": { 251 | "node": ">= 0.8" 252 | } 253 | }, 254 | "node_modules/end-of-stream": { 255 | "version": "1.4.4", 256 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 257 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 258 | "dev": true, 259 | "dependencies": { 260 | "once": "^1.4.0" 261 | } 262 | }, 263 | "node_modules/env-paths": { 264 | "version": "2.2.1", 265 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", 266 | "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", 267 | "dev": true, 268 | "engines": { 269 | "node": ">=6" 270 | } 271 | }, 272 | "node_modules/es6-error": { 273 | "version": "4.1.1", 274 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 275 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 276 | "dev": true, 277 | "optional": true 278 | }, 279 | "node_modules/escape-string-regexp": { 280 | "version": "4.0.0", 281 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 282 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 283 | "dev": true, 284 | "optional": true, 285 | "engines": { 286 | "node": ">=10" 287 | }, 288 | "funding": { 289 | "url": "https://github.com/sponsors/sindresorhus" 290 | } 291 | }, 292 | "node_modules/extract-zip": { 293 | "version": "1.7.0", 294 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", 295 | "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", 296 | "dev": true, 297 | "dependencies": { 298 | "concat-stream": "^1.6.2", 299 | "debug": "^2.6.9", 300 | "mkdirp": "^0.5.4", 301 | "yauzl": "^2.10.0" 302 | }, 303 | "bin": { 304 | "extract-zip": "cli.js" 305 | } 306 | }, 307 | "node_modules/extract-zip/node_modules/debug": { 308 | "version": "2.6.9", 309 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 310 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 311 | "dev": true, 312 | "dependencies": { 313 | "ms": "2.0.0" 314 | } 315 | }, 316 | "node_modules/extract-zip/node_modules/ms": { 317 | "version": "2.0.0", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 319 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 320 | "dev": true 321 | }, 322 | "node_modules/fd-slicer": { 323 | "version": "1.1.0", 324 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 325 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 326 | "dev": true, 327 | "dependencies": { 328 | "pend": "~1.2.0" 329 | } 330 | }, 331 | "node_modules/fs-extra": { 332 | "version": "8.1.0", 333 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 334 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 335 | "dev": true, 336 | "dependencies": { 337 | "graceful-fs": "^4.2.0", 338 | "jsonfile": "^4.0.0", 339 | "universalify": "^0.1.0" 340 | }, 341 | "engines": { 342 | "node": ">=6 <7 || >=8" 343 | } 344 | }, 345 | "node_modules/get-stream": { 346 | "version": "4.1.0", 347 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 348 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 349 | "dev": true, 350 | "dependencies": { 351 | "pump": "^3.0.0" 352 | }, 353 | "engines": { 354 | "node": ">=6" 355 | } 356 | }, 357 | "node_modules/global-agent": { 358 | "version": "3.0.0", 359 | "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", 360 | "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", 361 | "dev": true, 362 | "optional": true, 363 | "dependencies": { 364 | "boolean": "^3.0.1", 365 | "es6-error": "^4.1.1", 366 | "matcher": "^3.0.0", 367 | "roarr": "^2.15.3", 368 | "semver": "^7.3.2", 369 | "serialize-error": "^7.0.1" 370 | }, 371 | "engines": { 372 | "node": ">=10.0" 373 | } 374 | }, 375 | "node_modules/global-agent/node_modules/semver": { 376 | "version": "7.3.5", 377 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 378 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 379 | "dev": true, 380 | "optional": true, 381 | "dependencies": { 382 | "lru-cache": "^6.0.0" 383 | }, 384 | "bin": { 385 | "semver": "bin/semver.js" 386 | }, 387 | "engines": { 388 | "node": ">=10" 389 | } 390 | }, 391 | "node_modules/global-tunnel-ng": { 392 | "version": "2.7.1", 393 | "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", 394 | "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", 395 | "dev": true, 396 | "optional": true, 397 | "dependencies": { 398 | "encodeurl": "^1.0.2", 399 | "lodash": "^4.17.10", 400 | "npm-conf": "^1.1.3", 401 | "tunnel": "^0.0.6" 402 | }, 403 | "engines": { 404 | "node": ">=0.10" 405 | } 406 | }, 407 | "node_modules/globalthis": { 408 | "version": "1.0.2", 409 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", 410 | "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", 411 | "dev": true, 412 | "optional": true, 413 | "dependencies": { 414 | "define-properties": "^1.1.3" 415 | }, 416 | "engines": { 417 | "node": ">= 0.4" 418 | }, 419 | "funding": { 420 | "url": "https://github.com/sponsors/ljharb" 421 | } 422 | }, 423 | "node_modules/got": { 424 | "version": "9.6.0", 425 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 426 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 427 | "dev": true, 428 | "dependencies": { 429 | "@sindresorhus/is": "^0.14.0", 430 | "@szmarczak/http-timer": "^1.1.2", 431 | "cacheable-request": "^6.0.0", 432 | "decompress-response": "^3.3.0", 433 | "duplexer3": "^0.1.4", 434 | "get-stream": "^4.1.0", 435 | "lowercase-keys": "^1.0.1", 436 | "mimic-response": "^1.0.1", 437 | "p-cancelable": "^1.0.0", 438 | "to-readable-stream": "^1.0.0", 439 | "url-parse-lax": "^3.0.0" 440 | }, 441 | "engines": { 442 | "node": ">=8.6" 443 | } 444 | }, 445 | "node_modules/graceful-fs": { 446 | "version": "4.2.9", 447 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", 448 | "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", 449 | "dev": true 450 | }, 451 | "node_modules/http-cache-semantics": { 452 | "version": "4.1.0", 453 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 454 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 455 | "dev": true 456 | }, 457 | "node_modules/inherits": { 458 | "version": "2.0.4", 459 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 460 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 461 | "dev": true 462 | }, 463 | "node_modules/ini": { 464 | "version": "1.3.8", 465 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 466 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", 467 | "dev": true, 468 | "optional": true 469 | }, 470 | "node_modules/isarray": { 471 | "version": "1.0.0", 472 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 473 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 474 | "dev": true 475 | }, 476 | "node_modules/json-buffer": { 477 | "version": "3.0.0", 478 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 479 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 480 | "dev": true 481 | }, 482 | "node_modules/json-stringify-safe": { 483 | "version": "5.0.1", 484 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 485 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 486 | "dev": true, 487 | "optional": true 488 | }, 489 | "node_modules/jsonfile": { 490 | "version": "4.0.0", 491 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 492 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 493 | "dev": true, 494 | "optionalDependencies": { 495 | "graceful-fs": "^4.1.6" 496 | } 497 | }, 498 | "node_modules/keyv": { 499 | "version": "3.1.0", 500 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 501 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 502 | "dev": true, 503 | "dependencies": { 504 | "json-buffer": "3.0.0" 505 | } 506 | }, 507 | "node_modules/lodash": { 508 | "version": "4.17.21", 509 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 510 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 511 | "dev": true, 512 | "optional": true 513 | }, 514 | "node_modules/lowercase-keys": { 515 | "version": "1.0.1", 516 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 517 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 518 | "dev": true, 519 | "engines": { 520 | "node": ">=0.10.0" 521 | } 522 | }, 523 | "node_modules/lru-cache": { 524 | "version": "6.0.0", 525 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 526 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 527 | "dev": true, 528 | "optional": true, 529 | "dependencies": { 530 | "yallist": "^4.0.0" 531 | }, 532 | "engines": { 533 | "node": ">=10" 534 | } 535 | }, 536 | "node_modules/matcher": { 537 | "version": "3.0.0", 538 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", 539 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", 540 | "dev": true, 541 | "optional": true, 542 | "dependencies": { 543 | "escape-string-regexp": "^4.0.0" 544 | }, 545 | "engines": { 546 | "node": ">=10" 547 | } 548 | }, 549 | "node_modules/mimic-response": { 550 | "version": "1.0.1", 551 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 552 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 553 | "dev": true, 554 | "engines": { 555 | "node": ">=4" 556 | } 557 | }, 558 | "node_modules/minimist": { 559 | "version": "1.2.5", 560 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 561 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 562 | "dev": true 563 | }, 564 | "node_modules/mkdirp": { 565 | "version": "0.5.5", 566 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 567 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 568 | "dev": true, 569 | "dependencies": { 570 | "minimist": "^1.2.5" 571 | }, 572 | "bin": { 573 | "mkdirp": "bin/cmd.js" 574 | } 575 | }, 576 | "node_modules/ms": { 577 | "version": "2.1.2", 578 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 579 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 580 | "dev": true 581 | }, 582 | "node_modules/normalize-url": { 583 | "version": "4.5.1", 584 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", 585 | "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", 586 | "dev": true, 587 | "engines": { 588 | "node": ">=8" 589 | } 590 | }, 591 | "node_modules/npm-conf": { 592 | "version": "1.1.3", 593 | "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", 594 | "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", 595 | "dev": true, 596 | "optional": true, 597 | "dependencies": { 598 | "config-chain": "^1.1.11", 599 | "pify": "^3.0.0" 600 | }, 601 | "engines": { 602 | "node": ">=4" 603 | } 604 | }, 605 | "node_modules/object-keys": { 606 | "version": "1.1.1", 607 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 608 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 609 | "dev": true, 610 | "optional": true, 611 | "engines": { 612 | "node": ">= 0.4" 613 | } 614 | }, 615 | "node_modules/once": { 616 | "version": "1.4.0", 617 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 618 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 619 | "dev": true, 620 | "dependencies": { 621 | "wrappy": "1" 622 | } 623 | }, 624 | "node_modules/p-cancelable": { 625 | "version": "1.1.0", 626 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 627 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 628 | "dev": true, 629 | "engines": { 630 | "node": ">=6" 631 | } 632 | }, 633 | "node_modules/pend": { 634 | "version": "1.2.0", 635 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 636 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 637 | "dev": true 638 | }, 639 | "node_modules/pify": { 640 | "version": "3.0.0", 641 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 642 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 643 | "dev": true, 644 | "optional": true, 645 | "engines": { 646 | "node": ">=4" 647 | } 648 | }, 649 | "node_modules/prepend-http": { 650 | "version": "2.0.0", 651 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 652 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 653 | "dev": true, 654 | "engines": { 655 | "node": ">=4" 656 | } 657 | }, 658 | "node_modules/process-nextick-args": { 659 | "version": "2.0.1", 660 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 661 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 662 | "dev": true 663 | }, 664 | "node_modules/progress": { 665 | "version": "2.0.3", 666 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 667 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 668 | "dev": true, 669 | "engines": { 670 | "node": ">=0.4.0" 671 | } 672 | }, 673 | "node_modules/proto-list": { 674 | "version": "1.2.4", 675 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 676 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", 677 | "dev": true, 678 | "optional": true 679 | }, 680 | "node_modules/pump": { 681 | "version": "3.0.0", 682 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 683 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 684 | "dev": true, 685 | "dependencies": { 686 | "end-of-stream": "^1.1.0", 687 | "once": "^1.3.1" 688 | } 689 | }, 690 | "node_modules/readable-stream": { 691 | "version": "2.3.7", 692 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 693 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 694 | "dev": true, 695 | "dependencies": { 696 | "core-util-is": "~1.0.0", 697 | "inherits": "~2.0.3", 698 | "isarray": "~1.0.0", 699 | "process-nextick-args": "~2.0.0", 700 | "safe-buffer": "~5.1.1", 701 | "string_decoder": "~1.1.1", 702 | "util-deprecate": "~1.0.1" 703 | } 704 | }, 705 | "node_modules/responselike": { 706 | "version": "1.0.2", 707 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 708 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 709 | "dev": true, 710 | "dependencies": { 711 | "lowercase-keys": "^1.0.0" 712 | } 713 | }, 714 | "node_modules/roarr": { 715 | "version": "2.15.4", 716 | "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", 717 | "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", 718 | "dev": true, 719 | "optional": true, 720 | "dependencies": { 721 | "boolean": "^3.0.1", 722 | "detect-node": "^2.0.4", 723 | "globalthis": "^1.0.1", 724 | "json-stringify-safe": "^5.0.1", 725 | "semver-compare": "^1.0.0", 726 | "sprintf-js": "^1.1.2" 727 | }, 728 | "engines": { 729 | "node": ">=8.0" 730 | } 731 | }, 732 | "node_modules/safe-buffer": { 733 | "version": "5.1.2", 734 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 735 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 736 | "dev": true 737 | }, 738 | "node_modules/semver": { 739 | "version": "6.3.0", 740 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 741 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 742 | "dev": true, 743 | "bin": { 744 | "semver": "bin/semver.js" 745 | } 746 | }, 747 | "node_modules/semver-compare": { 748 | "version": "1.0.0", 749 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", 750 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", 751 | "dev": true, 752 | "optional": true 753 | }, 754 | "node_modules/serialize-error": { 755 | "version": "7.0.1", 756 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", 757 | "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", 758 | "dev": true, 759 | "optional": true, 760 | "dependencies": { 761 | "type-fest": "^0.13.1" 762 | }, 763 | "engines": { 764 | "node": ">=10" 765 | }, 766 | "funding": { 767 | "url": "https://github.com/sponsors/sindresorhus" 768 | } 769 | }, 770 | "node_modules/sprintf-js": { 771 | "version": "1.1.2", 772 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 773 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", 774 | "dev": true, 775 | "optional": true 776 | }, 777 | "node_modules/string_decoder": { 778 | "version": "1.1.1", 779 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 780 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 781 | "dev": true, 782 | "dependencies": { 783 | "safe-buffer": "~5.1.0" 784 | } 785 | }, 786 | "node_modules/sumchecker": { 787 | "version": "3.0.1", 788 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", 789 | "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", 790 | "dev": true, 791 | "dependencies": { 792 | "debug": "^4.1.0" 793 | }, 794 | "engines": { 795 | "node": ">= 8.0" 796 | } 797 | }, 798 | "node_modules/to-readable-stream": { 799 | "version": "1.0.0", 800 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 801 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 802 | "dev": true, 803 | "engines": { 804 | "node": ">=6" 805 | } 806 | }, 807 | "node_modules/tunnel": { 808 | "version": "0.0.6", 809 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 810 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 811 | "dev": true, 812 | "optional": true, 813 | "engines": { 814 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3" 815 | } 816 | }, 817 | "node_modules/type-fest": { 818 | "version": "0.13.1", 819 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", 820 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", 821 | "dev": true, 822 | "optional": true, 823 | "engines": { 824 | "node": ">=10" 825 | }, 826 | "funding": { 827 | "url": "https://github.com/sponsors/sindresorhus" 828 | } 829 | }, 830 | "node_modules/typedarray": { 831 | "version": "0.0.6", 832 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 833 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 834 | "dev": true 835 | }, 836 | "node_modules/universalify": { 837 | "version": "0.1.2", 838 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 839 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 840 | "dev": true, 841 | "engines": { 842 | "node": ">= 4.0.0" 843 | } 844 | }, 845 | "node_modules/url-parse-lax": { 846 | "version": "3.0.0", 847 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 848 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 849 | "dev": true, 850 | "dependencies": { 851 | "prepend-http": "^2.0.0" 852 | }, 853 | "engines": { 854 | "node": ">=4" 855 | } 856 | }, 857 | "node_modules/util-deprecate": { 858 | "version": "1.0.2", 859 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 860 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 861 | "dev": true 862 | }, 863 | "node_modules/wrappy": { 864 | "version": "1.0.2", 865 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 866 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 867 | "dev": true 868 | }, 869 | "node_modules/yallist": { 870 | "version": "4.0.0", 871 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 872 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 873 | "dev": true, 874 | "optional": true 875 | }, 876 | "node_modules/yauzl": { 877 | "version": "2.10.0", 878 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 879 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 880 | "dev": true, 881 | "dependencies": { 882 | "buffer-crc32": "~0.2.3", 883 | "fd-slicer": "~1.1.0" 884 | } 885 | } 886 | }, 887 | "dependencies": { 888 | "@electron/get": { 889 | "version": "1.13.1", 890 | "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.13.1.tgz", 891 | "integrity": "sha512-U5vkXDZ9DwXtkPqlB45tfYnnYBN8PePp1z/XDCupnSpdrxT8/ThCv9WCwPLf9oqiSGZTkH6dx2jDUPuoXpjkcA==", 892 | "dev": true, 893 | "requires": { 894 | "debug": "^4.1.1", 895 | "env-paths": "^2.2.0", 896 | "fs-extra": "^8.1.0", 897 | "global-agent": "^3.0.0", 898 | "global-tunnel-ng": "^2.7.1", 899 | "got": "^9.6.0", 900 | "progress": "^2.0.3", 901 | "semver": "^6.2.0", 902 | "sumchecker": "^3.0.1" 903 | } 904 | }, 905 | "@sindresorhus/is": { 906 | "version": "0.14.0", 907 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 908 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 909 | "dev": true 910 | }, 911 | "@szmarczak/http-timer": { 912 | "version": "1.1.2", 913 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 914 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 915 | "dev": true, 916 | "requires": { 917 | "defer-to-connect": "^1.0.1" 918 | } 919 | }, 920 | "@types/node": { 921 | "version": "14.18.12", 922 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", 923 | "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", 924 | "dev": true 925 | }, 926 | "boolean": { 927 | "version": "3.2.0", 928 | "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", 929 | "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", 930 | "dev": true, 931 | "optional": true 932 | }, 933 | "buffer-crc32": { 934 | "version": "0.2.13", 935 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 936 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 937 | "dev": true 938 | }, 939 | "buffer-from": { 940 | "version": "1.1.2", 941 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 942 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 943 | "dev": true 944 | }, 945 | "cacheable-request": { 946 | "version": "6.1.0", 947 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 948 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 949 | "dev": true, 950 | "requires": { 951 | "clone-response": "^1.0.2", 952 | "get-stream": "^5.1.0", 953 | "http-cache-semantics": "^4.0.0", 954 | "keyv": "^3.0.0", 955 | "lowercase-keys": "^2.0.0", 956 | "normalize-url": "^4.1.0", 957 | "responselike": "^1.0.2" 958 | }, 959 | "dependencies": { 960 | "get-stream": { 961 | "version": "5.2.0", 962 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 963 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 964 | "dev": true, 965 | "requires": { 966 | "pump": "^3.0.0" 967 | } 968 | }, 969 | "lowercase-keys": { 970 | "version": "2.0.0", 971 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 972 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 973 | "dev": true 974 | } 975 | } 976 | }, 977 | "clone-response": { 978 | "version": "1.0.2", 979 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 980 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 981 | "dev": true, 982 | "requires": { 983 | "mimic-response": "^1.0.0" 984 | } 985 | }, 986 | "concat-stream": { 987 | "version": "1.6.2", 988 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 989 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 990 | "dev": true, 991 | "requires": { 992 | "buffer-from": "^1.0.0", 993 | "inherits": "^2.0.3", 994 | "readable-stream": "^2.2.2", 995 | "typedarray": "^0.0.6" 996 | } 997 | }, 998 | "config-chain": { 999 | "version": "1.1.13", 1000 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", 1001 | "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", 1002 | "dev": true, 1003 | "optional": true, 1004 | "requires": { 1005 | "ini": "^1.3.4", 1006 | "proto-list": "~1.2.1" 1007 | } 1008 | }, 1009 | "core-util-is": { 1010 | "version": "1.0.3", 1011 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 1012 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 1013 | "dev": true 1014 | }, 1015 | "debug": { 1016 | "version": "4.3.3", 1017 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 1018 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 1019 | "dev": true, 1020 | "requires": { 1021 | "ms": "2.1.2" 1022 | } 1023 | }, 1024 | "decompress-response": { 1025 | "version": "3.3.0", 1026 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 1027 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 1028 | "dev": true, 1029 | "requires": { 1030 | "mimic-response": "^1.0.0" 1031 | } 1032 | }, 1033 | "defer-to-connect": { 1034 | "version": "1.1.3", 1035 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 1036 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 1037 | "dev": true 1038 | }, 1039 | "define-properties": { 1040 | "version": "1.1.3", 1041 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 1042 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 1043 | "dev": true, 1044 | "optional": true, 1045 | "requires": { 1046 | "object-keys": "^1.0.12" 1047 | } 1048 | }, 1049 | "detect-node": { 1050 | "version": "2.1.0", 1051 | "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", 1052 | "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", 1053 | "dev": true, 1054 | "optional": true 1055 | }, 1056 | "duplexer3": { 1057 | "version": "0.1.4", 1058 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 1059 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 1060 | "dev": true 1061 | }, 1062 | "electron": { 1063 | "version": "17.1.0", 1064 | "resolved": "https://registry.npmjs.org/electron/-/electron-17.1.0.tgz", 1065 | "integrity": "sha512-X/qdldmQ8lA15NmeraubWCTtMeTO8K9Ser0wtSCgOXVh53Sr1Ea0VQQ7Q9LuGgWRVz4qtr40cntuEdM8icdmTw==", 1066 | "dev": true, 1067 | "requires": { 1068 | "@electron/get": "^1.13.0", 1069 | "@types/node": "^14.6.2", 1070 | "extract-zip": "^1.0.3" 1071 | } 1072 | }, 1073 | "encodeurl": { 1074 | "version": "1.0.2", 1075 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1076 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 1077 | "dev": true, 1078 | "optional": true 1079 | }, 1080 | "end-of-stream": { 1081 | "version": "1.4.4", 1082 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 1083 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 1084 | "dev": true, 1085 | "requires": { 1086 | "once": "^1.4.0" 1087 | } 1088 | }, 1089 | "env-paths": { 1090 | "version": "2.2.1", 1091 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", 1092 | "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", 1093 | "dev": true 1094 | }, 1095 | "es6-error": { 1096 | "version": "4.1.1", 1097 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 1098 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 1099 | "dev": true, 1100 | "optional": true 1101 | }, 1102 | "escape-string-regexp": { 1103 | "version": "4.0.0", 1104 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1105 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1106 | "dev": true, 1107 | "optional": true 1108 | }, 1109 | "extract-zip": { 1110 | "version": "1.7.0", 1111 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", 1112 | "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", 1113 | "dev": true, 1114 | "requires": { 1115 | "concat-stream": "^1.6.2", 1116 | "debug": "^2.6.9", 1117 | "mkdirp": "^0.5.4", 1118 | "yauzl": "^2.10.0" 1119 | }, 1120 | "dependencies": { 1121 | "debug": { 1122 | "version": "2.6.9", 1123 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1124 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1125 | "dev": true, 1126 | "requires": { 1127 | "ms": "2.0.0" 1128 | } 1129 | }, 1130 | "ms": { 1131 | "version": "2.0.0", 1132 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1133 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1134 | "dev": true 1135 | } 1136 | } 1137 | }, 1138 | "fd-slicer": { 1139 | "version": "1.1.0", 1140 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 1141 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 1142 | "dev": true, 1143 | "requires": { 1144 | "pend": "~1.2.0" 1145 | } 1146 | }, 1147 | "fs-extra": { 1148 | "version": "8.1.0", 1149 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 1150 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 1151 | "dev": true, 1152 | "requires": { 1153 | "graceful-fs": "^4.2.0", 1154 | "jsonfile": "^4.0.0", 1155 | "universalify": "^0.1.0" 1156 | } 1157 | }, 1158 | "get-stream": { 1159 | "version": "4.1.0", 1160 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 1161 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 1162 | "dev": true, 1163 | "requires": { 1164 | "pump": "^3.0.0" 1165 | } 1166 | }, 1167 | "global-agent": { 1168 | "version": "3.0.0", 1169 | "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", 1170 | "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", 1171 | "dev": true, 1172 | "optional": true, 1173 | "requires": { 1174 | "boolean": "^3.0.1", 1175 | "es6-error": "^4.1.1", 1176 | "matcher": "^3.0.0", 1177 | "roarr": "^2.15.3", 1178 | "semver": "^7.3.2", 1179 | "serialize-error": "^7.0.1" 1180 | }, 1181 | "dependencies": { 1182 | "semver": { 1183 | "version": "7.3.5", 1184 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 1185 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 1186 | "dev": true, 1187 | "optional": true, 1188 | "requires": { 1189 | "lru-cache": "^6.0.0" 1190 | } 1191 | } 1192 | } 1193 | }, 1194 | "global-tunnel-ng": { 1195 | "version": "2.7.1", 1196 | "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", 1197 | "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", 1198 | "dev": true, 1199 | "optional": true, 1200 | "requires": { 1201 | "encodeurl": "^1.0.2", 1202 | "lodash": "^4.17.10", 1203 | "npm-conf": "^1.1.3", 1204 | "tunnel": "^0.0.6" 1205 | } 1206 | }, 1207 | "globalthis": { 1208 | "version": "1.0.2", 1209 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", 1210 | "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", 1211 | "dev": true, 1212 | "optional": true, 1213 | "requires": { 1214 | "define-properties": "^1.1.3" 1215 | } 1216 | }, 1217 | "got": { 1218 | "version": "9.6.0", 1219 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 1220 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 1221 | "dev": true, 1222 | "requires": { 1223 | "@sindresorhus/is": "^0.14.0", 1224 | "@szmarczak/http-timer": "^1.1.2", 1225 | "cacheable-request": "^6.0.0", 1226 | "decompress-response": "^3.3.0", 1227 | "duplexer3": "^0.1.4", 1228 | "get-stream": "^4.1.0", 1229 | "lowercase-keys": "^1.0.1", 1230 | "mimic-response": "^1.0.1", 1231 | "p-cancelable": "^1.0.0", 1232 | "to-readable-stream": "^1.0.0", 1233 | "url-parse-lax": "^3.0.0" 1234 | } 1235 | }, 1236 | "graceful-fs": { 1237 | "version": "4.2.9", 1238 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", 1239 | "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", 1240 | "dev": true 1241 | }, 1242 | "http-cache-semantics": { 1243 | "version": "4.1.0", 1244 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 1245 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 1246 | "dev": true 1247 | }, 1248 | "inherits": { 1249 | "version": "2.0.4", 1250 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1251 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1252 | "dev": true 1253 | }, 1254 | "ini": { 1255 | "version": "1.3.8", 1256 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 1257 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", 1258 | "dev": true, 1259 | "optional": true 1260 | }, 1261 | "isarray": { 1262 | "version": "1.0.0", 1263 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1264 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1265 | "dev": true 1266 | }, 1267 | "json-buffer": { 1268 | "version": "3.0.0", 1269 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 1270 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 1271 | "dev": true 1272 | }, 1273 | "json-stringify-safe": { 1274 | "version": "5.0.1", 1275 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1276 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 1277 | "dev": true, 1278 | "optional": true 1279 | }, 1280 | "jsonfile": { 1281 | "version": "4.0.0", 1282 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 1283 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 1284 | "dev": true, 1285 | "requires": { 1286 | "graceful-fs": "^4.1.6" 1287 | } 1288 | }, 1289 | "keyv": { 1290 | "version": "3.1.0", 1291 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 1292 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 1293 | "dev": true, 1294 | "requires": { 1295 | "json-buffer": "3.0.0" 1296 | } 1297 | }, 1298 | "lodash": { 1299 | "version": "4.17.21", 1300 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1301 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1302 | "dev": true, 1303 | "optional": true 1304 | }, 1305 | "lowercase-keys": { 1306 | "version": "1.0.1", 1307 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 1308 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 1309 | "dev": true 1310 | }, 1311 | "lru-cache": { 1312 | "version": "6.0.0", 1313 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1314 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1315 | "dev": true, 1316 | "optional": true, 1317 | "requires": { 1318 | "yallist": "^4.0.0" 1319 | } 1320 | }, 1321 | "matcher": { 1322 | "version": "3.0.0", 1323 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", 1324 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", 1325 | "dev": true, 1326 | "optional": true, 1327 | "requires": { 1328 | "escape-string-regexp": "^4.0.0" 1329 | } 1330 | }, 1331 | "mimic-response": { 1332 | "version": "1.0.1", 1333 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 1334 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 1335 | "dev": true 1336 | }, 1337 | "minimist": { 1338 | "version": "1.2.5", 1339 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1340 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1341 | "dev": true 1342 | }, 1343 | "mkdirp": { 1344 | "version": "0.5.5", 1345 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1346 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1347 | "dev": true, 1348 | "requires": { 1349 | "minimist": "^1.2.5" 1350 | } 1351 | }, 1352 | "ms": { 1353 | "version": "2.1.2", 1354 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1355 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1356 | "dev": true 1357 | }, 1358 | "normalize-url": { 1359 | "version": "4.5.1", 1360 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", 1361 | "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", 1362 | "dev": true 1363 | }, 1364 | "npm-conf": { 1365 | "version": "1.1.3", 1366 | "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", 1367 | "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", 1368 | "dev": true, 1369 | "optional": true, 1370 | "requires": { 1371 | "config-chain": "^1.1.11", 1372 | "pify": "^3.0.0" 1373 | } 1374 | }, 1375 | "object-keys": { 1376 | "version": "1.1.1", 1377 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1378 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1379 | "dev": true, 1380 | "optional": true 1381 | }, 1382 | "once": { 1383 | "version": "1.4.0", 1384 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1385 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1386 | "dev": true, 1387 | "requires": { 1388 | "wrappy": "1" 1389 | } 1390 | }, 1391 | "p-cancelable": { 1392 | "version": "1.1.0", 1393 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 1394 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 1395 | "dev": true 1396 | }, 1397 | "pend": { 1398 | "version": "1.2.0", 1399 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1400 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 1401 | "dev": true 1402 | }, 1403 | "pify": { 1404 | "version": "3.0.0", 1405 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1406 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 1407 | "dev": true, 1408 | "optional": true 1409 | }, 1410 | "prepend-http": { 1411 | "version": "2.0.0", 1412 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 1413 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 1414 | "dev": true 1415 | }, 1416 | "process-nextick-args": { 1417 | "version": "2.0.1", 1418 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1419 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 1420 | "dev": true 1421 | }, 1422 | "progress": { 1423 | "version": "2.0.3", 1424 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1425 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1426 | "dev": true 1427 | }, 1428 | "proto-list": { 1429 | "version": "1.2.4", 1430 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 1431 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", 1432 | "dev": true, 1433 | "optional": true 1434 | }, 1435 | "pump": { 1436 | "version": "3.0.0", 1437 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1438 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1439 | "dev": true, 1440 | "requires": { 1441 | "end-of-stream": "^1.1.0", 1442 | "once": "^1.3.1" 1443 | } 1444 | }, 1445 | "readable-stream": { 1446 | "version": "2.3.7", 1447 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1448 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1449 | "dev": true, 1450 | "requires": { 1451 | "core-util-is": "~1.0.0", 1452 | "inherits": "~2.0.3", 1453 | "isarray": "~1.0.0", 1454 | "process-nextick-args": "~2.0.0", 1455 | "safe-buffer": "~5.1.1", 1456 | "string_decoder": "~1.1.1", 1457 | "util-deprecate": "~1.0.1" 1458 | } 1459 | }, 1460 | "responselike": { 1461 | "version": "1.0.2", 1462 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 1463 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 1464 | "dev": true, 1465 | "requires": { 1466 | "lowercase-keys": "^1.0.0" 1467 | } 1468 | }, 1469 | "roarr": { 1470 | "version": "2.15.4", 1471 | "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", 1472 | "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", 1473 | "dev": true, 1474 | "optional": true, 1475 | "requires": { 1476 | "boolean": "^3.0.1", 1477 | "detect-node": "^2.0.4", 1478 | "globalthis": "^1.0.1", 1479 | "json-stringify-safe": "^5.0.1", 1480 | "semver-compare": "^1.0.0", 1481 | "sprintf-js": "^1.1.2" 1482 | } 1483 | }, 1484 | "safe-buffer": { 1485 | "version": "5.1.2", 1486 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1487 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1488 | "dev": true 1489 | }, 1490 | "semver": { 1491 | "version": "6.3.0", 1492 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1493 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1494 | "dev": true 1495 | }, 1496 | "semver-compare": { 1497 | "version": "1.0.0", 1498 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", 1499 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", 1500 | "dev": true, 1501 | "optional": true 1502 | }, 1503 | "serialize-error": { 1504 | "version": "7.0.1", 1505 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", 1506 | "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", 1507 | "dev": true, 1508 | "optional": true, 1509 | "requires": { 1510 | "type-fest": "^0.13.1" 1511 | } 1512 | }, 1513 | "sprintf-js": { 1514 | "version": "1.1.2", 1515 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 1516 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", 1517 | "dev": true, 1518 | "optional": true 1519 | }, 1520 | "string_decoder": { 1521 | "version": "1.1.1", 1522 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1523 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1524 | "dev": true, 1525 | "requires": { 1526 | "safe-buffer": "~5.1.0" 1527 | } 1528 | }, 1529 | "sumchecker": { 1530 | "version": "3.0.1", 1531 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", 1532 | "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", 1533 | "dev": true, 1534 | "requires": { 1535 | "debug": "^4.1.0" 1536 | } 1537 | }, 1538 | "to-readable-stream": { 1539 | "version": "1.0.0", 1540 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 1541 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 1542 | "dev": true 1543 | }, 1544 | "tunnel": { 1545 | "version": "0.0.6", 1546 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 1547 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 1548 | "dev": true, 1549 | "optional": true 1550 | }, 1551 | "type-fest": { 1552 | "version": "0.13.1", 1553 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", 1554 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", 1555 | "dev": true, 1556 | "optional": true 1557 | }, 1558 | "typedarray": { 1559 | "version": "0.0.6", 1560 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1561 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1562 | "dev": true 1563 | }, 1564 | "universalify": { 1565 | "version": "0.1.2", 1566 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1567 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1568 | "dev": true 1569 | }, 1570 | "url-parse-lax": { 1571 | "version": "3.0.0", 1572 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1573 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 1574 | "dev": true, 1575 | "requires": { 1576 | "prepend-http": "^2.0.0" 1577 | } 1578 | }, 1579 | "util-deprecate": { 1580 | "version": "1.0.2", 1581 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1582 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1583 | "dev": true 1584 | }, 1585 | "wrappy": { 1586 | "version": "1.0.2", 1587 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1588 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1589 | "dev": true 1590 | }, 1591 | "yallist": { 1592 | "version": "4.0.0", 1593 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1594 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1595 | "dev": true, 1596 | "optional": true 1597 | }, 1598 | "yauzl": { 1599 | "version": "2.10.0", 1600 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 1601 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 1602 | "dev": true, 1603 | "requires": { 1604 | "buffer-crc32": "~0.2.3", 1605 | "fd-slicer": "~1.1.0" 1606 | } 1607 | } 1608 | } 1609 | } 1610 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "electron": "^17.1.0" 4 | }, 5 | "name": "quickscript", 6 | "version": "1.0.0", 7 | "main": "index.js", 8 | "dependencies": { 9 | "boolean": "^3.2.0", 10 | "buffer-from": "^1.1.2", 11 | "buffer-crc32": "^0.2.13", 12 | "clone-response": "^1.0.2", 13 | "concat-stream": "^1.6.2", 14 | "cacheable-request": "^6.1.0", 15 | "config-chain": "^1.1.13", 16 | "core-util-is": "^1.0.3", 17 | "debug": "^4.3.3", 18 | "decompress-response": "^3.3.0", 19 | "defer-to-connect": "^1.1.3", 20 | "define-properties": "^1.1.3", 21 | "detect-node": "^2.1.0", 22 | "duplexer3": "^0.1.4", 23 | "encodeurl": "^1.0.2", 24 | "end-of-stream": "^1.4.4", 25 | "env-paths": "^2.2.1", 26 | "es6-error": "^4.1.1", 27 | "escape-string-regexp": "^4.0.0", 28 | "get-stream": "^4.1.0", 29 | "extract-zip": "^1.7.0", 30 | "global-agent": "^3.0.0", 31 | "globalthis": "^1.0.2", 32 | "fs-extra": "^8.1.0", 33 | "global-tunnel-ng": "^2.7.1", 34 | "graceful-fs": "^4.2.9", 35 | "got": "^9.6.0", 36 | "http-cache-semantics": "^4.1.0", 37 | "fd-slicer": "^1.1.0", 38 | "inherits": "^2.0.4", 39 | "ini": "^1.3.8", 40 | "isarray": "^1.0.0", 41 | "json-buffer": "^3.0.0", 42 | "json-stringify-safe": "^5.0.1", 43 | "jsonfile": "^4.0.0", 44 | "keyv": "^3.1.0", 45 | "lodash": "^4.17.21", 46 | "lowercase-keys": "^1.0.1", 47 | "lru-cache": "^6.0.0", 48 | "matcher": "^3.0.0", 49 | "mimic-response": "^1.0.1", 50 | "minimist": "^1.2.5", 51 | "mkdirp": "^0.5.5", 52 | "npm-conf": "^1.1.3", 53 | "ms": "^2.1.2", 54 | "normalize-url": "^4.5.1", 55 | "object-keys": "^1.1.1", 56 | "once": "^1.4.0", 57 | "p-cancelable": "^1.1.0", 58 | "pend": "^1.2.0", 59 | "pify": "^3.0.0", 60 | "prepend-http": "^2.0.0", 61 | "process-nextick-args": "^2.0.1", 62 | "proto-list": "^1.2.4", 63 | "progress": "^2.0.3", 64 | "readable-stream": "^2.3.7", 65 | "pump": "^3.0.0", 66 | "safe-buffer": "^5.1.2", 67 | "roarr": "^2.15.4", 68 | "responselike": "^1.0.2", 69 | "semver": "^6.3.0", 70 | "string_decoder": "^1.1.1", 71 | "serialize-error": "^7.0.1", 72 | "sprintf-js": "^1.1.2", 73 | "semver-compare": "^1.0.0", 74 | "sumchecker": "^3.0.1", 75 | "to-readable-stream": "^1.0.0", 76 | "type-fest": "^0.13.1", 77 | "tunnel": "^0.0.6", 78 | "universalify": "^0.1.2", 79 | "typedarray": "^0.0.6", 80 | "url-parse-lax": "^3.0.0", 81 | "wrappy": "^1.0.2", 82 | "yallist": "^4.0.0", 83 | "util-deprecate": "^1.0.2", 84 | "yauzl": "^2.10.0" 85 | }, 86 | "scripts": { 87 | "start": "npx electron ./src/main/main.js" 88 | }, 89 | "keywords": [], 90 | "author": "", 91 | "license": "ISC", 92 | "description": "" 93 | } 94 | -------------------------------------------------------------------------------- /src/main/attatchIpcListeners.js: -------------------------------------------------------------------------------- 1 | const { dialog, ipcMain } = require("electron"); 2 | 3 | const attatchIpcListeners = () => { 4 | ipcMain.handle("request-file-dialog", async (_, options) => { 5 | const dialogChoice = await dialog.showOpenDialog(options); 6 | return dialogChoice.filePaths[0]; 7 | }); 8 | 9 | ipcMain.handle("request-message-box", async (_, options) => { 10 | const dialogChoice = await dialog.showMessageBox(options); 11 | return dialogChoice.response; 12 | }); 13 | }; 14 | 15 | module.exports = attatchIpcListeners; 16 | -------------------------------------------------------------------------------- /src/main/main.js: -------------------------------------------------------------------------------- 1 | const { app, BrowserWindow, Menu, ipcMain } = require("electron"); 2 | const attachIpcListeners = require("./attatchIpcListeners"); 3 | 4 | const focusedWindowSend = (channel) => { 5 | BrowserWindow.getFocusedWindow().webContents.send(channel); 6 | }; 7 | 8 | Menu.setApplicationMenu( 9 | Menu.buildFromTemplate([ 10 | { 11 | label: "File", 12 | submenu: [ 13 | { 14 | label: "Save", 15 | click: () => { 16 | focusedWindowSend("save-script"); 17 | }, 18 | accelerator: "Ctrl+S", 19 | }, 20 | ], 21 | }, 22 | { 23 | label: "Developer", 24 | submenu: [ 25 | { 26 | label: "Inspect Element", 27 | role: "toggleDevTools", 28 | }, 29 | { 30 | label: "Reload Page", 31 | role: "reload", 32 | }, 33 | ], 34 | }, 35 | ]) 36 | ); 37 | 38 | const createWindow = () => { 39 | const win = new BrowserWindow({ 40 | width: 1200, 41 | height: 800, 42 | webPreferences: { 43 | nodeIntegration: true, 44 | contextIsolation: false, 45 | }, 46 | }); 47 | 48 | win.maximize(); 49 | 50 | win.loadFile("../renderer/pages/menu/menu.html"); 51 | }; 52 | 53 | app.once("ready", () => { 54 | createWindow(); 55 | attachIpcListeners(); 56 | 57 | app.on("activate", () => { 58 | if (BrowserWindow.getAllWindows().length === 0) createWindow(); 59 | }); 60 | }); 61 | 62 | app.on("window-all-closed", () => { 63 | if (process.platform !== "darwin") app.quit(); 64 | }); 65 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/editor.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | #scripting-input-area { 8 | width: 100vw; 9 | height: 100vh; 10 | border: none; 11 | outline: none; 12 | resize: none; 13 | font-size: 20px; 14 | } 15 | 16 | .menu { 17 | background: rgb(58, 58, 58); 18 | border-radius: 5px; 19 | position: fixed; 20 | top: 50%; 21 | left: 50%; 22 | transform: translate(-50%, -50%); 23 | text-align: center; 24 | padding: 20px; 25 | } 26 | 27 | .options-menu { 28 | width: 500px; 29 | height: 200px; 30 | } 31 | 32 | .comment-menu textarea { 33 | padding: 5px 10px; 34 | resize: none; 35 | outline: none; 36 | border: none; 37 | border-radius: 5px; 38 | width: 250px; 39 | height: 65px; 40 | } 41 | 42 | .options-menu-option { 43 | width: 100%; 44 | height: 30px; 45 | background-color: black; 46 | color: white; 47 | cursor: pointer; 48 | border: none; 49 | border-radius: 2px; 50 | margin-bottom: 5px; 51 | } 52 | 53 | #scripting-input-area { 54 | font-size: 23px; 55 | } 56 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quick Script - Editor 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/scripts/commentMenu.js: -------------------------------------------------------------------------------- 1 | import { state, scriptingInputArea } from "./editor.js"; 2 | 3 | /* Comment menu displays when adding a new comment */ 4 | 5 | export let commentMenuOpen = false; 6 | 7 | const commentMenu = document.createElement("div"); 8 | commentMenu.className = "menu comment-menu"; 9 | 10 | const commentInput = document.createElement("textarea"); 11 | commentInput.placeholder = "Your comment"; 12 | commentMenu.appendChild(commentInput); 13 | 14 | commentMenu.style.display = "none"; 15 | document.body.appendChild(commentMenu); 16 | 17 | /** 18 | * Show the comment menu 19 | */ 20 | export const openCommentMenu = () => { 21 | // Check if the text already has a comment and add to input field if so 22 | state.newSave.comments.forEach((comment) => { 23 | if ( 24 | scriptingInputArea.selectionStart === comment.startIdx && 25 | scriptingInputArea.selectionEnd === comment.endIdx 26 | ) { 27 | commentInput.value = comment.value; 28 | } 29 | }); 30 | 31 | commentMenu.style.display = "block"; 32 | commentInput.focus(); 33 | commentMenuOpen = true; 34 | }; 35 | 36 | /** 37 | * Delete a comment with a specific start and end index 38 | * @param {number} startIdx 39 | * @param {number} endIdx 40 | */ 41 | export const deleteComment = (startIdx, endIdx) => { 42 | state.newSave.comments = state.newSave.comments.filter( 43 | (comment) => comment.startIdx !== startIdx && comment.endIdx !== endIdx 44 | ); 45 | }; 46 | 47 | /** 48 | * Hide the comment menu 49 | */ 50 | export const closeCommentMenu = () => { 51 | if (!commentMenuOpen) return; 52 | 53 | commentMenu.style.display = "none"; 54 | commentMenuOpen = false; 55 | 56 | const filteredComments = state.newSave.comments.filter( 57 | (comment) => 58 | comment.startIdx === scriptingInputArea.selectionStart && 59 | comment.endIdx === scriptingInputArea.selectionEnd 60 | ); 61 | 62 | if (filteredComments.length === 0) { 63 | if (commentInput.value === "") return; 64 | 65 | state.newSave.comments.push({ 66 | startIdx: scriptingInputArea.selectionStart, 67 | endIdx: scriptingInputArea.selectionEnd, 68 | value: commentInput.value, 69 | }); 70 | } else { 71 | if (commentInput.value === "") { 72 | deleteComment( 73 | scriptingInputArea.selectionStart, 74 | scriptingInputArea.selectionEnd 75 | ); 76 | 77 | state.newSave.comments = newComments; 78 | } else { 79 | state.newSave.comments[ 80 | state.newSave.comments.indexOf(filteredComments[0]) 81 | ].value = commentInput.value; 82 | } 83 | } 84 | 85 | commentInput.value = ""; 86 | scriptingInputArea.focus(); 87 | }; 88 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/scripts/editor.js: -------------------------------------------------------------------------------- 1 | import { 2 | createOptionMenuOption, 3 | toggleOptionsMenu, 4 | closeOptionsMenu, 5 | } from "./optionMenu.js"; 6 | import { openCommentMenu, deleteComment } from "./commentMenu.js"; 7 | import { 8 | addShortcuts, 9 | addNavigationListeners, 10 | addZoomListeners, 11 | } from "./shortcuts.js"; 12 | import { loadScript, save } from "./save.js"; 13 | import { selectSentence, nextSentence, previousSentence } from "./selection.js"; 14 | 15 | const { ipcRenderer } = require("electron"); 16 | 17 | export const scriptingInputArea = document.getElementById( 18 | "scripting-input-area" 19 | ); 20 | scriptingInputArea.focus(); 21 | 22 | export const state = { 23 | newSave: {}, 24 | }; 25 | 26 | scriptingInputArea.addEventListener("input", ({ data }) => { 27 | state.newSave.contents = scriptingInputArea.value; 28 | 29 | if (!data) return; 30 | 31 | // bye performance 32 | state.newSave.comments.forEach((comment, idx) => { 33 | comment.startIdx += data.length; 34 | comment.endIdx += data.length; 35 | state.newSave.comments[idx] = comment; 36 | }); 37 | }); 38 | 39 | scriptingInputArea.addEventListener("keydown", (e) => { 40 | if (e.key !== "Backspace") return; 41 | 42 | state.newSave.comments.forEach(async (comment, idx) => { 43 | if ( 44 | scriptingInputArea.selectionStart === 45 | scriptingInputArea.selectionEnd 46 | ) { 47 | comment.startIdx--; 48 | comment.endIdx--; 49 | } else { 50 | comment.startIdx -= 51 | scriptingInputArea.selectionEnd - 52 | scriptingInputArea.selectionStart; 53 | comment.endIdx -= 54 | scriptingInputArea.selectionEnd - 55 | scriptingInputArea.selectionStart; 56 | } 57 | 58 | state.newSave.comments[idx] = comment; 59 | 60 | if (comment.endIdx !== scriptingInputArea.selectionEnd) return; 61 | e.preventDefault(); 62 | 63 | const dialogChoice = await ipcRenderer.invoke("request-message-box", { 64 | message: "This text contains a comment, do you wish to delete it?", 65 | type: "question", 66 | buttons: ["Yes", "No"], 67 | }); 68 | 69 | if (dialogChoice === 1) return; 70 | 71 | deleteComment(comment.startIdx, comment.endIdx); 72 | // Remove the last character 73 | scriptingInputArea.value = scriptingInputArea.value.substring( 74 | 0, 75 | scriptingInputArea.value.length - 1 76 | ); 77 | 78 | comment.startIdx++; 79 | comment.endIdx++; 80 | state.newSave.comments[idx] = comment; 81 | }); 82 | }); 83 | 84 | createOptionMenuOption("Add/Edit Comment", () => { 85 | closeOptionsMenu(); 86 | openCommentMenu(); 87 | }); 88 | 89 | createOptionMenuOption("Clear Comment", () => { 90 | deleteComment( 91 | scriptingInputArea.selectionStart, 92 | scriptingInputArea.selectionEnd 93 | ); 94 | 95 | closeOptionsMenu(); 96 | }); 97 | 98 | ipcRenderer.on("save-script", async () => { 99 | await save(); 100 | }); 101 | 102 | addNavigationListeners(); 103 | addShortcuts([ 104 | ["s", selectSentence], 105 | ["o", toggleOptionsMenu], 106 | ["ArrowRight", nextSentence], 107 | ["ArrowLeft", previousSentence], 108 | [ 109 | "m", 110 | async () => { 111 | await save(); 112 | location.href = "../view/view.html"; 113 | }, 114 | ], 115 | ]); 116 | addZoomListeners(); 117 | 118 | loadScript(); 119 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/scripts/optionMenu.js: -------------------------------------------------------------------------------- 1 | import { scriptingInputArea } from "./editor.js"; 2 | 3 | export let optionsMenuOpen = false; 4 | export let currentOptionIdx = 0; 5 | export const options = []; 6 | 7 | const optionsMenu = document.createElement("div"); 8 | optionsMenu.className = "menu options-menu"; 9 | optionsMenu.style.display = "none"; 10 | 11 | document.body.appendChild(optionsMenu); 12 | 13 | export const incrementOptionIdx = () => { 14 | currentOptionIdx++; 15 | }; 16 | 17 | export const decrementOptionIdx = () => { 18 | currentOptionIdx--; 19 | }; 20 | 21 | /** 22 | * Create option for option menu 23 | * @param {string} text 24 | * @param {Function} onclick 25 | */ 26 | export const createOptionMenuOption = (text, callback) => { 27 | const option = document.createElement("div"); 28 | option.innerText = text; 29 | option.className = "options-menu-option"; 30 | 31 | option.onclick = callback; 32 | options.push({ element: option, callback }); 33 | 34 | optionsMenu.appendChild(option); 35 | }; 36 | 37 | export const toggleOptionsMenu = () => { 38 | optionsMenuOpen = !optionsMenuOpen; 39 | 40 | if (!optionsMenuOpen) { 41 | closeOptionsMenu(); 42 | return; 43 | } 44 | 45 | if (scriptingInputArea.selectionStart === scriptingInputArea.selectionEnd) 46 | return; 47 | 48 | optionsMenu.style.display = "block"; 49 | 50 | scriptingInputArea.blur(); 51 | }; 52 | 53 | export const closeOptionsMenu = () => { 54 | optionsMenu.style.display = "none"; 55 | optionsMenuOpen = false; 56 | scriptingInputArea.focus(); 57 | }; 58 | 59 | export const showOptionBorder = (element) => { 60 | options.forEach((option) => { 61 | option.element.style.border = "none"; 62 | }); 63 | 64 | element.style.border = "solid 2px white"; 65 | }; 66 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/scripts/save.js: -------------------------------------------------------------------------------- 1 | import { scriptingInputArea, state } from "./editor.js"; 2 | 3 | const fs = require("fs/promises"); 4 | 5 | const currentScriptDirectory = localStorage.getItem("currentScriptDirectory"); 6 | 7 | /** Load script.json into editor */ 8 | export const loadScript = async () => { 9 | const scriptSaveRaw = await fs.readFile( 10 | `${currentScriptDirectory}/save.json`, 11 | "utf8" 12 | ); 13 | 14 | state.newSave = JSON.parse(scriptSaveRaw); 15 | 16 | document.title = `Quick Script Editor - ${state.newSave.name}`; 17 | scriptingInputArea.value = state.newSave.contents; 18 | }; 19 | 20 | /** Save script file */ 21 | export const save = async () => { 22 | await fs.writeFile( 23 | `${currentScriptDirectory}/save.json`, 24 | JSON.stringify(state.newSave) 25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/scripts/selection.js: -------------------------------------------------------------------------------- 1 | import { scriptingInputArea } from "./editor.js"; 2 | 3 | const whiteSpaceChars = [" ", "\t", "\n"]; 4 | 5 | const removeSelectionSpaceStart = (selectStartIdx) => { 6 | while (whiteSpaceChars.includes(scriptingInputArea.value[selectStartIdx])) { 7 | selectStartIdx++; 8 | } 9 | 10 | return selectStartIdx; 11 | }; 12 | 13 | const removeSelectionSpaceEnd = (selectEndIdx) => { 14 | while (whiteSpaceChars.includes(scriptingInputArea.value[selectEndIdx])) { 15 | selectEndIdx--; 16 | } 17 | 18 | return selectEndIdx; 19 | }; 20 | 21 | export const selectSentence = () => { 22 | const startIndex = scriptingInputArea.selectionStart; 23 | 24 | const scriptBehindCursor = scriptingInputArea.value.substring( 25 | 0, 26 | startIndex 27 | ); 28 | 29 | let selectStartIdx = 0; 30 | 31 | for (let i = scriptBehindCursor.length - 1; i >= 0; i--) { 32 | const char = scriptBehindCursor[i]; 33 | if (char === ".") { 34 | selectStartIdx = i + 1; 35 | break; 36 | } 37 | } 38 | 39 | let selectEndIdx = scriptingInputArea.value.length; 40 | 41 | const scriptAheadCursor = scriptingInputArea.value.substring(startIndex); 42 | 43 | for (let i = 0; i < scriptAheadCursor.length; i++) { 44 | const char = scriptAheadCursor[i]; 45 | if (char === ".") { 46 | selectEndIdx = i + scriptBehindCursor.length; 47 | break; 48 | } 49 | } 50 | 51 | selectStartIdx = removeSelectionSpaceStart(selectStartIdx); 52 | selectEndIdx = removeSelectionSpaceEnd(selectEndIdx); 53 | 54 | scriptingInputArea.setSelectionRange(selectStartIdx, selectEndIdx); 55 | }; 56 | 57 | export const nextSentence = () => { 58 | let selectionEndIdx = scriptingInputArea.value.length - 1; 59 | 60 | for ( 61 | let i = scriptingInputArea.selectionEnd + 1; 62 | i < scriptingInputArea.value.length; 63 | i++ 64 | ) { 65 | const char = scriptingInputArea.value[i]; 66 | if (char === ".") { 67 | selectionEndIdx = i; 68 | break; 69 | } 70 | } 71 | 72 | scriptingInputArea.setSelectionRange( 73 | scriptingInputArea.selectionStart, 74 | selectionEndIdx + 1 75 | ); 76 | }; 77 | 78 | export const previousSentence = () => { 79 | let firstDotOccured = false; 80 | let selectionStartIdx = 0; 81 | 82 | let firstSentenceEndIdx = scriptingInputArea.selectionEnd - 1; 83 | 84 | for ( 85 | let i = scriptingInputArea.selectionStart; 86 | i < scriptingInputArea.selectionEnd; 87 | i++ 88 | ) { 89 | const char = scriptingInputArea.value[i]; 90 | if (char === ".") { 91 | firstSentenceEndIdx = i; 92 | break; 93 | } 94 | } 95 | 96 | for (let i = firstSentenceEndIdx - 1; i >= 0; i--) { 97 | const char = scriptingInputArea.value[i]; 98 | if (char === ".") { 99 | if (firstDotOccured) { 100 | selectionStartIdx = i; 101 | break; 102 | } else firstDotOccured = true; 103 | } 104 | } 105 | 106 | if (selectionStartIdx === 0) selectionStartIdx -= 1; 107 | 108 | // Increment selectionStartIdx to ignore first full stop 109 | selectionStartIdx = removeSelectionSpaceStart(++selectionStartIdx); 110 | 111 | scriptingInputArea.setSelectionRange( 112 | selectionStartIdx, 113 | scriptingInputArea.selectionEnd 114 | ); 115 | }; 116 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/scripts/shortcuts.js: -------------------------------------------------------------------------------- 1 | import { commentMenuOpen, closeCommentMenu } from "./commentMenu.js"; 2 | import { 3 | optionsMenuOpen, 4 | currentOptionIdx, 5 | options, 6 | showOptionBorder, 7 | incrementOptionIdx, 8 | decrementOptionIdx, 9 | closeOptionsMenu, 10 | } from "./optionMenu.js"; 11 | import { scriptingInputArea } from "./editor.js"; 12 | import pxToNumber from "../util/pxToNumber.js"; 13 | 14 | /** 15 | * Creates shortcuts, always required to start with ALT 16 | * @param {[string, Function][]} shortcuts 17 | */ 18 | export const addShortcuts = (shortcuts) => { 19 | addEventListener("keydown", ({ altKey, key }) => { 20 | if (!altKey) return; 21 | 22 | shortcuts.forEach(([shortcutKey, callback]) => { 23 | if (key !== shortcutKey) return; 24 | callback(); 25 | }); 26 | }); 27 | }; 28 | 29 | export const addNavigationListeners = () => { 30 | showOptionBorder(options[currentOptionIdx].element); 31 | 32 | addEventListener("keydown", (e) => { 33 | const navKeys = [ 34 | "ArrowUp", 35 | "ArrowDown", 36 | "ArrowLeft", 37 | "ArrowRight", 38 | "Enter", 39 | "Escape", 40 | ]; 41 | 42 | if (!navKeys.includes(e.key)) return; 43 | 44 | if (optionsMenuOpen) { 45 | e.preventDefault(); 46 | 47 | if (e.key === "ArrowDown") { 48 | if (!options[currentOptionIdx + 1]) { 49 | currentOptionIdx = 0; 50 | showOptionBorder(options[currentOptionIdx].element); 51 | return; 52 | } 53 | 54 | incrementOptionIdx(); 55 | showOptionBorder(options[currentOptionIdx].element); 56 | } else if (e.key === "ArrowUp") { 57 | if (!options[currentOptionIdx - 1]) { 58 | currentOptionIdx = options.length - 1; 59 | showOptionBorder(options[currentOptionIdx].element); 60 | return; 61 | } 62 | 63 | decrementOptionIdx(); 64 | showOptionBorder(options[currentOptionIdx].element); 65 | } else if (e.key === "Enter") { 66 | options[currentOptionIdx].callback(); 67 | } else if (e.key === "Escape") { 68 | closeOptionsMenu(); 69 | } 70 | 71 | return; 72 | } 73 | 74 | if (commentMenuOpen) { 75 | if (e.key === "Escape") { 76 | e.preventDefault(); 77 | closeCommentMenu(); 78 | } 79 | 80 | return; 81 | } 82 | 83 | if (e.key === "Escape") { 84 | scriptingInputArea.setSelectionRange(0, 0); 85 | } 86 | }); 87 | }; 88 | 89 | export const addZoomListeners = () => { 90 | addEventListener("keydown", ({ key, ctrlKey }) => { 91 | if (!ctrlKey) return; 92 | 93 | const fontSize = parseFloat( 94 | getComputedStyle(scriptingInputArea, null).fontSize 95 | ); 96 | 97 | if (key === "=") { 98 | scriptingInputArea.style.fontSize = `${fontSize + 3}px`; 99 | } else if (key === "-") { 100 | scriptingInputArea.style.fontSize = `${fontSize - 3}px`; 101 | } 102 | }); 103 | }; 104 | -------------------------------------------------------------------------------- /src/renderer/pages/editor/util/pxToNumber.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts pixel string to number 3 | * @param {string} str 4 | * @returns {number} Number value of pixel string 5 | */ 6 | const pxToNumber = (str) => { 7 | return Number(str.substring(0, str.length - 2)); 8 | }; 9 | 10 | export default pxToNumber; 11 | -------------------------------------------------------------------------------- /src/renderer/pages/menu/menu.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | font-family: "Open Sans", sans-serif; 6 | background-color: #333333; 7 | color: white; 8 | text-align: center; 9 | } 10 | 11 | nav { 12 | padding: 60px; 13 | display: flex; 14 | height: 80px; 15 | margin-bottom: 80px; 16 | } 17 | 18 | h1 { 19 | font-size: 100px; 20 | font-weight: 800; 21 | margin: auto; 22 | } 23 | 24 | .btn { 25 | background-color: #ff7a00; 26 | outline: none; 27 | border: none; 28 | border-radius: 5px; 29 | color: white; 30 | font-family: "Open Sans", sans-serif; 31 | font-weight: 800; 32 | font-size: 30px; 33 | padding: 10px 30px; 34 | cursor: pointer; 35 | transition: all 0.2s ease; 36 | } 37 | 38 | .btn:hover { 39 | background-color: #a75000; 40 | } 41 | 42 | input { 43 | width: 770px; 44 | height: 74px; 45 | padding: 14px; 46 | font-size: 33px; 47 | font-weight: 600; 48 | outline: none; 49 | border: none; 50 | border-radius: 5px; 51 | margin-bottom: 22px; 52 | } 53 | 54 | #path-btn { 55 | padding: 30px; 56 | margin-left: 23px; 57 | background-color: white; 58 | color: black; 59 | border: none; 60 | outline: none; 61 | font-size: 33px; 62 | font-weight: 600; 63 | border-radius: 5px; 64 | cursor: pointer; 65 | display: block; 66 | } 67 | 68 | .path-container { 69 | display: flex; 70 | justify-content: center; 71 | } 72 | -------------------------------------------------------------------------------- /src/renderer/pages/menu/menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quick Script Menu 8 | 9 | 10 | 11 | 15 | 16 | 17 | 21 |
22 | 28 |
29 | 35 | 36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/renderer/pages/menu/menu.js: -------------------------------------------------------------------------------- 1 | const { ipcRenderer, dialog } = require("electron"); 2 | const fs = require("fs/promises"); 3 | 4 | const createScriptForm = document.getElementById("create-script-form"); 5 | const pathBtn = document.getElementById("path-btn"); 6 | const openScriptBtn = document.getElementById("open-script-btn"); 7 | 8 | const scriptNameInput = document.getElementById("script-name-input"); 9 | const scriptPathInput = document.getElementById("script-path-input"); 10 | 11 | /** 12 | * Display error to the user 13 | * @param {string} message 14 | */ 15 | const displayError = (message) => { 16 | alert(`[ERROR]: ${message}`); 17 | }; 18 | 19 | /** 20 | * Set the current script path for loading scripts 21 | * @param {string} path 22 | */ 23 | const setCurrentScriptPath = (path) => { 24 | localStorage.setItem("currentScriptDirectory", path); 25 | }; 26 | 27 | /** Load the script editor */ 28 | const loadEditor = () => { 29 | location.href = "../editor/editor.html"; 30 | }; 31 | 32 | /** Open file dialog to specify a directory for the script project */ 33 | pathBtn.addEventListener("click", async () => { 34 | const dialogChoice = await ipcRenderer.invoke("request-file-dialog", { 35 | properties: ["openDirectory"], 36 | }); 37 | 38 | if (!dialogChoice) return; 39 | 40 | // If a script name has been provided, add that to the path 41 | scriptPathInput.value = dialogChoice; 42 | if (scriptNameInput.value) { 43 | scriptPathInput.value += `\\${scriptNameInput.value}`; 44 | } 45 | }); 46 | 47 | createScriptForm.addEventListener("submit", async (e) => { 48 | e.preventDefault(); 49 | 50 | try { 51 | // Check if directory exists & is empty 52 | 53 | const dirContents = await fs.readdir(scriptPathInput.value); 54 | // Display error if directory contains files 55 | if (dirContents.length !== 0) { 56 | return displayError( 57 | `'${scriptPathInput.value}' is not empty. Directory must be empty to proceed.` 58 | ); 59 | } 60 | } catch { 61 | // Catch if file is either a file or doesn't exist. 62 | 63 | try { 64 | // Check if path is to a file 65 | const fileStats = await fs.stat(scriptPathInput.value); 66 | if (fileStats.isFile()) { 67 | displayError( 68 | `'${scriptPathInput.value}' is a file. Please specify a directory in order to proceed.` 69 | ); 70 | } 71 | 72 | return; 73 | } catch { 74 | // Catch if there is no file or directory to the given path 75 | await fs.mkdir(scriptPathInput.value); 76 | } 77 | } 78 | 79 | // Create a save.json and load the editor 80 | const save = JSON.stringify({ 81 | name: scriptNameInput.value, 82 | contents: "", 83 | comments: [], 84 | }); 85 | await fs.writeFile(`${scriptPathInput.value}/save.json`, save); 86 | 87 | setCurrentScriptPath(scriptPathInput.value); 88 | loadEditor(); 89 | }); 90 | 91 | // Open a script and load into editor 92 | openScriptBtn.addEventListener("click", async () => { 93 | const dialogChoice = await ipcRenderer.invoke("request-file-dialog", { 94 | properties: ["openDirectory"], 95 | }); 96 | 97 | if (!dialogChoice) return; 98 | 99 | const directoryContents = await fs.readdir(dialogChoice); 100 | if (!directoryContents.includes("save.json")) { 101 | return displayError("Directory does not include a 'save.json'"); 102 | } 103 | 104 | setCurrentScriptPath(dialogChoice); 105 | loadEditor(); 106 | }); 107 | -------------------------------------------------------------------------------- /src/renderer/pages/view/view.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | font-size: 30px; 6 | font-family: "Open Sans", sans-serif; 7 | } 8 | 9 | .comment-display { 10 | position: absolute; 11 | width: 100vw; 12 | padding: 20px; 13 | bottom: 0; 14 | background-color: rgb(58, 58, 58); 15 | color: white; 16 | text-align: center; 17 | } 18 | -------------------------------------------------------------------------------- /src/renderer/pages/view/view.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quick Script View 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/renderer/pages/view/view.js: -------------------------------------------------------------------------------- 1 | const currentScriptDirectory = localStorage.getItem("currentScriptDirectory"); 2 | const fs = require("fs/promises"); 3 | 4 | let scriptSave = {}; 5 | 6 | const commentDisplayElement = document.createElement("div"); 7 | commentDisplayElement.className = "comment-display"; 8 | commentDisplayElement.style.display = "none"; 9 | document.body.appendChild(commentDisplayElement); 10 | 11 | let showComments = false; 12 | 13 | /** Load script.json into view */ 14 | const loadScript = async () => { 15 | const scriptSaveRaw = await fs.readFile( 16 | `${currentScriptDirectory}/save.json`, 17 | "utf8" 18 | ); 19 | 20 | scriptSave = JSON.parse(scriptSaveRaw); 21 | 22 | document.title = `Quick Script View - ${scriptSave.name}`; 23 | 24 | const contentParent = document.createElement("p"); 25 | document.body.appendChild(contentParent); 26 | for (let i = 0; i < scriptSave.contents.length; i++) { 27 | let spanText = scriptSave.contents[i]; 28 | 29 | const span = document.createElement("span"); 30 | contentParent.appendChild(span); 31 | 32 | scriptSave.comments.forEach((comment) => { 33 | if (comment.startIdx === i) { 34 | spanText = ""; 35 | 36 | span.className = "comment"; 37 | span.addEventListener("mouseover", () => { 38 | if (showComments) { 39 | commentDisplayElement.textContent = comment.value; 40 | commentDisplayElement.innerHTML = 41 | commentDisplayElement.innerHTML.replace( 42 | /\n\r?/g, 43 | "
" 44 | ); 45 | commentDisplayElement.style.display = "block"; 46 | } 47 | }); 48 | 49 | span.addEventListener("mouseleave", () => { 50 | if (showComments) { 51 | commentDisplayElement.style.display = "none"; 52 | } 53 | }); 54 | 55 | while (i < comment.endIdx) { 56 | spanText += scriptSave.contents[i]; 57 | i++; 58 | } 59 | 60 | i--; // decrement i to remain in sync with the loop 61 | 62 | return; 63 | } 64 | }); 65 | 66 | span.textContent = spanText; 67 | span.innerHTML = span.innerHTML.replace(/\n\r?/g, "
"); 68 | } 69 | }; 70 | 71 | loadScript(); 72 | 73 | const toggleShowComments = () => { 74 | showComments = !showComments; 75 | const comments = document.getElementsByClassName("comment"); 76 | 77 | if (showComments) { 78 | for (let i = 0; i < comments.length; i++) { 79 | const comment = comments.item(i); 80 | comment.style.backgroundColor = "yellow"; 81 | } 82 | } else { 83 | for (let i = 0; i < comments.length; i++) { 84 | const comment = comments.item(i); 85 | comment.style.background = "none"; 86 | } 87 | } 88 | }; 89 | 90 | addEventListener("keydown", ({ altKey, key }) => { 91 | if (!altKey) return; 92 | 93 | if (key === "m") { 94 | location.href = "../editor/editor.html"; 95 | return; 96 | } 97 | 98 | if (key === "c") { 99 | toggleShowComments(); 100 | return; 101 | } 102 | }); 103 | 104 | addEventListener("keydown", ({ key, ctrlKey }) => { 105 | if (!ctrlKey) return; 106 | 107 | const fontSize = parseFloat(getComputedStyle(document.body, null).fontSize); 108 | 109 | if (key === "=") { 110 | document.body.style.fontSize = `${fontSize + 1}px`; 111 | } else if (key === "-") { 112 | document.body.style.fontSize = `${fontSize - 1}px`; 113 | } 114 | }); 115 | --------------------------------------------------------------------------------