├── .gitignore ├── .editorconfig ├── src ├── includes │ ├── prototypes.js │ ├── globals.js │ ├── init.js │ ├── settings.js │ ├── styles.js │ ├── logging.js │ ├── parsers.js │ ├── helpers.js │ └── ui.js └── header.js ├── .prettierrc.json ├── server.js ├── package.json ├── definitions ├── fileSaver.d.ts ├── jsZip.d.ts └── tampermonkey.d.ts ├── README.md ├── pnpm-lock.yaml └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .vscode 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.js] 4 | indent_size = 2 5 | -------------------------------------------------------------------------------- /src/includes/prototypes.js: -------------------------------------------------------------------------------- 1 | Array.prototype.unique = function (cb) { 2 | return h.unique(this, cb); 3 | }; 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "printWidth": 140, 4 | "semi": true, 5 | "arrowParens": "avoid", 6 | "singleQuote": true 7 | } -------------------------------------------------------------------------------- /src/includes/globals.js: -------------------------------------------------------------------------------- 1 | const JSZip = window.JSZip; 2 | const tippy = window.tippy; 3 | const http = window.GM_xmlhttpRequest; 4 | window.isFF = typeof InstallTrigger !== 'undefined'; -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const express = require('express'); 3 | const app = express(); 4 | const port = 3000; 5 | 6 | app.get('/', (req, res) => { 7 | res.send(fs.readFileSync('./dist/build.user.js').toString()); 8 | }); 9 | 10 | app.listen(port, () => { 11 | console.log(`Listening on port ${port}`); 12 | }); 13 | -------------------------------------------------------------------------------- /src/includes/init.js: -------------------------------------------------------------------------------- 1 | const init = { 2 | injectCustomStyles: () => { 3 | // Tippy transparent theme. 4 | const styleEl = document.createElement('style'); 5 | styleEl.textContent = styles.tippy.theme; 6 | document.head.append(styleEl); 7 | 8 | const customStyles = document.createElement('style'); 9 | // Margins classes 10 | const marginClasses = []; 11 | 12 | for (let i = 1; i <= 15; i++) { 13 | marginClasses.push(`.m-l-${i} {margin-left: ${i}px;}`); 14 | marginClasses.push(`.m-t-${i} {margin-top: ${i}px;}`); 15 | } 16 | 17 | customStyles.textContent = marginClasses.join('\n'); 18 | document.head.append(customStyles); 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /src/includes/settings.js: -------------------------------------------------------------------------------- 1 | const settings = { 2 | naming: { 3 | allowEmojis: false, 4 | invalidCharSubstitute: '-', 5 | }, 6 | hosts: { 7 | goFile: { 8 | token: 'KPQJgKlYsy8JPmbuxj3MC4e5PFEpdZYP', 9 | }, 10 | }, 11 | ui: { 12 | checkboxes: { 13 | toggleAllCheckboxLabel: '', 14 | }, 15 | }, 16 | extensions: { 17 | image: ['.jpg', '.jpeg', '.png', '.gif', '.gif', '.webp', '.jpe', '.svg', '.tif', '.tiff', '.jif'], 18 | video: [ 19 | '.mpeg', 20 | '.avchd', 21 | '.webm', 22 | '.mpv', 23 | '.swf', 24 | '.avi', 25 | '.m4p', 26 | '.wmv', 27 | '.mp2', 28 | '.m4v', 29 | '.qt', 30 | '.mpe', 31 | '.mp4', 32 | '.flv', 33 | '.mov', 34 | '.mpg', 35 | '.ogg', 36 | ], 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "forum-post-downloader", 3 | "version": "2.5.2", 4 | "description": "Downloads images and videos from all the popular hosts.", 5 | "scripts": { 6 | "build": "node build.js", 7 | "dev": "concurrently \"chokidar build.js ./src/* -c 'node build.js'\" \"node server.js\"" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/SkyCloudDev/ForumPostDownloader.git" 12 | }, 13 | "author": "x111000111", 14 | "license": "WTFPL", 15 | "bugs": { 16 | "url": "https://github.com/SkyCloudDev/ForumPostDownloader/issues" 17 | }, 18 | "homepage": "https://github.com/SkyCloudDev/ForumPostDownloader#readme", 19 | "devDependencies": { 20 | "chokidar-cli": "^3.0.0", 21 | "concurrently": "^7.5.0", 22 | "express": "^4.18.2", 23 | "prettier": "^2.7.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/includes/styles.js: -------------------------------------------------------------------------------- 1 | const styles = { 2 | tippy: { 3 | theme: `.tippy-box[data-theme~=transparent]{background-color:transparent}.tippy-box[data-theme~=transparent]>.tippy-arrow{width:14px;height:14px}.tippy-box[data-theme~=transparent][data-placement^=top]>.tippy-arrow:before{border-width:7px 7px 0;border-top-color:#3f3f3f}.tippy-box[data-theme~=transparent][data-placement^=bottom]>.tippy-arrow:before{border-width:1 7px 7px;border-bottom-color:#3f3f3f}.tippy-box[data-theme~=transparent][data-placement^=left]>.tippy-arrow:before{border-width:7px 0 7px 7px;border-left-color:#3f3f3f}.tippy-box[data-theme~=transparent][data-placement^=right]>.tippy-arrow:before{border-width:7px 7px 7px 0;border-right-color:#3f3f3f}.tippy-box[data-theme~=transparent]>.tippy-backdrop{background-color:transparent;}.tippy-box[data-theme~=transparent]>.tippy-svg-arrow{fill:gainsboro}`, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /definitions/fileSaver.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for FileSaver.js 2.0 2 | // Project: https://github.com/eligrey/FileSaver.js/ 3 | // Definitions by: Cyril Schumacher 4 | // Daniel Roth 5 | // HitkoDev 6 | // JounQin 7 | // BendingBender 8 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 9 | 10 | export = FileSaver; 11 | 12 | export as namespace saveAs; 13 | 14 | /** 15 | * FileSaver.js implements the saveAs() FileSaver interface in browsers that do not natively support it. 16 | * @param data - The actual file data blob or URL. 17 | * @param filename - The optional name of the file to be downloaded. If omitted, the name used in the file data will be used. If none is provided "download" will be used. 18 | * @param options - Optional FileSaver.js config 19 | */ 20 | declare function FileSaver(data: Blob | string, filename?: string, options?: FileSaver.FileSaverOptions): void; 21 | 22 | /** 23 | * FileSaver.js implements the saveAs() FileSaver interface in browsers that do not natively support it. 24 | * @param data - The actual file data blob or URL. 25 | * @param filename - The optional name of the file to be downloaded. If omitted, the name used in the file data will be used. If none is provided "download" will be used. 26 | * @param disableAutoBOM - Optional & defaults to `true`. Set to `false` if you want FileSaver.js to automatically provide Unicode text encoding hints 27 | * @deprecated use `{ autoBom: false }` as the third argument 28 | */ 29 | // tslint:disable-next-line:unified-signatures 30 | declare function FileSaver(data: Blob | string, filename?: string, disableAutoBOM?: boolean): void; 31 | 32 | declare namespace FileSaver { 33 | interface FileSaverOptions { 34 | /** 35 | * Automatically provide Unicode text encoding hints 36 | * @default false 37 | */ 38 | autoBom: boolean; 39 | } 40 | 41 | const saveAs: typeof FileSaver; 42 | } -------------------------------------------------------------------------------- /src/includes/logging.js: -------------------------------------------------------------------------------- 1 | window.logs = []; 2 | 3 | const log = { 4 | /** 5 | * @returns {number} 6 | */ 7 | separator: postId => window.logs.push({ postId, message: '-'.repeat(175) }), 8 | /** 9 | * @param postId 10 | * @param str 11 | * @param type 12 | * @param toConsole 13 | */ 14 | write: (postId, str, type, toConsole = true) => { 15 | const date = new Date(); 16 | const message = `[${date.toDateString()} ${date.toLocaleTimeString()}] [${type}] ${str}` 17 | .replace(/(::.*?::)/gi, (match, g) => g.toUpperCase()) 18 | .replace(/::/g, ''); 19 | window.logs.push({ postId, message }); 20 | if (toConsole) { 21 | if (type.toLowerCase() === 'info') { 22 | console.info(message); 23 | } else if (type.toLowerCase() === 'warn') { 24 | console.warn(message); 25 | } else { 26 | console.error(message); 27 | } 28 | } 29 | }, 30 | /** 31 | * @param postId 32 | * @param str 33 | * @param scope 34 | */ 35 | info: (postId, str, scope) => log.write(postId, `[${scope}] ${str}`, 'INFO'), 36 | /** 37 | * @param postId 38 | * @param str 39 | * @param scope 40 | */ 41 | warn: (postId, str, scope) => log.write(postId, `[${scope}] ${str}`, 'WARNING'), 42 | /** 43 | * @param postId 44 | * @param str 45 | * @param scope 46 | */ 47 | error: (postId, str, scope) => log.write(postId, `[${scope}] ${str}`, 'ERROR'), 48 | // TODO: Fix param orders for the methods: -.- 49 | post: { 50 | /** 51 | * @param postId 52 | * @param str 53 | * @param postNumber 54 | * @returns {*} 55 | */ 56 | info: (postId, str, postNumber) => log.info(postId, str, `POST #${postNumber}`), 57 | /** 58 | * @param postId 59 | * @param str 60 | * @param postNumber 61 | * @returns {*} 62 | */ 63 | error: (postId, str, postNumber) => log.error(postId, str, `POST #${postNumber}`), 64 | }, 65 | host: { 66 | /** 67 | * @param postId 68 | * @param str 69 | * @param host 70 | * @returns {*} 71 | */ 72 | info: (postId, str, host) => log.info(postId, str, host), 73 | /** 74 | * @param postId 75 | * @param str 76 | * @param host 77 | * @returns {*} 78 | */ 79 | error: (postId, str, host) => log.error(postId, str, host), 80 | }, 81 | }; 82 | -------------------------------------------------------------------------------- /src/header.js: -------------------------------------------------------------------------------- 1 | // noinspection SpellCheckingInspection,JSUnresolvedVariable,JSUnresolvedFunction,TypeScriptUMDGlobal,JSUnusedGlobalSymbols 2 | // ==UserScript== 3 | // @name XenForoPostDownloader 4 | // @namespace https://github.com/SkyCloudDev 5 | // @author SkyCloudDev 6 | // @author x111000111 7 | // @author backwards 8 | // @description Downloads images and videos from posts 9 | // @version 2.5.2 10 | // @updateURL https://github.com/SkyCloudDev/ForumPostDownloader/raw/main/dist/build.user.js 11 | // @downloadURL https://github.com/SkyCloudDev/ForumPostDownloader/raw/main/dist/build.user.js 12 | // @icon https://simp4.jpg.church/simpcityIcon192.png 13 | // @license WTFPL; http://www.wtfpl.net/txt/copying/ 14 | // @match https://simpcity.su/threads/* 15 | // @require https://unpkg.com/@popperjs/core@2 16 | // @require https://unpkg.com/tippy.js@6 17 | // @require https://unpkg.com/file-saver@2.0.4/dist/FileSaver.min.js 18 | // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js 19 | // @require https://raw.githubusercontent.com/geraintluff/sha256/gh-pages/sha256.min.js 20 | // @connect self 21 | // @connect anonfiles.com 22 | // @connect coomer.party 23 | // @connect box.com 24 | // @connect boxcloud.com 25 | // @connect kemono.party 26 | // @connect github.com 27 | // @connect bunkr.ru 28 | // @connect bunkr.su 29 | // @connect bunkr.la 30 | // @connect cyberdrop.me 31 | // @connect cyberdrop.cc 32 | // @connect cyberdrop.nl 33 | // @connect cyberdrop.to 34 | // @connect cyberfile.su 35 | // @connect cyberfile.me 36 | // @connect saint.to 37 | // @connect sendvid.com 38 | // @connect redd.it 39 | // @connect dailystar.co.uk 40 | // @connect pinuderest.com 41 | // @connect onlyfans.com 42 | // @connect i.ibb.co 43 | // @connect ibb.co 44 | // @connect imagebam.com 45 | // @connect imgur.com 46 | // @connect jpg.church 47 | // @connect jpg.fish 48 | // @connect jpg.fishing 49 | // @connect imgbox.com 50 | // @connect pixhost.to 51 | // @connect pixl.is 52 | // @connect pixl.li 53 | // @connect pornhub.com 54 | // @connect postimg.cc 55 | // @connect img.kiwi 56 | // @connect imgvb.com 57 | // @connect instagram.com 58 | // @connect cdninstagram.com 59 | // @connect pixxxels.cc 60 | // @connect postimg.cc 61 | // @connect erome.com 62 | // @connect imagevenue.com 63 | // @connect nhentai-proxy.herokuapp.com 64 | // @connect pbs.twimg.com 65 | // @connect media.tumblr.com 66 | // @connect cdn.discordapp.com 67 | // @connect pixeldrain.com 68 | // @connect redgifs.com 69 | // @connect rule34.xxx 70 | // @connect gfycat.com 71 | // @connect noodlemagazine.com 72 | // @connect pvvstream.pro 73 | // @connect spankbang.com 74 | // @connect sb-cd.com 75 | // @connect gofile.io 76 | // @connect phncdn.com 77 | // @connect xvideos.com 78 | // @connect give.xxx 79 | // @connect zippyshare.com 80 | // @connect githubusercontent.com 81 | // @run-at document-start 82 | // @grant GM_xmlhttpRequest 83 | // @grant GM_download 84 | // @grant GM_setValue 85 | // @grant GM_getValue 86 | // @grant GM_log 87 | 88 | // ==/UserScript== 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Forum Posts Downloader 2 | This Tampermonkey script allows for downloading individual posts and pages from the SimpCity forum (should work for any XenForo forum). 3 | 4 | ## Supported Hosts 5 | - [x] jpg.church 🢒 https://simpcity.su/threads/alexis-clark.15203/post-1160129 6 | - [x] ibb.co 🢒 https://simpcity.su/threads/martina-raja-tosi.105401/post-1065693 7 | - [x] img.kiwi 🢒 https://simpcity.su/threads/yellz0.89827/post-1155221 8 | - [x] imgbox.com 🢒 https://simpcity.su/threads/sirena-mysirenaofc.63488/post-478107 9 | - [x] reddit.com 🢒 https://simpcity.su/threads/lena12.10427/post-17564 10 | - [x] twitter.com 🢒 https://simpcity.su/threads/crybabyxo-lexi.112025/post-1170246 11 | - [x] pixl.is 🢒 https://simpcity.su/threads/lillyroma1982-lilly-roma.13466/post-1170354 12 | - [x] pixhost.to 🢒 https://simpcity.su/threads/emily-ratajkowski.11090/post-889542 13 | - [x] imagebam.com 🢒 https://simpcity.su/threads/xobondaixo-bella-bondai.64960/# 14 | - [x] saint.to 🢒 https://simpcity.su/threads/audrey-bradford-dreybradford.13355/post-1144820 15 | - [x] gfycat.com 🢒 https://simpcity.su/threads/grace-boor.10153/post-1170389 16 | - [x] box.com 🢒 https://simpcity.su/threads/nataliarose2020-hotwethailey.38931/post-888139 17 | - [x] redgifs.com 🢒 https://simpcity.su/threads/movies-and-tv-scenes.63781/post-1041255 18 | - [x] bunkr.is 🢒 https://simpcity.su/threads/movies-and-tv-scenes.63781/post-1041380 19 | - [x] pixeldrain.com 🢒 https://simpcity.su/threads/jessi-callahan-babygirl-honeybun.26041/post-1170383 20 | - [x] anonfiles.com 🢒 https://simpcity.su/threads/julieta-yanez-ters29.94204/post-1170305 21 | - [x] gofile.com 🢒 https://simpcity.su/threads/dakota-tyler-dakotatylerxxx.33609/post-1136725 22 | - [x] erome.com 🢒 https://simpcity.su/threads/taylor-jay-xtaylorjayx.6209/# 23 | - [x] cyberfile.is 🢒 https://simpcity.su/threads/brazzyblondebhabie-aubrey-chesna.12405/post-1170196 24 | - [x] cyberdrop.me 🢒 https://simpcity.su/threads/sophxof.43374/post-250161 25 | - [x] pornhub.com 🢒 https://simpcity.su/threads/arya-fae-aryafae710.111893/post-1168184 26 | - [x] noodlemagazine.com 🢒 https://simpcity.su/threads/arya-fae-aryafae710.111893/post-1168184 27 | - [x] spankbang.com 🢒 https://simpcity.su/threads/joi-jerk-off-instructions-thread.56850/post-1170472 28 | 29 | ## Installation 30 | 1. Install the Tampermonkey browser extension: [Chrome](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en) [Firefox](https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/) [Brave](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en) 31 | 2. **Important:** Under the tampermonkey settings, set the **Config mode** to **Advanced** and enable the **Browser API** in **Download Mode (BETA)**. 32 | 3. Copy the contents of [https://github.com/SkyCloudDev/ForumPostDownloader/blob/main/dist/build.user.js](https://github.com/SkyCloudDev/ForumPostDownloader/blob/main/dist/build.user.js) 33 | 4. Create a new Tampermonkey script and paste the contents you copied in step 3 (build.js). 34 | 5. Save the script (Ctrl+S). 35 | 6. Visit any thread to verify the script installation. 36 | 37 | # Updates 38 | The script should automatically update from GitHub. If it doesn't simply repeat the steps 3-6 from the installation section (paste into the existing script instead of creating a new one (step #4)). 39 | -------------------------------------------------------------------------------- /src/includes/parsers.js: -------------------------------------------------------------------------------- 1 | const parsers = { 2 | thread: { 3 | /** 4 | * @returns {string} 5 | */ 6 | parseTitle: () => { 7 | const emojisPattern = 8 | /[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f191}-\u{1f251}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}]/gu; 9 | let parsed = h.stripTags(['a', 'span'], h.element('.p-title-value').innerHTML).replace('/\n/g', ''); 10 | return !settings.naming.allowEmojis ? parsed.replace(emojisPattern, settings.naming.invalidCharSubstitute).trim() : parsed.trim(); 11 | }, 12 | /** 13 | * 14 | * @param post 15 | * @returns {{pageNumber: string, post, spoilers: *, footer: HTMLElement, contentContainer: Element, textContent: (*|string|string), postId: string, postNumber: string, content: (*|string|string|string)}} 16 | */ 17 | parsePost: post => { 18 | const messageContent = post.parentNode.parentNode.querySelector('.message-content > .message-userContent > .message-body'); 19 | const footer = post.parentNode.parentNode.querySelector('footer'); 20 | const messageContentClone = messageContent.cloneNode(true); 21 | 22 | const postIdAnchor = post.querySelector('li:last-of-type > a'); 23 | const postId = /(?<=\/post-).*/i.exec(postIdAnchor.getAttribute('href'))[0]; 24 | const postNumber = postIdAnchor.textContent.replace('#', '').trim(); 25 | 26 | // Remove the following from the post content: 27 | // 1. Quotes. 28 | // 2. CodeBlock headers 29 | // 3. Spoiler button text from each spoiler 30 | // 2. Icons from un-furled urls (url parser can sometimes match them). 31 | ['.contentRow-figure', '.js-unfurl-favicon', 'blockquote', '.button-text > span'] 32 | .flatMap(i => [...messageContentClone.querySelectorAll(i)]) 33 | .forEach(i => { 34 | if (i.tagName === 'BLOCKQUOTE') { 35 | // Only remove blockquotes that quote the other posts. 36 | if (i.querySelector('.bbCodeBlock-title')) { 37 | i.remove(); 38 | } 39 | } else { 40 | i.remove(); 41 | } 42 | }); 43 | 44 | // Remove thread links. 45 | [...messageContentClone.querySelectorAll('.contentRow-header > a[href^="https://simpcity.su/threads"]')] 46 | .map(a => a.parentNode.parentNode.parentNode.parentNode) 47 | .forEach(i => i.remove()); 48 | 49 | // Extract spoilers from the post content. 50 | const spoilers = [...messageContentClone.querySelectorAll('.bbCodeBlock--spoiler > .bbCodeBlock-content')] 51 | .filter(s => !s.querySelector('.bbCodeBlock--unfurl')) 52 | .concat([...messageContentClone.querySelectorAll('.bbCodeInlineSpoiler')].filter(s => !s.querySelector('.bbCodeBlock--unfurl'))) 53 | .map(s => s.innerText) 54 | .concat( 55 | h.re 56 | .matchAll(/(?<=pw|pass|passwd|password)(\s:|:)?\s+?[a-zA-Z0-9~!@#$%^&*()_+{}|:'"<>?\/,;.]+/gis, messageContentClone.innerText) 57 | .map(s => s.trim()), 58 | ) 59 | .map(s => 60 | s 61 | .trim() 62 | .replace(/^:/, '') 63 | .replace(/\bp:\b/i, '') 64 | .replace(/\bpw:\b/i, '') 65 | .replace(/\bkey:\b/i, '') 66 | .trim(), 67 | ) 68 | .filter(s => s !== '') 69 | .unique(); 70 | 71 | const postContent = messageContentClone.innerHTML; 72 | const postTextContent = messageContentClone.innerText; 73 | 74 | const matches = /(?<=\/page-)\d+/is.exec(document.location.pathname); 75 | 76 | const pageNumber = matches && matches.length ? Number(matches[0]) : 1; 77 | 78 | return { 79 | post, 80 | postId, 81 | postNumber, 82 | pageNumber, 83 | spoilers, 84 | footer, 85 | content: postContent, 86 | textContent: postTextContent, 87 | contentContainer: messageContent, 88 | }; 89 | }, 90 | }, 91 | hosts: { 92 | /** 93 | * @param postContent 94 | * @returns {(*&{id: number, enabled: boolean})[]} 95 | */ 96 | parseHosts: postContent => { 97 | let parsed = []; 98 | 99 | for (const host of hosts) { 100 | // Require at-least the signature plus an array of matchers. 101 | if (host.length < 2) { 102 | continue; 103 | } 104 | 105 | const signature = host[0].split(':'); 106 | const matchers = host[1]; 107 | 108 | if (!h.isArray(matchers) || !matchers.length) { 109 | continue; 110 | } 111 | 112 | const name = signature[0]; 113 | let category = signature.length > 1 ? signature[1] : 'misc'; 114 | 115 | let singleMatcherPattern = matchers[0]; 116 | let albumMatcherPattern = matchers.length > 1 ? matchers[1] : null; 117 | 118 | const execMatcher = matcher => { 119 | let pattern = matcher.toString().replace(/~an@/g, 'a-zA-Z0-9'); 120 | 121 | const stripQueryString = h.contains('', pattern.toString()); 122 | const stripTrailingSlash = !h.contains('', pattern.toString()); 123 | pattern = pattern.replace('', '').replace('', ''); 124 | 125 | if (h.contains('!!', pattern)) { 126 | pattern = pattern.replace('!!', ''); 127 | pattern = h.re.toRegExp(h.re.toString(pattern), 'igs'); 128 | } else { 129 | const pat = `(?<=data-url="|src="|href=")https?:\/\/(www.)?${h.re.toString(pattern)}.*?(?=")|https?:\/\/(www.)?${h.re.toString( 130 | pattern, 131 | )}.*?(?=("|<|$|\]|'))`; 132 | pattern = h.re.toRegExp(pat, 'igs'); 133 | } 134 | 135 | let matches = h.re.matchAll(pattern, postContent).unique(); 136 | 137 | matches = matches.map(url => { 138 | if (stripQueryString && h.contains('?', url)) { 139 | url = url.substring(0, url.indexOf('?')); 140 | } 141 | 142 | if (stripTrailingSlash && url[url.length - 1]) { 143 | url = url[url.length - 1] === '/' ? url.substring(0, url.length - 1) : url; 144 | } 145 | 146 | return url.trim(); 147 | }); 148 | 149 | return h.unique(matches); 150 | }; 151 | 152 | const categories = category.split(','); 153 | 154 | if (singleMatcherPattern) { 155 | let singleCategory = [categories[0]].map(c => { 156 | if (c === 'image' || c === 'video') { 157 | return `${h.ucFirst(c)}s`; 158 | } 159 | 160 | if (c.trim() !== '') { 161 | return h.ucFirst(c); 162 | } 163 | 164 | return 'Direct Links'; 165 | })[0]; 166 | 167 | parsed.push({ 168 | name, 169 | type: 'single', 170 | category: singleCategory, 171 | resources: execMatcher(singleMatcherPattern), 172 | }); 173 | } 174 | 175 | if (albumMatcherPattern) { 176 | let albumCategory = categories.length > 1 ? categories[1] : categories[0]; 177 | 178 | albumCategory = `${h.ucFirst(albumCategory)} Albums`; 179 | 180 | parsed.push({ 181 | name, 182 | type: 'album', 183 | category: albumCategory, 184 | resources: execMatcher(albumMatcherPattern), 185 | }); 186 | } 187 | } 188 | 189 | return parsed 190 | .map(p => ({ 191 | ...p, 192 | enabled: true, 193 | id: Math.round(Math.random() * Number.MAX_SAFE_INTEGER), 194 | })) 195 | .filter(p => p.resources.length); 196 | }, 197 | }, 198 | }; 199 | -------------------------------------------------------------------------------- /src/includes/helpers.js: -------------------------------------------------------------------------------- 1 | const h = { 2 | /** 3 | * @param v 4 | * @returns {arg is any[]} 5 | */ 6 | isArray: v => Array.isArray(v), 7 | /** 8 | * @param v 9 | * @returns {boolean} 10 | */ 11 | isObject: v => typeof v === 'object', 12 | /** 13 | * @param v 14 | * @returns {boolean} 15 | */ 16 | isNullOrUndef: v => v === null || v === undefined || typeof v === 'undefined', 17 | /** 18 | * @param path 19 | * @returns {unknown} 20 | */ 21 | basename: path => 22 | path 23 | .replace(/\/(\s+)?$/, '') 24 | .split('/') 25 | .reverse()[0], 26 | /** 27 | * @param path 28 | * @returns {string} 29 | */ 30 | fnNoExt: path => path.trim().split('.').reverse().slice(1).reverse().join('.'), 31 | /** 32 | * @param path 33 | * @returns {unknown} 34 | */ 35 | ext: path => { 36 | return !path || path.indexOf('.') < 0 ? null : path.split('.').reverse()[0]; 37 | }, 38 | /** 39 | * @param element 40 | * @returns {string} 41 | */ 42 | show: element => (element.style.display = 'block'), 43 | /** 44 | * @param element 45 | * @returns {string} 46 | */ 47 | hide: element => (element.style.display = 'none'), 48 | /** 49 | * @param executor 50 | * @returns {Promise} 51 | */ 52 | promise: executor => new Promise(executor), 53 | /** 54 | * @param ms 55 | * @returns {Promise} 56 | */ 57 | delayedResolve: async ms => await h.promise(resolve => setTimeout(resolve, ms)), 58 | /** 59 | * @param tag 60 | * @param content 61 | * @returns {*} 62 | */ 63 | stripTag: (tag, content) => content.replace(new RegExp(`<${tag}.*?<\/${tag}>`, 'igs'), ''), 64 | /** 65 | * @param tags 66 | * @param content 67 | * @returns {*} 68 | */ 69 | stripTags: (tags, content) => tags.reduce((stripped, tag) => h.stripTag(tag, stripped), content), 70 | /** 71 | * @param string 72 | * @param maxLength 73 | * @returns {string|*} 74 | */ 75 | limit: (string, maxLength = 20) => (string.length > maxLength ? `${string.substring(0, maxLength - 1)}...` : string), 76 | /** 77 | * @param selector 78 | * @param container 79 | * @returns {*} 80 | */ 81 | element: (selector, container = document) => container.querySelector(selector), 82 | /** 83 | * @param selector 84 | * @param container 85 | * @returns {NodeListOf<*>} 86 | */ 87 | elements: (selector, container = document) => container.querySelectorAll(selector), 88 | /** 89 | * @param needle 90 | * @param haystack 91 | * @param ignoreCase 92 | * @returns {boolean} 93 | */ 94 | contains: (needle, haystack, ignoreCase = true) => 95 | (ignoreCase ? haystack.toLowerCase().indexOf(needle.toLowerCase()) : haystack.indexOf(needle)) > -1, 96 | /** 97 | * @param str 98 | * @returns {*|string} 99 | */ 100 | ucFirst: str => (!str ? str : `${str[0].toUpperCase()}${str.substring(1)}`), 101 | /** 102 | * @param items 103 | * @param cb 104 | * @returns {*} 105 | */ 106 | unique: (items, cb) => { 107 | if (cb) { 108 | return items.reduce((acc, item) => (!acc.find(i => i[byKey] === item[byKey]) ? acc.concat(item) : acc), []); 109 | } 110 | 111 | return items.reduce((acc, item) => (acc.indexOf(item) < 0 ? acc.concat(item) : acc), []); 112 | }, 113 | /** 114 | * https://github.com/sindresorhus/pretty-bytes 115 | * 116 | * @param number 117 | * @param options 118 | * @returns {string} 119 | */ 120 | prettyBytes: (number, options = {}) => { 121 | const BYTE_UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; 122 | 123 | const BIBYTE_UNITS = ['B', 'kiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; 124 | 125 | const BIT_UNITS = ['b', 'kbit', 'Mbit', 'Gbit', 'Tbit', 'Pbit', 'Ebit', 'Zbit', 'Ybit']; 126 | 127 | const BIBIT_UNITS = ['b', 'kibit', 'Mibit', 'Gibit', 'Tibit', 'Pibit', 'Eibit', 'Zibit', 'Yibit']; 128 | 129 | /* 130 | Formats the given number using `Number#toLocaleString`. 131 | - If locale is a string, the value is expected to be a locale-key (for example: `de`). 132 | - If locale is true, the system default locale is used for translation. 133 | - If no value for locale is specified, the number is returned unmodified. 134 | */ 135 | const toLocaleString = (number, locale, options) => { 136 | let result = number; 137 | if (typeof locale === 'string' || Array.isArray(locale)) { 138 | result = number.toLocaleString(locale, options); 139 | } else if (locale === true || options !== undefined) { 140 | result = number.toLocaleString(undefined, options); 141 | } 142 | 143 | return result; 144 | }; 145 | 146 | if (!Number.isFinite(number)) { 147 | throw new TypeError(`Expected a finite number, got ${typeof number}: ${number}`); 148 | } 149 | 150 | options = { 151 | bits: false, 152 | binary: false, 153 | space: true, 154 | ...options, 155 | }; 156 | 157 | const UNITS = options.bits ? (options.binary ? BIBIT_UNITS : BIT_UNITS) : options.binary ? BIBYTE_UNITS : BYTE_UNITS; 158 | 159 | const separator = options.space ? ' ' : ''; 160 | 161 | if (options.signed && number === 0) { 162 | return ` 0${separator}${UNITS[0]}`; 163 | } 164 | 165 | const isNegative = number < 0; 166 | const prefix = isNegative ? '-' : options.signed ? '+' : ''; 167 | 168 | if (isNegative) { 169 | number = -number; 170 | } 171 | 172 | let localeOptions; 173 | 174 | if (options.minimumFractionDigits !== undefined) { 175 | localeOptions = { minimumFractionDigits: options.minimumFractionDigits }; 176 | } 177 | 178 | if (options.maximumFractionDigits !== undefined) { 179 | localeOptions = { maximumFractionDigits: options.maximumFractionDigits, ...localeOptions }; 180 | } 181 | 182 | if (number < 1) { 183 | const numberString = toLocaleString(number, options.locale, localeOptions); 184 | return prefix + numberString + separator + UNITS[0]; 185 | } 186 | 187 | const exponent = Math.min(Math.floor(options.binary ? Math.log(number) / Math.log(1024) : Math.log10(number) / 3), UNITS.length - 1); 188 | number /= (options.binary ? 1024 : 1000) ** exponent; 189 | 190 | if (!localeOptions) { 191 | number = number.toPrecision(3); 192 | } 193 | 194 | const numberString = toLocaleString(Number(number), options.locale, localeOptions); 195 | 196 | const unit = UNITS[exponent]; 197 | 198 | return prefix + numberString + separator + unit; 199 | }, 200 | ui: { 201 | /** 202 | * @param element 203 | * @param text 204 | */ 205 | setText: (element, text) => { 206 | element.textContent = text; 207 | }, 208 | /** 209 | * @param element 210 | * @param props 211 | */ 212 | setElProps: (element, props) => { 213 | for (const prop in props) { 214 | element.style[prop] = props[prop]; 215 | } 216 | }, 217 | }, 218 | http: { 219 | /** 220 | * @param method 221 | * @param url 222 | * @param callbacks 223 | * @param headers 224 | * @param data 225 | * @param responseType 226 | * @returns {Promise} 227 | */ 228 | base: (method, url, callbacks = {}, headers = {}, data = {}, responseType = 'document') => { 229 | return h.promise((resolve, reject) => { 230 | let responseHeaders = null; 231 | http({ 232 | url, 233 | method, 234 | responseType, 235 | data, 236 | headers: { 237 | Referer: url, 238 | ...headers, 239 | }, 240 | onreadystatechange: response => { 241 | if (response.readyState === 2) { 242 | responseHeaders = response.responseHeaders; 243 | } 244 | callbacks && callbacks.onStateChange && callbacks.onStateChange(response); 245 | }, 246 | onprogress: response => { 247 | callbacks && callbacks.onProgress && callbacks.onProgress(response); 248 | }, 249 | onload: response => { 250 | const { responseText } = response; 251 | const dom = response?.response; 252 | callbacks && callbacks.onLoad && callbacks.onLoad(response); 253 | resolve({ source: responseText, dom, responseHeaders }); 254 | }, 255 | onerror: error => { 256 | callbacks && callbacks.onError && callbacks.onError(error); 257 | reject(error); 258 | }, 259 | }); 260 | }); 261 | }, 262 | /** 263 | * @param url 264 | * @param callbacks 265 | * @param headers 266 | * @param responseType 267 | * @returns {Promise} 268 | */ 269 | get: (url, callbacks = {}, headers = {}, responseType = 'document') => { 270 | return h.promise(resolve => resolve(h.http.base('GET', url, callbacks, headers, {}, responseType))); 271 | }, 272 | /** 273 | * @param url 274 | * @param data 275 | * @param callbacks 276 | * @param headers 277 | * @returns {Promise} 278 | */ 279 | post: (url, data = {}, callbacks = {}, headers = {}) => { 280 | return h.promise(resolve => resolve(h.http.base('POST', url, callbacks, headers, data))); 281 | }, 282 | }, 283 | re: { 284 | /** 285 | * @param pattern 286 | * @returns {string|*} 287 | */ 288 | stripFlags: pattern => { 289 | if (!h.contains('/', pattern)) { 290 | return pattern; 291 | } 292 | 293 | const s = pattern.split('').reverse().join(''); 294 | 295 | const index = s.indexOf('/'); 296 | 297 | return s.substring(index).split('').reverse().join(''); 298 | }, 299 | /** 300 | * @param pattern 301 | * @returns {string|*} 302 | */ 303 | toString: pattern => { 304 | let stringified = h.re.stripFlags(pattern.toString()); 305 | 306 | if (stringified[0] === '/') { 307 | stringified = stringified.substring(1); 308 | } 309 | 310 | if (stringified[stringified.length - 1] === '/') { 311 | stringified = stringified.substring(0, stringified.length - 1); 312 | } 313 | 314 | return stringified; 315 | }, 316 | /** 317 | * @param pattern 318 | * @param flags 319 | * @returns {RegExp} 320 | */ 321 | toRegExp: (pattern, flags) => { 322 | return new RegExp(pattern, flags); 323 | }, 324 | /** 325 | * @param pattern 326 | * @param subject 327 | * @returns {*|null} 328 | */ 329 | match: (pattern, subject) => { 330 | const matches = pattern.exec(subject); 331 | return matches && matches.length ? matches[0] : null; 332 | }, 333 | /** 334 | * @source regex101.com 335 | * @param pattern 336 | * @param subject 337 | * @returns {*[]} 338 | */ 339 | matchAll: (pattern, subject) => { 340 | const matches = []; 341 | 342 | let m; 343 | 344 | while ((m = pattern.exec(subject)) !== null) { 345 | // This is necessary to avoid infinite loops with zero-width matches 346 | if (m.index === pattern.lastIndex) { 347 | pattern.lastIndex++; 348 | } 349 | 350 | matches.push(m[0]); 351 | } 352 | 353 | return matches; 354 | }, 355 | }, 356 | }; 357 | -------------------------------------------------------------------------------- /definitions/jsZip.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for JSZip 3.1 2 | // Project: http://stuk.github.com/jszip/, https://github.com/stuk/jszip 3 | // Definitions by: mzeiher , forabi 4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 5 | // TypeScript Version: 2.3 6 | 7 | /// 8 | 9 | interface JSZipSupport { 10 | arraybuffer: boolean; 11 | uint8array: boolean; 12 | blob: boolean; 13 | nodebuffer: boolean; 14 | } 15 | 16 | type Compression = 'STORE' | 'DEFLATE'; 17 | 18 | /** 19 | * Depends on the compression type. With `STORE` (no compression), these options are ignored. With 20 | * `DEFLATE`, you can give the compression level between 1 (best speed) and 9 (best compression). 21 | */ 22 | interface CompressionOptions { 23 | level: number; 24 | } 25 | 26 | interface InputByType { 27 | base64: string; 28 | string: string; 29 | text: string; 30 | binarystring: string; 31 | array: number[]; 32 | uint8array: Uint8Array; 33 | arraybuffer: ArrayBuffer; 34 | blob: Blob; 35 | stream: NodeJS.ReadableStream; 36 | } 37 | 38 | interface OutputByType { 39 | base64: string; 40 | string: string; 41 | text: string; 42 | binarystring: string; 43 | array: number[]; 44 | uint8array: Uint8Array; 45 | arraybuffer: ArrayBuffer; 46 | blob: Blob; 47 | nodebuffer: Buffer; 48 | } 49 | 50 | // This private `_data` property on a JSZipObject uses this interface. 51 | // If/when it is made public this should be uncommented. 52 | // interface CompressedObject { 53 | // compressedSize: number; 54 | // uncompressedSize: number; 55 | // crc32: number; 56 | // compression: object; 57 | // compressedContent: string|ArrayBuffer|Uint8Array|Buffer; 58 | // } 59 | 60 | type InputFileFormat = InputByType[keyof InputByType] | Promise; 61 | 62 | declare namespace JSZip { 63 | type InputType = keyof InputByType; 64 | 65 | type OutputType = keyof OutputByType; 66 | 67 | interface JSZipMetadata { 68 | percent: number; 69 | currentFile: string | null; 70 | } 71 | 72 | type OnUpdateCallback = (metadata: JSZipMetadata) => void; 73 | 74 | interface JSZipObject { 75 | name: string; 76 | /** 77 | * Present for files loadded with `loadAsync`. May contain ".." path components that could 78 | * result in a zip-slip attack. See https://snyk.io/research/zip-slip-vulnerability 79 | */ 80 | unsafeOriginalName?: string; 81 | dir: boolean; 82 | date: Date; 83 | comment: string; 84 | /** The UNIX permissions of the file, if any. */ 85 | unixPermissions: number | string | null; 86 | /** The UNIX permissions of the file, if any. */ 87 | dosPermissions: number | null; 88 | options: JSZipObjectOptions; 89 | 90 | /** 91 | * Prepare the content in the asked type. 92 | * @param type the type of the result. 93 | * @param onUpdate a function to call on each internal update. 94 | * @return Promise the promise of the result. 95 | */ 96 | async(type: T, onUpdate?: OnUpdateCallback): Promise; 97 | nodeStream(type?: 'nodebuffer', onUpdate?: OnUpdateCallback): NodeJS.ReadableStream; 98 | } 99 | 100 | interface JSZipFileOptions { 101 | /** Set to `true` if the data is `base64` encoded. For example image data from a `` element. Plain text and HTML do not need this option. */ 102 | base64?: boolean; 103 | /** 104 | * Set to `true` if the data should be treated as raw content, `false` if this is a text. If `base64` is used, 105 | * this defaults to `true`, if the data is not a `string`, this will be set to `true`. 106 | */ 107 | binary?: boolean; 108 | /** 109 | * The last modification date, defaults to the current date. 110 | */ 111 | date?: Date; 112 | /** 113 | * Sets per file compression. The `compressionOptions` parameter depends on the compression type. 114 | */ 115 | compression?: Compression; 116 | /** 117 | * Sets per file compression level for `DEFLATE` compression. 118 | */ 119 | compressionOptions?: null | CompressionOptions; 120 | comment?: string; 121 | /** Set to `true` if (and only if) the input is a "binary string" and has already been prepared with a `0xFF` mask. */ 122 | optimizedBinaryString?: boolean; 123 | /** Set to `true` if folders in the file path should be automatically created, otherwise there will only be virtual folders that represent the path to the file. */ 124 | createFolders?: boolean; 125 | /** Set to `true` if this is a directory and content should be ignored. */ 126 | dir?: boolean; 127 | 128 | /** 6 bits number. The DOS permissions of the file, if any. */ 129 | dosPermissions?: number | null; 130 | /** 131 | * 16 bits number. The UNIX permissions of the file, if any. 132 | * Also accepts a `string` representing the octal value: `"644"`, `"755"`, etc. 133 | */ 134 | unixPermissions?: number | string | null; 135 | } 136 | 137 | interface JSZipObjectOptions { 138 | compression: Compression; 139 | } 140 | 141 | interface JSZipGeneratorOptions { 142 | /** 143 | * Sets compression option for all entries that have not specified their own `compression` option 144 | */ 145 | compression?: Compression; 146 | /** 147 | * Sets compression level for `DEFLATE` compression. 148 | */ 149 | compressionOptions?: null | CompressionOptions; 150 | type?: T; 151 | comment?: string; 152 | /** 153 | * mime-type for the generated file. 154 | * Useful when you need to generate a file with a different extension, ie: “.ods”. 155 | * @default 'application/zip' 156 | */ 157 | mimeType?: string; 158 | encodeFileName?(filename: string): string; 159 | /** Stream the files and create file descriptors */ 160 | streamFiles?: boolean; 161 | /** DOS (default) or UNIX */ 162 | platform?: 'DOS' | 'UNIX'; 163 | } 164 | 165 | interface JSZipLoadOptions { 166 | base64?: boolean; 167 | checkCRC32?: boolean; 168 | optimizedBinaryString?: boolean; 169 | createFolders?: boolean; 170 | decodeFileName?: (bytes: string[] | Uint8Array | Buffer) => string; 171 | } 172 | 173 | type DataEventCallback = (dataChunk: T, metadata: JSZipMetadata) => void 174 | type EndEventCallback = () => void 175 | type ErrorEventCallback = (error: Error) => void 176 | 177 | interface JSZipStreamHelper { 178 | /** 179 | * Register a listener on an event 180 | */ 181 | on(event: 'data', callback: DataEventCallback): this; 182 | on(event: 'end', callback: EndEventCallback): this; 183 | on(event: 'error', callback: ErrorEventCallback): this; 184 | 185 | /** 186 | * Read the whole stream and call a callback with the complete content 187 | * 188 | * @param updateCallback The function called every time the stream updates 189 | * @return A Promise of the full content 190 | */ 191 | accumulate(updateCallback?: (metadata: JSZipMetadata) => void): Promise; 192 | 193 | /** 194 | * Resume the stream if the stream is paused. Once resumed, the stream starts sending data events again 195 | * 196 | * @return The current StreamHelper object, for chaining 197 | */ 198 | resume(): this; 199 | 200 | /** 201 | * Pause the stream if the stream is running. Once paused, the stream stops sending data events 202 | * 203 | * @return The current StreamHelper object, for chaining 204 | */ 205 | pause(): this; 206 | } 207 | } 208 | 209 | interface JSZip { 210 | files: {[key: string]: JSZip.JSZipObject}; 211 | 212 | /** 213 | * Get a file from the archive 214 | * 215 | * @param Path relative path to file 216 | * @return File matching path, null if no file found 217 | */ 218 | file(path: string): JSZip.JSZipObject | null; 219 | 220 | /** 221 | * Get files matching a RegExp from archive 222 | * 223 | * @param path RegExp to match 224 | * @return Return all matching files or an empty array 225 | */ 226 | file(path: RegExp): JSZip.JSZipObject[]; 227 | 228 | /** 229 | * Add a file to the archive 230 | * 231 | * @param path Relative path to file 232 | * @param data Content of the file 233 | * @param options Optional information about the file 234 | * @return JSZip object 235 | */ 236 | file(path: string, data: InputByType[T] | Promise, options?: JSZip.JSZipFileOptions): this; 237 | file(path: string, data: null, options?: JSZip.JSZipFileOptions & { dir: true }): this; 238 | 239 | /** 240 | * Returns an new JSZip instance with the given folder as root 241 | * 242 | * @param name Name of the folder 243 | * @return New JSZip object with the given folder as root or null 244 | */ 245 | folder(name: string): JSZip | null; 246 | 247 | /** 248 | * Returns new JSZip instances with the matching folders as root 249 | * 250 | * @param name RegExp to match 251 | * @return New array of JSZipFile objects which match the RegExp 252 | */ 253 | folder(name: RegExp): JSZip.JSZipObject[]; 254 | 255 | /** 256 | * Call a callback function for each entry at this folder level. 257 | * 258 | * @param callback function 259 | */ 260 | forEach(callback: (relativePath: string, file: JSZip.JSZipObject) => void): void; 261 | 262 | /** 263 | * Get all files which match the given filter function 264 | * 265 | * @param predicate Filter function 266 | * @return Array of matched elements 267 | */ 268 | filter(predicate: (relativePath: string, file: JSZip.JSZipObject) => boolean): JSZip.JSZipObject[]; 269 | 270 | /** 271 | * Removes the file or folder from the archive 272 | * 273 | * @param path Relative path of file or folder 274 | * @return Returns the JSZip instance 275 | */ 276 | remove(path: string): JSZip; 277 | 278 | /** 279 | * Generates a new archive asynchronously 280 | * 281 | * @param options Optional options for the generator 282 | * @param onUpdate The optional function called on each internal update with the metadata. 283 | * @return The serialized archive 284 | */ 285 | generateAsync(options?: JSZip.JSZipGeneratorOptions, onUpdate?: JSZip.OnUpdateCallback): Promise; 286 | 287 | /** 288 | * Generates a new archive asynchronously 289 | * 290 | * @param options Optional options for the generator 291 | * @param onUpdate The optional function called on each internal update with the metadata. 292 | * @return A Node.js `ReadableStream` 293 | */ 294 | generateNodeStream(options?: JSZip.JSZipGeneratorOptions<'nodebuffer'>, onUpdate?: JSZip.OnUpdateCallback): NodeJS.ReadableStream; 295 | 296 | /** 297 | * Generates the complete zip file with the internal stream implementation 298 | * 299 | * @param options Optional options for the generator 300 | * @return a StreamHelper 301 | */ 302 | generateInternalStream(options?: JSZip.JSZipGeneratorOptions): JSZip.JSZipStreamHelper; 303 | 304 | /** 305 | * Deserialize zip file asynchronously 306 | * 307 | * @param data Serialized zip file 308 | * @param options Options for deserializing 309 | * @return Returns promise 310 | */ 311 | loadAsync(data: InputFileFormat, options?: JSZip.JSZipLoadOptions): Promise; 312 | 313 | /** 314 | * Create JSZip instance 315 | */ 316 | new(): this; 317 | 318 | (): JSZip; 319 | 320 | prototype: JSZip; 321 | support: JSZipSupport; 322 | external: { 323 | Promise: PromiseConstructorLike; 324 | }; 325 | version: string; 326 | } 327 | 328 | declare var JSZip: JSZip; 329 | 330 | export = JSZip; -------------------------------------------------------------------------------- /src/includes/ui.js: -------------------------------------------------------------------------------- 1 | const ui = { 2 | /** 3 | * @returns {string} 4 | */ 5 | getTooltipBackgroundColor: () => { 6 | const theme = document.body.innerHTML.indexOf('__&s=11') > -1 ? 'purple' : 'classic'; 7 | return theme === 'purple' ? '#30204f' : '#2a2929'; 8 | }, 9 | /** 10 | * @param target 11 | * @param content 12 | * @param options 13 | * @returns {*} 14 | */ 15 | tooltip: (target, content, options = {}) => { 16 | // noinspection JSUnusedGlobalSymbols 17 | return tippy(target, { 18 | arrow: true, 19 | theme: 'transparent', 20 | allowHTML: true, 21 | content: content, 22 | appendTo: () => document.body, 23 | placement: 'left', 24 | interactive: true, 25 | ...options, 26 | }); 27 | }, 28 | pBars: { 29 | /** 30 | * @param color 31 | * @param height 32 | * @param width 33 | * @returns {HTMLDivElement} 34 | */ 35 | base: (color, height = '3px', width = '0%') => { 36 | const pb = document.createElement('div'); 37 | pb.style.height = height; 38 | pb.style.background = color; 39 | pb.style.width = width; 40 | return pb; 41 | }, 42 | /** 43 | * @param color 44 | * @returns {HTMLDivElement} 45 | */ 46 | createFileProgressBar: (color = '#46658b') => { 47 | const pb = ui.pBars.base(color); 48 | pb.style.marginBottom = '1px'; 49 | return pb; 50 | }, 51 | /** 52 | * @param color 53 | * @returns {HTMLDivElement} 54 | */ 55 | createTotalProgressBar: (color = '#545454') => { 56 | const pb = ui.pBars.base(color); 57 | pb.style.marginBottom = '10px'; 58 | return pb; 59 | }, 60 | }, 61 | labels: { 62 | /** 63 | * @param initialText 64 | * @param color 65 | * @returns {{container: HTMLDivElement, el: HTMLSpanElement}} 66 | */ 67 | createBlockLabel: (initialText = null, color = '#959595') => { 68 | const container = document.createElement('div'); 69 | container.style.color = color; 70 | container.style.fontSize = '12px'; 71 | 72 | const span = document.createElement('span'); 73 | container.appendChild(span); 74 | 75 | if (initialText) { 76 | span.textContent = initialText; 77 | } 78 | 79 | return { 80 | el: span, 81 | container, 82 | }; 83 | }, 84 | status: { 85 | /** 86 | * @param initialText 87 | * @returns {{container: HTMLDivElement, el: HTMLSpanElement}} 88 | */ 89 | createStatusLabel: (initialText = '') => { 90 | const label = ui.labels.createBlockLabel(initialText); 91 | label.el.style.marginBottom = '3px'; 92 | 93 | return label; 94 | }, 95 | }, 96 | }, 97 | buttons: { 98 | /** 99 | * @returns {HTMLAnchorElement} 100 | */ 101 | createPostDownloadButton: () => { 102 | const downloadPostBtn = document.createElement('a'); 103 | downloadPostBtn.setAttribute('href', '#'); 104 | downloadPostBtn.innerHTML = '🡳 Download'; 105 | 106 | return downloadPostBtn; 107 | }, 108 | /** 109 | * @returns {HTMLLIElement} 110 | */ 111 | createPostDownloadButtonContainer: () => { 112 | return document.createElement('li'); 113 | }, 114 | /** 115 | * @param post 116 | * @returns {{container: HTMLLIElement, btn: HTMLAnchorElement}} 117 | */ 118 | addDownloadPostButton: post => { 119 | const btnDownloadPostContainer = ui.buttons.createPostDownloadButtonContainer(); 120 | const btnDownloadPost = ui.buttons.createPostDownloadButton(); 121 | btnDownloadPostContainer.appendChild(btnDownloadPost); 122 | post.prepend(btnDownloadPostContainer); 123 | 124 | return { 125 | container: btnDownloadPostContainer, 126 | btn: btnDownloadPost, 127 | }; 128 | }, 129 | }, 130 | forms: { 131 | /** 132 | * @param id 133 | * @param label 134 | * @param checked 135 | * @returns {string} 136 | */ 137 | createCheckbox: (id, label, checked) => { 138 | return ` 139 | 151 | `; 152 | }, 153 | /** 154 | * @param content 155 | * @returns {string} 156 | */ 157 | createRow: content => { 158 | return ` 159 | 162 | `; 163 | }, 164 | /** 165 | * @param label 166 | * @returns {string} 167 | */ 168 | createLabel: label => { 169 | return ` 170 |
171 | ${label} 172 |
173 | `; 174 | }, 175 | config: { 176 | page: { 177 | /** 178 | * @param backgroundColor 179 | * @param innerHTML 180 | * @returns {string} 181 | */ 182 | createForm: (backgroundColor, innerHTML) => { 183 | return ` 184 | 191 | `; 192 | }, 193 | }, 194 | post: { 195 | /** 196 | * @param postId 197 | * @param backgroundColor 198 | * @param innerHTML 199 | * @returns {string} 200 | */ 201 | createForm: (postId, backgroundColor, innerHTML) => { 202 | return ` 203 | 210 | `; 211 | }, 212 | /** 213 | * @param currentValue 214 | * @param postId 215 | * @param backgroundColor 216 | * @param placeholder 217 | * @returns {string} 218 | */ 219 | createFilenameInput: (currentValue, postId, backgroundColor, placeholder) => { 220 | return ` 221 | 237 | `; 238 | }, 239 | /** 240 | * @returns {string} 241 | */ 242 | createZippedCheckbox: (postId, checked) => { 243 | return ui.forms.createCheckbox(`settings-${postId}-zipped`, 'Zipped', checked); 244 | }, 245 | /** 246 | * @returns {string} 247 | */ 248 | createFlattenCheckbox: (postId, checked) => { 249 | return ui.forms.createCheckbox(`settings-${postId}-flatten`, 'Flatten', checked); 250 | }, 251 | /** 252 | * @returns {string} 253 | */ 254 | createSkipDownloadCheckbox: (postId, checked) => { 255 | return ui.forms.createCheckbox(`settings-${postId}-skip-download`, 'Skip Download', checked); 256 | }, 257 | /** 258 | * @returns {string} 259 | */ 260 | createGenerateLinksCheckbox: (postId, checked) => { 261 | return ui.forms.createCheckbox(`settings-${postId}-generate-links`, 'Generate Links', checked); 262 | }, 263 | /** 264 | * @returns {string} 265 | */ 266 | createGenerateLogCheckbox: (postId, checked) => { 267 | return ui.forms.createCheckbox(`settings-${postId}-generate-log`, 'Generate Log', checked); 268 | }, 269 | /** 270 | * @returns {string} 271 | */ 272 | createSkipDuplicatesCheckbox: (postId, checked) => { 273 | return ui.forms.createCheckbox(`settings-${postId}-skip-duplicates`, 'Skip Duplicates', checked); 274 | }, 275 | /** 276 | * @param hosts 277 | * @param getTotalDownloadableResourcesCB 278 | * @returns {string} 279 | */ 280 | createFilterLabel: (hosts, getTotalDownloadableResourcesCB) => { 281 | return ` 282 |
Filter (${getTotalDownloadableResourcesCB( 283 | hosts, 284 | )})
285 | `; 286 | }, 287 | /** 288 | * @param postId 289 | * @returns {string} 290 | */ 291 | createToggleAllCheckbox: postId => { 292 | return ui.forms.createCheckbox(`settings-toggle-all-hosts-${postId}`, settings.ui.checkboxes.toggleAllCheckboxLabel, true); 293 | }, 294 | /** 295 | * @param postId 296 | * @param host 297 | * @returns {string} 298 | */ 299 | createHostCheckbox: (postId, host) => { 300 | const title = `${host.name} ${host.category}`; 301 | return ui.forms.createCheckbox(`downloader-host-${host.id}-${postId}`, `${title} (${host.resources.length})`, host.enabled); 302 | }, 303 | /** 304 | * @param postId 305 | * @param filterLabel 306 | * @param hostsHtml 307 | * @param createToggleAllCheckbox 308 | * @returns {string} 309 | */ 310 | createHostCheckboxes: (postId, filterLabel, hostsHtml, createToggleAllCheckbox) => { 311 | return ` 312 |
313 | ${filterLabel} 314 | ${createToggleAllCheckbox ? ui.forms.config.post.createToggleAllCheckbox(postId) : ''} 315 | ${hostsHtml} 316 |
317 | `; 318 | }, 319 | /** 320 | * @param parsedPost 321 | * @param parsedHosts 322 | * @param defaultFilename 323 | * @param settings 324 | * @param onSubmitFormCB 325 | * @param totalDownloadableResourcesForPostCB 326 | * @param btnDownloadPost 327 | */ 328 | createPostConfigForm: ( 329 | parsedPost, 330 | parsedHosts, 331 | defaultFilename, 332 | settings, 333 | onSubmitFormCB, 334 | totalDownloadableResourcesForPostCB, 335 | btnDownloadPost, 336 | ) => { 337 | const { postId } = parsedPost; 338 | const color = ui.getTooltipBackgroundColor(); 339 | 340 | const customFilename = settings.output.find(o => o.postId === postId)?.value || ''; 341 | 342 | let hostsHtml = '
'; 343 | parsedHosts.forEach(host => (hostsHtml += ui.forms.config.post.createHostCheckbox(postId, host))); 344 | hostsHtml += '
'; 345 | 346 | const filterLabel = ui.forms.config.post.createFilterLabel(parsedHosts, totalDownloadableResourcesForPostCB); 347 | 348 | const settingsHeading = ` 349 | 354 | `; 355 | 356 | let formHtml = [ 357 | window.isFF ? ui.forms.config.post.createFilenameInput(customFilename, postId, color, defaultFilename) : null, 358 | settingsHeading, 359 | !window.isFF ? ui.forms.config.post.createZippedCheckbox(postId, settings.zipped) : null, 360 | ui.forms.config.post.createFlattenCheckbox(postId, settings.flatten), 361 | ui.forms.config.post.createSkipDuplicatesCheckbox(postId, settings.skipDuplicates), 362 | ui.forms.config.post.createGenerateLinksCheckbox(postId, settings.generateLinks), 363 | ui.forms.config.post.createGenerateLogCheckbox(postId, settings.generateLog), 364 | ui.forms.config.post.createSkipDownloadCheckbox(postId, settings.skipDownload), 365 | ui.forms.config.post.createHostCheckboxes(postId, filterLabel, hostsHtml, parsedHosts.length > 1), 366 | ui.forms.createRow( 367 | ' Show Download Page Button', 368 | ), 369 | ].filter(c => c !== null); 370 | 371 | const configForm = ui.forms.config.post.createForm(postId, color, formHtml.join('')); 372 | 373 | ui.tooltip(btnDownloadPost, configForm, { 374 | onShown: instance => { 375 | const inputEl = h.element(`#filename-input-${postId}`); 376 | if (inputEl) { 377 | inputEl.addEventListener('input', e => { 378 | const value = e.target.value; 379 | const o = settings.output.find(o => o.postId === postId); 380 | if (o) { 381 | o.value = value; 382 | } else { 383 | settings.output.push({ 384 | postId, 385 | value, 386 | }); 387 | } 388 | }); 389 | } 390 | 391 | let prevSettings = JSON.parse(JSON.stringify(settings)); 392 | 393 | const setPrevSettings = settings => { 394 | prevSettings = JSON.parse(JSON.stringify(settings)); 395 | }; 396 | 397 | let updateSettings = true; 398 | 399 | h.element(`#settings-${postId}-skip-download`).addEventListener('change', e => { 400 | const checked = e.target.checked; 401 | 402 | settings.skipDownload = checked; 403 | 404 | settings.flatten = checked ? false : prevSettings.flatten; 405 | settings.skipDuplicates = checked ? false : prevSettings.skipDuplicates; 406 | settings.generateLinks = checked ? true : prevSettings.generateLinks; 407 | 408 | updateSettings = false; 409 | 410 | h.element(`#settings-${postId}-flatten`).checked = checked ? false : prevSettings.flatten; 411 | h.element(`#settings-${postId}-flatten`).disabled = checked; 412 | 413 | h.element(`#settings-${postId}-skip-duplicates`).checked = checked ? false : prevSettings.skipDuplicates; 414 | h.element(`#settings-${postId}-skip-duplicates`).disabled = checked; 415 | 416 | h.element(`#settings-${postId}-generate-links`).checked = checked ? true : prevSettings.generateLinks; 417 | h.element(`#settings-${postId}-generate-links`).disabled = checked; 418 | 419 | setTimeout(() => (updateSettings = true), 100); 420 | }); 421 | 422 | if (!window.isFF) { 423 | h.element(`#settings-${postId}-zipped`).addEventListener('change', e => { 424 | settings.zipped = e.target.checked; 425 | }); 426 | } 427 | 428 | h.element(`#settings-${postId}-generate-links`).addEventListener('change', e => { 429 | settings.generateLinks = e.target.checked; 430 | 431 | if (updateSettings) { 432 | setPrevSettings(settings); 433 | } 434 | }); 435 | 436 | h.element(`#settings-${postId}-generate-log`).addEventListener('change', e => { 437 | settings.generateLog = e.target.checked; 438 | 439 | if (updateSettings) { 440 | setPrevSettings(settings); 441 | } 442 | }); 443 | 444 | h.element(`#settings-${postId}-flatten`).addEventListener('change', e => { 445 | settings.flatten = e.target.checked; 446 | 447 | if (updateSettings) { 448 | setPrevSettings(settings); 449 | } 450 | }); 451 | 452 | h.element(`#settings-${postId}-skip-duplicates`).addEventListener('change', e => { 453 | settings.skipDuplicates = e.target.checked; 454 | 455 | if (updateSettings) { 456 | setPrevSettings(settings); 457 | } 458 | }); 459 | 460 | h.element(`#download-config-form-${postId}`).addEventListener('submit', async e => { 461 | e.preventDefault(); 462 | onSubmitFormCB({ tippyInstance: instance }); 463 | }); 464 | 465 | if (parsedHosts.length > 1) { 466 | h.element(`#settings-toggle-all-hosts-${postId}`).addEventListener('change', async e => { 467 | e.preventDefault(); 468 | 469 | const checked = e.target.checked; 470 | 471 | const hostCheckboxes = parsedHosts.flatMap(host => h.element(`#downloader-host-${host.id}-${postId}`)); 472 | const checkedHostCheckboxes = hostCheckboxes.filter(e => e.checked); 473 | const unCheckedHostCheckboxes = hostCheckboxes.filter(e => !e.checked); 474 | 475 | if (checked) { 476 | unCheckedHostCheckboxes.forEach(c => c.click()); 477 | } else { 478 | checkedHostCheckboxes.forEach(c => c.click()); 479 | } 480 | }); 481 | } 482 | 483 | parsedHosts.forEach(host => { 484 | h.element(`#downloader-host-${host.id}-${postId}`).addEventListener('change', e => { 485 | host.enabled = e.target.checked; 486 | const filteredCount = totalDownloadableResourcesForPostCB(parsedHosts); 487 | h.element('#filtered-count').textContent = `(${filteredCount})`; 488 | 489 | if (parsedHosts.length > 0) { 490 | const checkedLength = parsedHosts 491 | .flatMap(host => h.element(`#downloader-host-${host.id}-${postId}`)) 492 | .filter(h => h.checked).length; 493 | 494 | const totalResources = parsedHosts.reduce((acc, host) => acc + host.resources.length, 0); 495 | 496 | const totalDownloadableResources = parsedHosts 497 | .filter(host => host.enabled && host.resources.length) 498 | .reduce((acc, host) => acc + host.resources.length, 0); 499 | 500 | btnDownloadPost.innerHTML = `🡳 Download (${totalDownloadableResources}/${totalResources})`; 501 | 502 | if (parsedHosts.length > 1) { 503 | const toggleAllHostsCheckbox = h.element(`#settings-toggle-all-hosts-${postId}`); 504 | 505 | if (checkedLength !== parsedHosts.length) { 506 | toggleAllHostsCheckbox.removeAttribute('checked'); 507 | toggleAllHostsCheckbox.checked = false; 508 | } else { 509 | toggleAllHostsCheckbox.setAttribute('checked', 'checked'); 510 | toggleAllHostsCheckbox.checked = true; 511 | } 512 | } 513 | } 514 | }); 515 | }); 516 | }, 517 | }); 518 | }, 519 | }, 520 | }, 521 | }, 522 | }; 523 | -------------------------------------------------------------------------------- /definitions/tampermonkey.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for non-npm package Tampermonkey 4.x 2 | // Project: https://tampermonkey.net 3 | // Definitions by: Steven Wang 4 | // Nikolay Borzov 5 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 6 | 7 | // This definition is based on the API reference of Tampermonkey 8 | // https://tampermonkey.net/documentation.php 9 | // TypeScript Version: 3.3 10 | 11 | declare namespace Tampermonkey { 12 | type ValueChangeListener = ( 13 | name: string, 14 | oldValue: any, 15 | newValue: any, 16 | remote: boolean 17 | ) => void; 18 | 19 | // Response 20 | 21 | enum ReadyState { 22 | Unsent = 0, 23 | Opened = 1, 24 | HeadersReceived = 2, 25 | Loading = 3, 26 | Done = 4 27 | } 28 | 29 | interface ResponseBase { 30 | readonly responseHeaders: string; 31 | readonly readyState: ReadyState; 32 | readonly response: any; 33 | readonly responseText: string; 34 | readonly responseXML: Document | null; 35 | readonly status: number; 36 | readonly statusText: string; 37 | } 38 | 39 | interface ProgressResponseBase { 40 | done: number; 41 | lengthComputable: boolean; 42 | loaded: number; 43 | position: number; 44 | total: number; 45 | totalSize: number; 46 | } 47 | 48 | interface ErrorResponse extends ResponseBase { 49 | readonly error: string; 50 | } 51 | 52 | interface Response extends ResponseBase { 53 | readonly finalUrl: string; 54 | readonly context: TContext; 55 | } 56 | 57 | interface ProgressResponse 58 | extends Response, 59 | ProgressResponseBase {} 60 | 61 | // Request 62 | 63 | interface RequestHeaders { 64 | readonly [header: string]: string; 65 | } 66 | 67 | type RequestEventListener = ( 68 | this: TResponse, 69 | response: TResponse 70 | ) => void; 71 | 72 | interface Request { 73 | method?: 'GET' | 'HEAD' | 'POST' | undefined; 74 | /** Destination URL */ 75 | url: string; 76 | /** 77 | * i.e. user-agent, referer... (some special headers are not supported 78 | * by Safari and Android browsers) 79 | */ 80 | headers?: RequestHeaders | undefined; 81 | /** String to send via a POST request */ 82 | data?: string | undefined; 83 | /** A cookie to be patched into the sent cookie set */ 84 | cookie?: string | undefined; 85 | /** Send the data string in binary mode */ 86 | binary?: boolean | undefined; 87 | /** Don't cache the resource */ 88 | nocache?: boolean | undefined; 89 | /** Revalidate maybe cached content */ 90 | revalidate?: boolean | undefined; 91 | /** Timeout in ms */ 92 | timeout?: number | undefined; 93 | /** Property which will be added to the response object */ 94 | context?: TContext | undefined; 95 | responseType?: 'arraybuffer' | 'blob' | 'json' | undefined; 96 | /** MIME type for the request */ 97 | overrideMimeType?: string | undefined; 98 | /** Don't send cookies with the requests (please see the fetch notes) */ 99 | anonymous?: boolean | undefined; 100 | /** 101 | * (Beta) Use a fetch instead of a xhr request(at Chrome this causes 102 | * `xhr.abort`, `details.timeout` and `xhr.onprogress` to not work and 103 | * makes `xhr.onreadystatechange` receive only readyState 4 events) 104 | */ 105 | fetch?: boolean | undefined; 106 | /** Username for authentication */ 107 | user?: string | undefined; 108 | password?: string | undefined; 109 | 110 | // Events 111 | 112 | /** Callback to be executed if the request was aborted */ 113 | onabort?(): void; 114 | /** Callback to be executed if the request ended up with an error */ 115 | onerror?: RequestEventListener | undefined; 116 | /** Callback to be executed if the request started to load */ 117 | onloadstart?: RequestEventListener> | undefined; 118 | /** Callback to be executed if the request made some progress */ 119 | onprogress?: RequestEventListener> | undefined; 120 | /** Callback to be executed if the request's ready state changed */ 121 | onreadystatechange?: RequestEventListener> | undefined; 122 | /** Callback to be executed if the request failed due to a timeout */ 123 | ontimeout?(): void; 124 | /** Callback to be executed if the request was loaded */ 125 | onload?: RequestEventListener> | undefined; 126 | } 127 | 128 | // Download Response 129 | 130 | interface DownloadProgressResponse extends ProgressResponseBase { 131 | readonly finalUrl: string; 132 | } 133 | 134 | interface DownloadErrorResponse { 135 | /** 136 | * Error reason 137 | * - `not_enabled` - the download feature isn't enabled by the user 138 | * - `not_whitelisted` - the requested file extension is not 139 | * whitelisted 140 | * - `not_permitted` - the user enabled the download feature, but did 141 | * not give the downloads permission 142 | * - `not_supported` - the download feature isn't supported by the 143 | * browser/version 144 | * - `not_succeeded` - the download wasn't started or failed, the 145 | * details attribute may provide more information 146 | */ 147 | error: 148 | | 'not_enabled' 149 | | 'not_whitelisted' 150 | | 'not_permitted' 151 | | 'not_supported' 152 | | 'not_succeeded'; 153 | /** Detail about that error */ 154 | details?: string | undefined; 155 | } 156 | 157 | // Download Request 158 | 159 | interface DownloadRequest { 160 | /** URL from where the data should be downloaded */ 161 | url: string; 162 | /** 163 | * Filename - for security reasons the file extension needs to be 164 | * whitelisted at Tampermonkey options page 165 | */ 166 | name: string; 167 | headers?: RequestHeaders | undefined; 168 | /** Show 'Save As' dialog */ 169 | saveAs?: boolean | undefined; 170 | timeout?: number | undefined; 171 | /** Callback to be executed if this download ended up with an error */ 172 | onerror?: RequestEventListener | undefined; 173 | /** Callback to be executed if this download finished */ 174 | ontimeout?(): void; 175 | /** Callback to be executed if this download finished */ 176 | onload?(): void; 177 | /** Callback to be executed if this download failed due to a timeout */ 178 | onprogress?: RequestEventListener | undefined; 179 | } 180 | 181 | interface AbortHandle { 182 | abort(): TReturn; 183 | } 184 | 185 | interface OpenTabOptions { 186 | /** Decides whether the new tab should be focused */ 187 | active?: boolean | undefined; 188 | /** Inserts the new tab after the current one */ 189 | insert?: boolean | undefined; 190 | /** Makes the browser re-focus the current tab on close */ 191 | setParent?: boolean | undefined; 192 | } 193 | 194 | interface OpenTabObject { 195 | /** Closes tab */ 196 | close(): void; 197 | /** Set closed listener */ 198 | onclose?(): void; 199 | closed: boolean; 200 | } 201 | 202 | interface NotificationThis extends Notification { 203 | id: string; 204 | } 205 | 206 | type NotificationOnClick = (this: NotificationThis) => void; 207 | /** `clicked` is `true` when `text` was set */ 208 | type NotificationOnDone = (this: NotificationThis, clicked: boolean) => void; 209 | 210 | interface Notification { 211 | /** Text of the notification (optional if highlight is set) */ 212 | text?: string | undefined; 213 | /** Notification title. If not specified the script name is used */ 214 | title?: string | undefined; 215 | image?: string | undefined; 216 | /** Flag whether to highlight the tab that sends the notification */ 217 | highlight?: boolean | undefined; 218 | /** Whether to play or not play a sound */ 219 | silent?: boolean | undefined; 220 | /** Time after that the notification will be hidden. `0` = disabled */ 221 | timeout?: number | undefined; 222 | /** 223 | * Called when the notification is closed (no matter if this was 224 | * triggered by a timeout or a click) or the tab was highlighted 225 | */ 226 | onclick?: NotificationOnClick | undefined; 227 | /** Called in case the user clicks the notification */ 228 | ondone?: NotificationOnDone | undefined; 229 | } 230 | 231 | interface TextNotification extends Notification { 232 | /** Text of the notification (optional if highlight is set) */ 233 | text: string; 234 | } 235 | 236 | interface HighlightNotification extends Notification { 237 | text?: undefined; 238 | highlight: true; 239 | } 240 | 241 | type NotificationDetails = TextNotification | HighlightNotification; 242 | 243 | // Interfaces for GM_info 244 | 245 | /** 246 | * The metadata that the user can override in the settings 247 | * for example run-at or excludes 248 | */ 249 | interface ScriptMetadataOverrides { 250 | merge_connects: boolean; 251 | merge_excludes: boolean; 252 | merge_includes: boolean; 253 | merge_matches: boolean; 254 | orig_connects: string[]; 255 | orig_excludes: string[]; 256 | orig_includes: string[]; 257 | orig_matches: string[]; 258 | orig_noframes: string | null; 259 | orig_run_at: string | null; 260 | use_blockers: string[]; 261 | use_connects: string[]; 262 | use_excludes: string[]; 263 | use_includes: string[]; 264 | use_matches: string[]; 265 | } 266 | 267 | /** 268 | * The options that the user of the userscript 269 | * can set in the settings (!== overrides) 270 | */ 271 | interface ScriptSettings { 272 | check_for_updates: boolean; 273 | comment: string | null; 274 | compat_foreach: boolean; 275 | compat_metadata: boolean; 276 | compat_prototypes: boolean; 277 | compat_wrappedjsobject: boolean; 278 | compatopts_for_requires: boolean; 279 | noframes: boolean | null; 280 | run_at: string; 281 | override: ScriptMetadataOverrides; 282 | } 283 | 284 | /** 285 | * The resources from the metadata block (@resources) 286 | * that tampermonkey should preload 287 | */ 288 | interface ScriptResource { 289 | name: string; 290 | url: string; 291 | content: string; 292 | meta: string; 293 | } 294 | 295 | /** 296 | * `.. | null` means if it was not explicitely set in the metadata 297 | * block it is null 298 | */ 299 | interface ScriptMetadata { 300 | antifeatures: Record>; 301 | author: string | null; 302 | 303 | /** 304 | * Idk what this is, nothing I did changed this from any empty array 305 | * and it's not documented anywhere 306 | */ 307 | blockers: any[]; 308 | 309 | copyright: string | null; 310 | description: string | null; 311 | description_i18n: Record; 312 | downloadURL: string | null; 313 | evilness: number; 314 | excludes: string[]; 315 | grant: string[]; 316 | header: string; 317 | homepage: string | null; 318 | icon: string | null; 319 | icon64: string | null; 320 | includes: string[]; 321 | lastModified: number; 322 | matches: string[]; 323 | name: string; 324 | name_i18n: Record; 325 | namespace: string | null; 326 | options: ScriptSettings; 327 | 328 | position: number; 329 | resources: ScriptResource[]; 330 | 331 | /** 332 | * Never null, defaults to document-idle 333 | */ 334 | 'run-at': string; 335 | 336 | supportURL: string | null; 337 | sync: { 338 | imported: boolean; 339 | }; 340 | unwrap: boolean; 341 | updateURL: string | null; 342 | uuid: string; 343 | version: string; 344 | webRequest: string[]; 345 | } 346 | 347 | interface ScriptInfo { 348 | downloadMode: 'native' | 'browser' | 'disabled'; 349 | isFirstPartyIsolation: boolean | undefined; 350 | isIncognito: boolean; 351 | script: ScriptMetadata; 352 | 353 | /** 354 | * In tampermonkey it's "Tampermonkey" 355 | * but I'll leave it as string so this can be used 356 | * for other managers 357 | */ 358 | scriptHandler: string; 359 | 360 | scriptMetaStr: string; 361 | scriptSource: string; 362 | scriptUpdateURL: string | undefined; 363 | scriptWillUpdate: boolean; 364 | 365 | /** This refers to tampermonkey's version */ 366 | version: string; 367 | } 368 | 369 | type ContentType = string | { type?: string | undefined; mimetype?: string | undefined }; 370 | } 371 | 372 | /** 373 | * The unsafeWindow object provides full access to the pages javascript 374 | * functions and variables 375 | */ 376 | declare var unsafeWindow: Window; 377 | 378 | // Styles 379 | 380 | /** 381 | * Adds the given style to the document and returns the injected style element. 382 | */ 383 | declare function GM_addStyle(css: string): HTMLStyleElement; 384 | 385 | // Storage 386 | 387 | /** Sets the value of `name` to the storage */ 388 | declare function GM_setValue(name: string, value: any): void; 389 | 390 | /** 391 | * Adds a change listener to the storage and returns the listener ID. 392 | * The `remote` argument of the callback function shows whether this value was 393 | * modified from the instance of another tab (`true`) or within this script 394 | * instance (`false`). Therefore this functionality can be used by scripts of 395 | * different browser tabs to communicate with each other. 396 | * @param name Name of the observed variable 397 | * @param listener 398 | */ 399 | declare function GM_addValueChangeListener( 400 | name: string, 401 | listener: Tampermonkey.ValueChangeListener 402 | ): number; 403 | 404 | /** Removes a change listener by its ID */ 405 | declare function GM_removeValueChangeListener(listenerId: number): void; 406 | 407 | /** Gets the value of 'name' from storage */ 408 | declare function GM_getValue( 409 | name: string, 410 | defaultValue?: TValue 411 | ): TValue; 412 | 413 | /** Deletes 'name' from storage */ 414 | declare function GM_deleteValue(name: string): void; 415 | 416 | /** Lists all names of the storage */ 417 | declare function GM_listValues(): string[]; 418 | 419 | // Resources 420 | 421 | /** Get the content of a predefined `@resource` tag at the script header */ 422 | declare function GM_getResourceText(name: string): string; 423 | 424 | /** 425 | * Get the base64 encoded URI of a predefined `@resource` tag at the script 426 | * header 427 | */ 428 | declare function GM_getResourceURL(name: string): string; 429 | 430 | // Menu commands 431 | 432 | /** 433 | * Register a menu to be displayed at the Tampermonkey menu at pages where this 434 | * script runs and returns a menu command ID. 435 | */ 436 | declare function GM_registerMenuCommand( 437 | name: string, 438 | onClick: () => void, 439 | accessKey?: string 440 | ): number; 441 | 442 | /** 443 | * Unregister a menu command that was previously registered by 444 | * `GM_registerMenuCommand` or `GM.registerMenuCommand` with the given menu command ID. 445 | */ 446 | declare function GM_unregisterMenuCommand(menuCommandId: number): void; 447 | 448 | // Requests 449 | 450 | /** Makes an xmlHttpRequest */ 451 | declare function GM_xmlhttpRequest( 452 | details: Tampermonkey.Request // tslint:disable-line:no-unnecessary-generics 453 | ): Tampermonkey.AbortHandle; 454 | 455 | /** Downloads a given URL to the local disk */ 456 | declare function GM_download( 457 | details: Tampermonkey.DownloadRequest 458 | ): Tampermonkey.AbortHandle; 459 | declare function GM_download( 460 | url: string, 461 | name: string 462 | ): Tampermonkey.AbortHandle; 463 | 464 | // Tabs 465 | 466 | /** Saves the tab object to reopen it after a page unload */ 467 | declare function GM_saveTab(obj: object): void; 468 | 469 | /** Gets a object that is persistent as long as this tab is open */ 470 | declare function GM_getTab(callback: (obj: any) => void): void; 471 | 472 | /** Gets all tab objects as a hash to communicate with other script instances */ 473 | declare function GM_getTabs( 474 | callback: (tabsMap: { [tabId: number]: any }) => void 475 | ): void; 476 | 477 | // Utils 478 | 479 | declare const GM_info: Tampermonkey.ScriptInfo; 480 | 481 | /** Log a message to the console */ 482 | declare function GM_log(...message: any[]): void; 483 | 484 | /** 485 | * Opens a new tab with this url. 486 | * The options object can have the following properties: 487 | * - `active` decides whether the new tab should be focused, 488 | * - `insert` that inserts the new tab after the current one and 489 | * - `setParent` makes the browser re-focus the current tab on close. 490 | * 491 | * Otherwise the new tab is just appended. 492 | * If `options` is boolean (loadInBackground) it has the opposite meaning of 493 | * active and was added to achieve Greasemonkey 3.x compatibility. 494 | * 495 | * If neither active nor loadInBackground is given, then the tab will not be 496 | * focused. 497 | * @returns Object with the function `close`, the listener `onclose` and a flag 498 | * called `closed`. 499 | */ 500 | declare function GM_openInTab( 501 | url: string, 502 | options?: Tampermonkey.OpenTabOptions | boolean 503 | ): Tampermonkey.OpenTabObject; 504 | 505 | /** 506 | * Shows a HTML5 Desktop notification and/or highlight the current tab. 507 | * @param details 508 | * @param ondone If specified used instead of `details.ondone` 509 | */ 510 | declare function GM_notification( 511 | details: Tampermonkey.NotificationDetails, 512 | ondone?: Tampermonkey.NotificationOnDone 513 | ): void; 514 | 515 | /** 516 | * Shows a HTML5 Desktop notification and/or highlight the current tab. 517 | * @param text Text of the notification 518 | * @param title Notification title. If not specified the script name is used 519 | * @param image 520 | * @param onclick Called in case the user clicks the notification 521 | */ 522 | declare function GM_notification( 523 | text: string, 524 | title?: string, 525 | image?: string, 526 | onclick?: Tampermonkey.NotificationOnClick 527 | ): void; 528 | 529 | /** 530 | * Copies data into the clipboard. 531 | * The parameter 'info' can be an object like 532 | * `{ type: 'text', mimetype: 'text/plain'}` or just a string expressing the 533 | * type ("text" or "html"). 534 | */ 535 | declare function GM_setClipboard( 536 | data: string, 537 | info?: Tampermonkey.ContentType, 538 | ): void; 539 | 540 | // GM.* 541 | 542 | /** 543 | * `GM` has all the `GM_*` apis in promisified form 544 | */ 545 | declare const GM: Readonly<{ 546 | // Styles 547 | 548 | /** 549 | * Adds the given style to the document and returns the injected style element. 550 | */ 551 | addStyle(css: string): Promise; 552 | 553 | // Storage 554 | 555 | /** Sets the value of `name` to the storage */ 556 | setValue(name: string, value: any): Promise; 557 | 558 | /** Gets the value of 'name' from storage */ 559 | getValue(name: string, defaultValue?: TValue): Promise; 560 | 561 | /** Deletes 'name' from storage */ 562 | deleteValue(name: string): Promise; 563 | 564 | /** Lists all names of the storage */ 565 | listValues(): Promise; 566 | 567 | /** 568 | * Adds a change listener to the storage and returns the listener ID. 569 | * The `remote` argument of the callback function shows whether this value was 570 | * modified from the instance of another tab (`true`) or within this script 571 | * instance (`false`). Therefore this functionality can be used by scripts of 572 | * different browser tabs to communicate with each other. 573 | * @param name Name of the observed variable 574 | * @param listener 575 | */ 576 | addValueChangeListener(name: string, listener: Tampermonkey.ValueChangeListener): Promise; 577 | 578 | /** Removes a change listener by its ID */ 579 | removeValueChangeListener(listenerId: number): Promise; 580 | 581 | // Resources 582 | 583 | /** Get the content of a predefined `@resource` tag at the script header */ 584 | getResourceText(name: string): Promise; 585 | 586 | /** 587 | * Get the base64 encoded URI of a predefined `@resource` tag at the script 588 | * header 589 | */ 590 | getResourceUrl(name: string): Promise; 591 | 592 | // Menu commands 593 | 594 | /** 595 | * Register a menu to be displayed at the Tampermonkey menu at pages where this 596 | * script runs and returns a menu command ID. 597 | * @param name 598 | * @param onClick 599 | * @param name 600 | * @param onClick 601 | * @param accessKey The key to use for keyboard shortcuts 602 | */ 603 | registerMenuCommand(name: string, onClick: () => void, accessKey?: string): Promise; 604 | /** 605 | * Unregister a menu command that was previously registered by 606 | * `GM_registerMenuCommand` or `GM.registerMenuCommand` with the given menu command ID. 607 | */ 608 | unregisterMenuCommand(menuCommandId: number): Promise; 609 | 610 | // Requests 611 | 612 | /** 613 | * Makes an xmlHttpRequest 614 | * 615 | * @throws {Tampermonkey.ErrorResponse} 616 | */ 617 | xmlHttpRequest( 618 | // onload and the like still work 619 | details: Tampermonkey.Request, // tslint:disable-line:no-unnecessary-generics 620 | ): Promise>; 621 | 622 | // GM_download has two signatures, GM.download has one 623 | /** 624 | * Downloads a given URL to the local disk 625 | * 626 | * @throws {Tampermonkey.DownloadErrorResponse} 627 | */ 628 | download(details: Tampermonkey.DownloadRequest): Promise; 629 | 630 | // Tabs 631 | 632 | /** Saves the tab object to reopen it after a page unload */ 633 | saveTab(obj: any): Promise; 634 | 635 | /** Gets a object that is persistent as long as this tab is open */ 636 | getTab(): Promise; 637 | 638 | /** Gets all tab objects as a hash to communicate with other script instances */ 639 | getTabs(): Promise<{ [tabId: number]: any }>; 640 | 641 | // Utils 642 | info: Tampermonkey.ScriptInfo; 643 | 644 | /** Log a message to the console */ 645 | log(...message: any[]): Promise; 646 | 647 | /** 648 | * Opens a new tab with this url. 649 | * The options object can have the following properties: 650 | * - `active` decides whether the new tab should be focused, 651 | * - `insert` that inserts the new tab after the current one and 652 | * - `setParent` makes the browser re-focus the current tab on close. 653 | * 654 | * Otherwise the new tab is just appended. 655 | * If `options` is boolean (loadInBackground) it has the opposite meaning of 656 | * active and was added to achieve Greasemonkey 3.x compatibility. 657 | * 658 | * If neither active nor loadInBackground is given, then the tab will not be 659 | * focused. 660 | * @returns Object with the function `close`, the listener `onclose` and a flag 661 | * called `closed`. 662 | */ 663 | openInTab(url: string, options?: Tampermonkey.OpenTabOptions | boolean): Promise; 664 | 665 | /** 666 | * Shows a HTML5 Desktop notification and/or highlight the current tab. 667 | * @param details 668 | * @param ondone If specified used instead of `details.ondone` 669 | * @returns True if the notification was clicked 670 | */ 671 | notification(details: Tampermonkey.NotificationDetails, ondone?: Tampermonkey.NotificationOnDone): Promise; 672 | 673 | /** 674 | * Shows a HTML5 Desktop notification and/or highlight the current tab. 675 | * @param text Text of the notification 676 | * @param title Notification title. If not specified the script name is used 677 | * @param image 678 | * @param onclick Called in case the user clicks the notification 679 | * @returns True if the notification was clicked 680 | */ 681 | notification( 682 | text: string, 683 | title?: string, 684 | image?: string, 685 | onclick?: Tampermonkey.NotificationOnClick, 686 | ): Promise; 687 | 688 | /** 689 | * Copies data into the clipboard. 690 | * The parameter 'info' can be an object like 691 | * `{ type: 'text', mimetype: 'text/plain'}` or just a string expressing the 692 | * type ("text" or "html"). 693 | */ 694 | setClipboard( 695 | data: string, 696 | info?: Tampermonkey.ContentType, 697 | ): Promise; 698 | }>; -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | chokidar-cli: ^3.0.0 5 | concurrently: ^7.5.0 6 | express: ^4.18.2 7 | prettier: ^2.7.1 8 | 9 | devDependencies: 10 | chokidar-cli: 3.0.0 11 | concurrently: 7.6.0 12 | express: 4.18.2 13 | prettier: 2.8.3 14 | 15 | packages: 16 | 17 | /accepts/1.3.8: 18 | resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} 19 | engines: {node: '>= 0.6'} 20 | dependencies: 21 | mime-types: 2.1.35 22 | negotiator: 0.6.3 23 | dev: true 24 | 25 | /ansi-regex/4.1.1: 26 | resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} 27 | engines: {node: '>=6'} 28 | dev: true 29 | 30 | /ansi-regex/5.0.1: 31 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 32 | engines: {node: '>=8'} 33 | dev: true 34 | 35 | /ansi-styles/3.2.1: 36 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} 37 | engines: {node: '>=4'} 38 | dependencies: 39 | color-convert: 1.9.3 40 | dev: true 41 | 42 | /ansi-styles/4.3.0: 43 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 44 | engines: {node: '>=8'} 45 | dependencies: 46 | color-convert: 2.0.1 47 | dev: true 48 | 49 | /anymatch/3.1.3: 50 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 51 | engines: {node: '>= 8'} 52 | dependencies: 53 | normalize-path: 3.0.0 54 | picomatch: 2.3.1 55 | dev: true 56 | 57 | /array-flatten/1.1.1: 58 | resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} 59 | dev: true 60 | 61 | /binary-extensions/2.2.0: 62 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 63 | engines: {node: '>=8'} 64 | dev: true 65 | 66 | /body-parser/1.20.1: 67 | resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} 68 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 69 | dependencies: 70 | bytes: 3.1.2 71 | content-type: 1.0.5 72 | debug: 2.6.9 73 | depd: 2.0.0 74 | destroy: 1.2.0 75 | http-errors: 2.0.0 76 | iconv-lite: 0.4.24 77 | on-finished: 2.4.1 78 | qs: 6.11.0 79 | raw-body: 2.5.1 80 | type-is: 1.6.18 81 | unpipe: 1.0.0 82 | transitivePeerDependencies: 83 | - supports-color 84 | dev: true 85 | 86 | /braces/3.0.2: 87 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 88 | engines: {node: '>=8'} 89 | dependencies: 90 | fill-range: 7.0.1 91 | dev: true 92 | 93 | /bytes/3.1.2: 94 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} 95 | engines: {node: '>= 0.8'} 96 | dev: true 97 | 98 | /call-bind/1.0.2: 99 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} 100 | dependencies: 101 | function-bind: 1.1.1 102 | get-intrinsic: 1.2.0 103 | dev: true 104 | 105 | /camelcase/5.3.1: 106 | resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} 107 | engines: {node: '>=6'} 108 | dev: true 109 | 110 | /chalk/4.1.2: 111 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 112 | engines: {node: '>=10'} 113 | dependencies: 114 | ansi-styles: 4.3.0 115 | supports-color: 7.2.0 116 | dev: true 117 | 118 | /chokidar-cli/3.0.0: 119 | resolution: {integrity: sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==} 120 | engines: {node: '>= 8.10.0'} 121 | hasBin: true 122 | dependencies: 123 | chokidar: 3.5.3 124 | lodash.debounce: 4.0.8 125 | lodash.throttle: 4.1.1 126 | yargs: 13.3.2 127 | dev: true 128 | 129 | /chokidar/3.5.3: 130 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 131 | engines: {node: '>= 8.10.0'} 132 | dependencies: 133 | anymatch: 3.1.3 134 | braces: 3.0.2 135 | glob-parent: 5.1.2 136 | is-binary-path: 2.1.0 137 | is-glob: 4.0.3 138 | normalize-path: 3.0.0 139 | readdirp: 3.6.0 140 | optionalDependencies: 141 | fsevents: 2.3.2 142 | dev: true 143 | 144 | /cliui/5.0.0: 145 | resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} 146 | dependencies: 147 | string-width: 3.1.0 148 | strip-ansi: 5.2.0 149 | wrap-ansi: 5.1.0 150 | dev: true 151 | 152 | /cliui/8.0.1: 153 | resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} 154 | engines: {node: '>=12'} 155 | dependencies: 156 | string-width: 4.2.3 157 | strip-ansi: 6.0.1 158 | wrap-ansi: 7.0.0 159 | dev: true 160 | 161 | /color-convert/1.9.3: 162 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 163 | dependencies: 164 | color-name: 1.1.3 165 | dev: true 166 | 167 | /color-convert/2.0.1: 168 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 169 | engines: {node: '>=7.0.0'} 170 | dependencies: 171 | color-name: 1.1.4 172 | dev: true 173 | 174 | /color-name/1.1.3: 175 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 176 | dev: true 177 | 178 | /color-name/1.1.4: 179 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 180 | dev: true 181 | 182 | /concurrently/7.6.0: 183 | resolution: {integrity: sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==} 184 | engines: {node: ^12.20.0 || ^14.13.0 || >=16.0.0} 185 | hasBin: true 186 | dependencies: 187 | chalk: 4.1.2 188 | date-fns: 2.29.3 189 | lodash: 4.17.21 190 | rxjs: 7.8.0 191 | shell-quote: 1.7.4 192 | spawn-command: 0.0.2-1 193 | supports-color: 8.1.1 194 | tree-kill: 1.2.2 195 | yargs: 17.6.2 196 | dev: true 197 | 198 | /content-disposition/0.5.4: 199 | resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} 200 | engines: {node: '>= 0.6'} 201 | dependencies: 202 | safe-buffer: 5.2.1 203 | dev: true 204 | 205 | /content-type/1.0.5: 206 | resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} 207 | engines: {node: '>= 0.6'} 208 | dev: true 209 | 210 | /cookie-signature/1.0.6: 211 | resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} 212 | dev: true 213 | 214 | /cookie/0.5.0: 215 | resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} 216 | engines: {node: '>= 0.6'} 217 | dev: true 218 | 219 | /date-fns/2.29.3: 220 | resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==} 221 | engines: {node: '>=0.11'} 222 | dev: true 223 | 224 | /debug/2.6.9: 225 | resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} 226 | peerDependencies: 227 | supports-color: '*' 228 | peerDependenciesMeta: 229 | supports-color: 230 | optional: true 231 | dependencies: 232 | ms: 2.0.0 233 | dev: true 234 | 235 | /decamelize/1.2.0: 236 | resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} 237 | engines: {node: '>=0.10.0'} 238 | dev: true 239 | 240 | /depd/2.0.0: 241 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} 242 | engines: {node: '>= 0.8'} 243 | dev: true 244 | 245 | /destroy/1.2.0: 246 | resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} 247 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 248 | dev: true 249 | 250 | /ee-first/1.1.1: 251 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} 252 | dev: true 253 | 254 | /emoji-regex/7.0.3: 255 | resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} 256 | dev: true 257 | 258 | /emoji-regex/8.0.0: 259 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 260 | dev: true 261 | 262 | /encodeurl/1.0.2: 263 | resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} 264 | engines: {node: '>= 0.8'} 265 | dev: true 266 | 267 | /escalade/3.1.1: 268 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 269 | engines: {node: '>=6'} 270 | dev: true 271 | 272 | /escape-html/1.0.3: 273 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} 274 | dev: true 275 | 276 | /etag/1.8.1: 277 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} 278 | engines: {node: '>= 0.6'} 279 | dev: true 280 | 281 | /express/4.18.2: 282 | resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} 283 | engines: {node: '>= 0.10.0'} 284 | dependencies: 285 | accepts: 1.3.8 286 | array-flatten: 1.1.1 287 | body-parser: 1.20.1 288 | content-disposition: 0.5.4 289 | content-type: 1.0.5 290 | cookie: 0.5.0 291 | cookie-signature: 1.0.6 292 | debug: 2.6.9 293 | depd: 2.0.0 294 | encodeurl: 1.0.2 295 | escape-html: 1.0.3 296 | etag: 1.8.1 297 | finalhandler: 1.2.0 298 | fresh: 0.5.2 299 | http-errors: 2.0.0 300 | merge-descriptors: 1.0.1 301 | methods: 1.1.2 302 | on-finished: 2.4.1 303 | parseurl: 1.3.3 304 | path-to-regexp: 0.1.7 305 | proxy-addr: 2.0.7 306 | qs: 6.11.0 307 | range-parser: 1.2.1 308 | safe-buffer: 5.2.1 309 | send: 0.18.0 310 | serve-static: 1.15.0 311 | setprototypeof: 1.2.0 312 | statuses: 2.0.1 313 | type-is: 1.6.18 314 | utils-merge: 1.0.1 315 | vary: 1.1.2 316 | transitivePeerDependencies: 317 | - supports-color 318 | dev: true 319 | 320 | /fill-range/7.0.1: 321 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 322 | engines: {node: '>=8'} 323 | dependencies: 324 | to-regex-range: 5.0.1 325 | dev: true 326 | 327 | /finalhandler/1.2.0: 328 | resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} 329 | engines: {node: '>= 0.8'} 330 | dependencies: 331 | debug: 2.6.9 332 | encodeurl: 1.0.2 333 | escape-html: 1.0.3 334 | on-finished: 2.4.1 335 | parseurl: 1.3.3 336 | statuses: 2.0.1 337 | unpipe: 1.0.0 338 | transitivePeerDependencies: 339 | - supports-color 340 | dev: true 341 | 342 | /find-up/3.0.0: 343 | resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} 344 | engines: {node: '>=6'} 345 | dependencies: 346 | locate-path: 3.0.0 347 | dev: true 348 | 349 | /forwarded/0.2.0: 350 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} 351 | engines: {node: '>= 0.6'} 352 | dev: true 353 | 354 | /fresh/0.5.2: 355 | resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} 356 | engines: {node: '>= 0.6'} 357 | dev: true 358 | 359 | /fsevents/2.3.2: 360 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 361 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 362 | os: [darwin] 363 | requiresBuild: true 364 | dev: true 365 | optional: true 366 | 367 | /function-bind/1.1.1: 368 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 369 | dev: true 370 | 371 | /get-caller-file/2.0.5: 372 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 373 | engines: {node: 6.* || 8.* || >= 10.*} 374 | dev: true 375 | 376 | /get-intrinsic/1.2.0: 377 | resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} 378 | dependencies: 379 | function-bind: 1.1.1 380 | has: 1.0.3 381 | has-symbols: 1.0.3 382 | dev: true 383 | 384 | /glob-parent/5.1.2: 385 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 386 | engines: {node: '>= 6'} 387 | dependencies: 388 | is-glob: 4.0.3 389 | dev: true 390 | 391 | /has-flag/4.0.0: 392 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 393 | engines: {node: '>=8'} 394 | dev: true 395 | 396 | /has-symbols/1.0.3: 397 | resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} 398 | engines: {node: '>= 0.4'} 399 | dev: true 400 | 401 | /has/1.0.3: 402 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 403 | engines: {node: '>= 0.4.0'} 404 | dependencies: 405 | function-bind: 1.1.1 406 | dev: true 407 | 408 | /http-errors/2.0.0: 409 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} 410 | engines: {node: '>= 0.8'} 411 | dependencies: 412 | depd: 2.0.0 413 | inherits: 2.0.4 414 | setprototypeof: 1.2.0 415 | statuses: 2.0.1 416 | toidentifier: 1.0.1 417 | dev: true 418 | 419 | /iconv-lite/0.4.24: 420 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 421 | engines: {node: '>=0.10.0'} 422 | dependencies: 423 | safer-buffer: 2.1.2 424 | dev: true 425 | 426 | /inherits/2.0.4: 427 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 428 | dev: true 429 | 430 | /ipaddr.js/1.9.1: 431 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} 432 | engines: {node: '>= 0.10'} 433 | dev: true 434 | 435 | /is-binary-path/2.1.0: 436 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 437 | engines: {node: '>=8'} 438 | dependencies: 439 | binary-extensions: 2.2.0 440 | dev: true 441 | 442 | /is-extglob/2.1.1: 443 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 444 | engines: {node: '>=0.10.0'} 445 | dev: true 446 | 447 | /is-fullwidth-code-point/2.0.0: 448 | resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} 449 | engines: {node: '>=4'} 450 | dev: true 451 | 452 | /is-fullwidth-code-point/3.0.0: 453 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 454 | engines: {node: '>=8'} 455 | dev: true 456 | 457 | /is-glob/4.0.3: 458 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 459 | engines: {node: '>=0.10.0'} 460 | dependencies: 461 | is-extglob: 2.1.1 462 | dev: true 463 | 464 | /is-number/7.0.0: 465 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 466 | engines: {node: '>=0.12.0'} 467 | dev: true 468 | 469 | /locate-path/3.0.0: 470 | resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} 471 | engines: {node: '>=6'} 472 | dependencies: 473 | p-locate: 3.0.0 474 | path-exists: 3.0.0 475 | dev: true 476 | 477 | /lodash.debounce/4.0.8: 478 | resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} 479 | dev: true 480 | 481 | /lodash.throttle/4.1.1: 482 | resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} 483 | dev: true 484 | 485 | /lodash/4.17.21: 486 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 487 | dev: true 488 | 489 | /media-typer/0.3.0: 490 | resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} 491 | engines: {node: '>= 0.6'} 492 | dev: true 493 | 494 | /merge-descriptors/1.0.1: 495 | resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} 496 | dev: true 497 | 498 | /methods/1.1.2: 499 | resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} 500 | engines: {node: '>= 0.6'} 501 | dev: true 502 | 503 | /mime-db/1.52.0: 504 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 505 | engines: {node: '>= 0.6'} 506 | dev: true 507 | 508 | /mime-types/2.1.35: 509 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 510 | engines: {node: '>= 0.6'} 511 | dependencies: 512 | mime-db: 1.52.0 513 | dev: true 514 | 515 | /mime/1.6.0: 516 | resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} 517 | engines: {node: '>=4'} 518 | hasBin: true 519 | dev: true 520 | 521 | /ms/2.0.0: 522 | resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} 523 | dev: true 524 | 525 | /ms/2.1.3: 526 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 527 | dev: true 528 | 529 | /negotiator/0.6.3: 530 | resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} 531 | engines: {node: '>= 0.6'} 532 | dev: true 533 | 534 | /normalize-path/3.0.0: 535 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 536 | engines: {node: '>=0.10.0'} 537 | dev: true 538 | 539 | /object-inspect/1.12.3: 540 | resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} 541 | dev: true 542 | 543 | /on-finished/2.4.1: 544 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} 545 | engines: {node: '>= 0.8'} 546 | dependencies: 547 | ee-first: 1.1.1 548 | dev: true 549 | 550 | /p-limit/2.3.0: 551 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 552 | engines: {node: '>=6'} 553 | dependencies: 554 | p-try: 2.2.0 555 | dev: true 556 | 557 | /p-locate/3.0.0: 558 | resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} 559 | engines: {node: '>=6'} 560 | dependencies: 561 | p-limit: 2.3.0 562 | dev: true 563 | 564 | /p-try/2.2.0: 565 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 566 | engines: {node: '>=6'} 567 | dev: true 568 | 569 | /parseurl/1.3.3: 570 | resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} 571 | engines: {node: '>= 0.8'} 572 | dev: true 573 | 574 | /path-exists/3.0.0: 575 | resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} 576 | engines: {node: '>=4'} 577 | dev: true 578 | 579 | /path-to-regexp/0.1.7: 580 | resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} 581 | dev: true 582 | 583 | /picomatch/2.3.1: 584 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 585 | engines: {node: '>=8.6'} 586 | dev: true 587 | 588 | /prettier/2.8.3: 589 | resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==} 590 | engines: {node: '>=10.13.0'} 591 | hasBin: true 592 | dev: true 593 | 594 | /proxy-addr/2.0.7: 595 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} 596 | engines: {node: '>= 0.10'} 597 | dependencies: 598 | forwarded: 0.2.0 599 | ipaddr.js: 1.9.1 600 | dev: true 601 | 602 | /qs/6.11.0: 603 | resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} 604 | engines: {node: '>=0.6'} 605 | dependencies: 606 | side-channel: 1.0.4 607 | dev: true 608 | 609 | /range-parser/1.2.1: 610 | resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} 611 | engines: {node: '>= 0.6'} 612 | dev: true 613 | 614 | /raw-body/2.5.1: 615 | resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} 616 | engines: {node: '>= 0.8'} 617 | dependencies: 618 | bytes: 3.1.2 619 | http-errors: 2.0.0 620 | iconv-lite: 0.4.24 621 | unpipe: 1.0.0 622 | dev: true 623 | 624 | /readdirp/3.6.0: 625 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 626 | engines: {node: '>=8.10.0'} 627 | dependencies: 628 | picomatch: 2.3.1 629 | dev: true 630 | 631 | /require-directory/2.1.1: 632 | resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 633 | engines: {node: '>=0.10.0'} 634 | dev: true 635 | 636 | /require-main-filename/2.0.0: 637 | resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} 638 | dev: true 639 | 640 | /rxjs/7.8.0: 641 | resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} 642 | dependencies: 643 | tslib: 2.5.0 644 | dev: true 645 | 646 | /safe-buffer/5.2.1: 647 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 648 | dev: true 649 | 650 | /safer-buffer/2.1.2: 651 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 652 | dev: true 653 | 654 | /send/0.18.0: 655 | resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} 656 | engines: {node: '>= 0.8.0'} 657 | dependencies: 658 | debug: 2.6.9 659 | depd: 2.0.0 660 | destroy: 1.2.0 661 | encodeurl: 1.0.2 662 | escape-html: 1.0.3 663 | etag: 1.8.1 664 | fresh: 0.5.2 665 | http-errors: 2.0.0 666 | mime: 1.6.0 667 | ms: 2.1.3 668 | on-finished: 2.4.1 669 | range-parser: 1.2.1 670 | statuses: 2.0.1 671 | transitivePeerDependencies: 672 | - supports-color 673 | dev: true 674 | 675 | /serve-static/1.15.0: 676 | resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} 677 | engines: {node: '>= 0.8.0'} 678 | dependencies: 679 | encodeurl: 1.0.2 680 | escape-html: 1.0.3 681 | parseurl: 1.3.3 682 | send: 0.18.0 683 | transitivePeerDependencies: 684 | - supports-color 685 | dev: true 686 | 687 | /set-blocking/2.0.0: 688 | resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} 689 | dev: true 690 | 691 | /setprototypeof/1.2.0: 692 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} 693 | dev: true 694 | 695 | /shell-quote/1.7.4: 696 | resolution: {integrity: sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==} 697 | dev: true 698 | 699 | /side-channel/1.0.4: 700 | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} 701 | dependencies: 702 | call-bind: 1.0.2 703 | get-intrinsic: 1.2.0 704 | object-inspect: 1.12.3 705 | dev: true 706 | 707 | /spawn-command/0.0.2-1: 708 | resolution: {integrity: sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==} 709 | dev: true 710 | 711 | /statuses/2.0.1: 712 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} 713 | engines: {node: '>= 0.8'} 714 | dev: true 715 | 716 | /string-width/3.1.0: 717 | resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} 718 | engines: {node: '>=6'} 719 | dependencies: 720 | emoji-regex: 7.0.3 721 | is-fullwidth-code-point: 2.0.0 722 | strip-ansi: 5.2.0 723 | dev: true 724 | 725 | /string-width/4.2.3: 726 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 727 | engines: {node: '>=8'} 728 | dependencies: 729 | emoji-regex: 8.0.0 730 | is-fullwidth-code-point: 3.0.0 731 | strip-ansi: 6.0.1 732 | dev: true 733 | 734 | /strip-ansi/5.2.0: 735 | resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} 736 | engines: {node: '>=6'} 737 | dependencies: 738 | ansi-regex: 4.1.1 739 | dev: true 740 | 741 | /strip-ansi/6.0.1: 742 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 743 | engines: {node: '>=8'} 744 | dependencies: 745 | ansi-regex: 5.0.1 746 | dev: true 747 | 748 | /supports-color/7.2.0: 749 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 750 | engines: {node: '>=8'} 751 | dependencies: 752 | has-flag: 4.0.0 753 | dev: true 754 | 755 | /supports-color/8.1.1: 756 | resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} 757 | engines: {node: '>=10'} 758 | dependencies: 759 | has-flag: 4.0.0 760 | dev: true 761 | 762 | /to-regex-range/5.0.1: 763 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 764 | engines: {node: '>=8.0'} 765 | dependencies: 766 | is-number: 7.0.0 767 | dev: true 768 | 769 | /toidentifier/1.0.1: 770 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} 771 | engines: {node: '>=0.6'} 772 | dev: true 773 | 774 | /tree-kill/1.2.2: 775 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 776 | hasBin: true 777 | dev: true 778 | 779 | /tslib/2.5.0: 780 | resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} 781 | dev: true 782 | 783 | /type-is/1.6.18: 784 | resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} 785 | engines: {node: '>= 0.6'} 786 | dependencies: 787 | media-typer: 0.3.0 788 | mime-types: 2.1.35 789 | dev: true 790 | 791 | /unpipe/1.0.0: 792 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} 793 | engines: {node: '>= 0.8'} 794 | dev: true 795 | 796 | /utils-merge/1.0.1: 797 | resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} 798 | engines: {node: '>= 0.4.0'} 799 | dev: true 800 | 801 | /vary/1.1.2: 802 | resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} 803 | engines: {node: '>= 0.8'} 804 | dev: true 805 | 806 | /which-module/2.0.0: 807 | resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} 808 | dev: true 809 | 810 | /wrap-ansi/5.1.0: 811 | resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} 812 | engines: {node: '>=6'} 813 | dependencies: 814 | ansi-styles: 3.2.1 815 | string-width: 3.1.0 816 | strip-ansi: 5.2.0 817 | dev: true 818 | 819 | /wrap-ansi/7.0.0: 820 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 821 | engines: {node: '>=10'} 822 | dependencies: 823 | ansi-styles: 4.3.0 824 | string-width: 4.2.3 825 | strip-ansi: 6.0.1 826 | dev: true 827 | 828 | /y18n/4.0.3: 829 | resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} 830 | dev: true 831 | 832 | /y18n/5.0.8: 833 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 834 | engines: {node: '>=10'} 835 | dev: true 836 | 837 | /yargs-parser/13.1.2: 838 | resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} 839 | dependencies: 840 | camelcase: 5.3.1 841 | decamelize: 1.2.0 842 | dev: true 843 | 844 | /yargs-parser/21.1.1: 845 | resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} 846 | engines: {node: '>=12'} 847 | dev: true 848 | 849 | /yargs/13.3.2: 850 | resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} 851 | dependencies: 852 | cliui: 5.0.0 853 | find-up: 3.0.0 854 | get-caller-file: 2.0.5 855 | require-directory: 2.1.1 856 | require-main-filename: 2.0.0 857 | set-blocking: 2.0.0 858 | string-width: 3.1.0 859 | which-module: 2.0.0 860 | y18n: 4.0.3 861 | yargs-parser: 13.1.2 862 | dev: true 863 | 864 | /yargs/17.6.2: 865 | resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} 866 | engines: {node: '>=12'} 867 | dependencies: 868 | cliui: 8.0.1 869 | escalade: 3.1.1 870 | get-caller-file: 2.0.5 871 | require-directory: 2.1.1 872 | string-width: 4.2.3 873 | y18n: 5.0.8 874 | yargs-parser: 21.1.1 875 | dev: true 876 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | accepts@~1.3.8: 6 | version "1.3.8" 7 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 8 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 9 | dependencies: 10 | mime-types "~2.1.34" 11 | negotiator "0.6.3" 12 | 13 | ansi-regex@^4.1.0: 14 | version "4.1.1" 15 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" 16 | integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== 17 | 18 | ansi-regex@^5.0.1: 19 | version "5.0.1" 20 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 21 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 22 | 23 | ansi-styles@^3.2.0: 24 | version "3.2.1" 25 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 26 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 27 | dependencies: 28 | color-convert "^1.9.0" 29 | 30 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 31 | version "4.3.0" 32 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 33 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 34 | dependencies: 35 | color-convert "^2.0.1" 36 | 37 | anymatch@~3.1.2: 38 | version "3.1.2" 39 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 40 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 41 | dependencies: 42 | normalize-path "^3.0.0" 43 | picomatch "^2.0.4" 44 | 45 | array-flatten@1.1.1: 46 | version "1.1.1" 47 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 48 | integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== 49 | 50 | binary-extensions@^2.0.0: 51 | version "2.2.0" 52 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 53 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 54 | 55 | body-parser@1.20.1: 56 | version "1.20.1" 57 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" 58 | integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== 59 | dependencies: 60 | bytes "3.1.2" 61 | content-type "~1.0.4" 62 | debug "2.6.9" 63 | depd "2.0.0" 64 | destroy "1.2.0" 65 | http-errors "2.0.0" 66 | iconv-lite "0.4.24" 67 | on-finished "2.4.1" 68 | qs "6.11.0" 69 | raw-body "2.5.1" 70 | type-is "~1.6.18" 71 | unpipe "1.0.0" 72 | 73 | braces@~3.0.2: 74 | version "3.0.2" 75 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 76 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 77 | dependencies: 78 | fill-range "^7.0.1" 79 | 80 | bytes@3.1.2: 81 | version "3.1.2" 82 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 83 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 84 | 85 | call-bind@^1.0.0: 86 | version "1.0.2" 87 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 88 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 89 | dependencies: 90 | function-bind "^1.1.1" 91 | get-intrinsic "^1.0.2" 92 | 93 | camelcase@^5.0.0: 94 | version "5.3.1" 95 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 96 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 97 | 98 | chalk@^4.1.0: 99 | version "4.1.2" 100 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 101 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 102 | dependencies: 103 | ansi-styles "^4.1.0" 104 | supports-color "^7.1.0" 105 | 106 | chokidar-cli@^3.0.0: 107 | version "3.0.0" 108 | resolved "https://registry.yarnpkg.com/chokidar-cli/-/chokidar-cli-3.0.0.tgz#29283666063b9e167559d30f247ff8fc48794eb7" 109 | integrity sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ== 110 | dependencies: 111 | chokidar "^3.5.2" 112 | lodash.debounce "^4.0.8" 113 | lodash.throttle "^4.1.1" 114 | yargs "^13.3.0" 115 | 116 | chokidar@^3.5.2: 117 | version "3.5.3" 118 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 119 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 120 | dependencies: 121 | anymatch "~3.1.2" 122 | braces "~3.0.2" 123 | glob-parent "~5.1.2" 124 | is-binary-path "~2.1.0" 125 | is-glob "~4.0.1" 126 | normalize-path "~3.0.0" 127 | readdirp "~3.6.0" 128 | optionalDependencies: 129 | fsevents "~2.3.2" 130 | 131 | cliui@^5.0.0: 132 | version "5.0.0" 133 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" 134 | integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== 135 | dependencies: 136 | string-width "^3.1.0" 137 | strip-ansi "^5.2.0" 138 | wrap-ansi "^5.1.0" 139 | 140 | cliui@^8.0.1: 141 | version "8.0.1" 142 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" 143 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 144 | dependencies: 145 | string-width "^4.2.0" 146 | strip-ansi "^6.0.1" 147 | wrap-ansi "^7.0.0" 148 | 149 | color-convert@^1.9.0: 150 | version "1.9.3" 151 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 152 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 153 | dependencies: 154 | color-name "1.1.3" 155 | 156 | color-convert@^2.0.1: 157 | version "2.0.1" 158 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 159 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 160 | dependencies: 161 | color-name "~1.1.4" 162 | 163 | color-name@1.1.3: 164 | version "1.1.3" 165 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 166 | integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== 167 | 168 | color-name@~1.1.4: 169 | version "1.1.4" 170 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 171 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 172 | 173 | concurrently@^7.5.0: 174 | version "7.5.0" 175 | resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.5.0.tgz#4dd432d4634a8251f27ab000c4974e78e3906bd3" 176 | integrity sha512-5E3mwiS+i2JYBzr5BpXkFxOnleZTMsG+WnE/dCG4/P+oiVXrbmrBwJ2ozn4SxwB2EZDrKR568X+puVohxz3/Mg== 177 | dependencies: 178 | chalk "^4.1.0" 179 | date-fns "^2.29.1" 180 | lodash "^4.17.21" 181 | rxjs "^7.0.0" 182 | shell-quote "^1.7.3" 183 | spawn-command "^0.0.2-1" 184 | supports-color "^8.1.0" 185 | tree-kill "^1.2.2" 186 | yargs "^17.3.1" 187 | 188 | content-disposition@0.5.4: 189 | version "0.5.4" 190 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 191 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 192 | dependencies: 193 | safe-buffer "5.2.1" 194 | 195 | content-type@~1.0.4: 196 | version "1.0.4" 197 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 198 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 199 | 200 | cookie-signature@1.0.6: 201 | version "1.0.6" 202 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 203 | integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== 204 | 205 | cookie@0.5.0: 206 | version "0.5.0" 207 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" 208 | integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 209 | 210 | date-fns@^2.29.1: 211 | version "2.29.3" 212 | resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" 213 | integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== 214 | 215 | debug@2.6.9: 216 | version "2.6.9" 217 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 218 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 219 | dependencies: 220 | ms "2.0.0" 221 | 222 | decamelize@^1.2.0: 223 | version "1.2.0" 224 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 225 | integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== 226 | 227 | depd@2.0.0: 228 | version "2.0.0" 229 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 230 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 231 | 232 | destroy@1.2.0: 233 | version "1.2.0" 234 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 235 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 236 | 237 | ee-first@1.1.1: 238 | version "1.1.1" 239 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 240 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 241 | 242 | emoji-regex@^7.0.1: 243 | version "7.0.3" 244 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 245 | integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== 246 | 247 | emoji-regex@^8.0.0: 248 | version "8.0.0" 249 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 250 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 251 | 252 | encodeurl@~1.0.2: 253 | version "1.0.2" 254 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 255 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 256 | 257 | escalade@^3.1.1: 258 | version "3.1.1" 259 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 260 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 261 | 262 | escape-html@~1.0.3: 263 | version "1.0.3" 264 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 265 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 266 | 267 | etag@~1.8.1: 268 | version "1.8.1" 269 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 270 | integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 271 | 272 | express@^4.18.2: 273 | version "4.18.2" 274 | resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" 275 | integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== 276 | dependencies: 277 | accepts "~1.3.8" 278 | array-flatten "1.1.1" 279 | body-parser "1.20.1" 280 | content-disposition "0.5.4" 281 | content-type "~1.0.4" 282 | cookie "0.5.0" 283 | cookie-signature "1.0.6" 284 | debug "2.6.9" 285 | depd "2.0.0" 286 | encodeurl "~1.0.2" 287 | escape-html "~1.0.3" 288 | etag "~1.8.1" 289 | finalhandler "1.2.0" 290 | fresh "0.5.2" 291 | http-errors "2.0.0" 292 | merge-descriptors "1.0.1" 293 | methods "~1.1.2" 294 | on-finished "2.4.1" 295 | parseurl "~1.3.3" 296 | path-to-regexp "0.1.7" 297 | proxy-addr "~2.0.7" 298 | qs "6.11.0" 299 | range-parser "~1.2.1" 300 | safe-buffer "5.2.1" 301 | send "0.18.0" 302 | serve-static "1.15.0" 303 | setprototypeof "1.2.0" 304 | statuses "2.0.1" 305 | type-is "~1.6.18" 306 | utils-merge "1.0.1" 307 | vary "~1.1.2" 308 | 309 | fill-range@^7.0.1: 310 | version "7.0.1" 311 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 312 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 313 | dependencies: 314 | to-regex-range "^5.0.1" 315 | 316 | finalhandler@1.2.0: 317 | version "1.2.0" 318 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" 319 | integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 320 | dependencies: 321 | debug "2.6.9" 322 | encodeurl "~1.0.2" 323 | escape-html "~1.0.3" 324 | on-finished "2.4.1" 325 | parseurl "~1.3.3" 326 | statuses "2.0.1" 327 | unpipe "~1.0.0" 328 | 329 | find-up@^3.0.0: 330 | version "3.0.0" 331 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 332 | integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== 333 | dependencies: 334 | locate-path "^3.0.0" 335 | 336 | forwarded@0.2.0: 337 | version "0.2.0" 338 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 339 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 340 | 341 | fresh@0.5.2: 342 | version "0.5.2" 343 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 344 | integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 345 | 346 | fsevents@~2.3.2: 347 | version "2.3.2" 348 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 349 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 350 | 351 | function-bind@^1.1.1: 352 | version "1.1.1" 353 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 354 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 355 | 356 | get-caller-file@^2.0.1, get-caller-file@^2.0.5: 357 | version "2.0.5" 358 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 359 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 360 | 361 | get-intrinsic@^1.0.2: 362 | version "1.1.3" 363 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" 364 | integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== 365 | dependencies: 366 | function-bind "^1.1.1" 367 | has "^1.0.3" 368 | has-symbols "^1.0.3" 369 | 370 | glob-parent@~5.1.2: 371 | version "5.1.2" 372 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 373 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 374 | dependencies: 375 | is-glob "^4.0.1" 376 | 377 | has-flag@^4.0.0: 378 | version "4.0.0" 379 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 380 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 381 | 382 | has-symbols@^1.0.3: 383 | version "1.0.3" 384 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 385 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 386 | 387 | has@^1.0.3: 388 | version "1.0.3" 389 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 390 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 391 | dependencies: 392 | function-bind "^1.1.1" 393 | 394 | http-errors@2.0.0: 395 | version "2.0.0" 396 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 397 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 398 | dependencies: 399 | depd "2.0.0" 400 | inherits "2.0.4" 401 | setprototypeof "1.2.0" 402 | statuses "2.0.1" 403 | toidentifier "1.0.1" 404 | 405 | iconv-lite@0.4.24: 406 | version "0.4.24" 407 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 408 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 409 | dependencies: 410 | safer-buffer ">= 2.1.2 < 3" 411 | 412 | inherits@2.0.4: 413 | version "2.0.4" 414 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 415 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 416 | 417 | ipaddr.js@1.9.1: 418 | version "1.9.1" 419 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 420 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 421 | 422 | is-binary-path@~2.1.0: 423 | version "2.1.0" 424 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 425 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 426 | dependencies: 427 | binary-extensions "^2.0.0" 428 | 429 | is-extglob@^2.1.1: 430 | version "2.1.1" 431 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 432 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 433 | 434 | is-fullwidth-code-point@^2.0.0: 435 | version "2.0.0" 436 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 437 | integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== 438 | 439 | is-fullwidth-code-point@^3.0.0: 440 | version "3.0.0" 441 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 442 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 443 | 444 | is-glob@^4.0.1, is-glob@~4.0.1: 445 | version "4.0.3" 446 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 447 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 448 | dependencies: 449 | is-extglob "^2.1.1" 450 | 451 | is-number@^7.0.0: 452 | version "7.0.0" 453 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 454 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 455 | 456 | locate-path@^3.0.0: 457 | version "3.0.0" 458 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 459 | integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== 460 | dependencies: 461 | p-locate "^3.0.0" 462 | path-exists "^3.0.0" 463 | 464 | lodash.debounce@^4.0.8: 465 | version "4.0.8" 466 | resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" 467 | integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== 468 | 469 | lodash.throttle@^4.1.1: 470 | version "4.1.1" 471 | resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" 472 | integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== 473 | 474 | lodash@^4.17.21: 475 | version "4.17.21" 476 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 477 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 478 | 479 | media-typer@0.3.0: 480 | version "0.3.0" 481 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 482 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 483 | 484 | merge-descriptors@1.0.1: 485 | version "1.0.1" 486 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 487 | integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== 488 | 489 | methods@~1.1.2: 490 | version "1.1.2" 491 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 492 | integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== 493 | 494 | mime-db@1.52.0: 495 | version "1.52.0" 496 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 497 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 498 | 499 | mime-types@~2.1.24, mime-types@~2.1.34: 500 | version "2.1.35" 501 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 502 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 503 | dependencies: 504 | mime-db "1.52.0" 505 | 506 | mime@1.6.0: 507 | version "1.6.0" 508 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 509 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 510 | 511 | ms@2.0.0: 512 | version "2.0.0" 513 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 514 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 515 | 516 | ms@2.1.3: 517 | version "2.1.3" 518 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 519 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 520 | 521 | negotiator@0.6.3: 522 | version "0.6.3" 523 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 524 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 525 | 526 | normalize-path@^3.0.0, normalize-path@~3.0.0: 527 | version "3.0.0" 528 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 529 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 530 | 531 | object-inspect@^1.9.0: 532 | version "1.12.2" 533 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" 534 | integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== 535 | 536 | on-finished@2.4.1: 537 | version "2.4.1" 538 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 539 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 540 | dependencies: 541 | ee-first "1.1.1" 542 | 543 | p-limit@^2.0.0: 544 | version "2.3.0" 545 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 546 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 547 | dependencies: 548 | p-try "^2.0.0" 549 | 550 | p-locate@^3.0.0: 551 | version "3.0.0" 552 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 553 | integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== 554 | dependencies: 555 | p-limit "^2.0.0" 556 | 557 | p-try@^2.0.0: 558 | version "2.2.0" 559 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 560 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 561 | 562 | parseurl@~1.3.3: 563 | version "1.3.3" 564 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 565 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 566 | 567 | path-exists@^3.0.0: 568 | version "3.0.0" 569 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 570 | integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== 571 | 572 | path-to-regexp@0.1.7: 573 | version "0.1.7" 574 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 575 | integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== 576 | 577 | picomatch@^2.0.4, picomatch@^2.2.1: 578 | version "2.3.1" 579 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 580 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 581 | 582 | prettier@^2.7.1: 583 | version "2.7.1" 584 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" 585 | integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== 586 | 587 | proxy-addr@~2.0.7: 588 | version "2.0.7" 589 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 590 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 591 | dependencies: 592 | forwarded "0.2.0" 593 | ipaddr.js "1.9.1" 594 | 595 | qs@6.11.0: 596 | version "6.11.0" 597 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 598 | integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 599 | dependencies: 600 | side-channel "^1.0.4" 601 | 602 | range-parser@~1.2.1: 603 | version "1.2.1" 604 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 605 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 606 | 607 | raw-body@2.5.1: 608 | version "2.5.1" 609 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 610 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 611 | dependencies: 612 | bytes "3.1.2" 613 | http-errors "2.0.0" 614 | iconv-lite "0.4.24" 615 | unpipe "1.0.0" 616 | 617 | readdirp@~3.6.0: 618 | version "3.6.0" 619 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 620 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 621 | dependencies: 622 | picomatch "^2.2.1" 623 | 624 | require-directory@^2.1.1: 625 | version "2.1.1" 626 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 627 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 628 | 629 | require-main-filename@^2.0.0: 630 | version "2.0.0" 631 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" 632 | integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== 633 | 634 | rxjs@^7.0.0: 635 | version "7.5.7" 636 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" 637 | integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== 638 | dependencies: 639 | tslib "^2.1.0" 640 | 641 | safe-buffer@5.2.1: 642 | version "5.2.1" 643 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 644 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 645 | 646 | "safer-buffer@>= 2.1.2 < 3": 647 | version "2.1.2" 648 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 649 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 650 | 651 | send@0.18.0: 652 | version "0.18.0" 653 | resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" 654 | integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 655 | dependencies: 656 | debug "2.6.9" 657 | depd "2.0.0" 658 | destroy "1.2.0" 659 | encodeurl "~1.0.2" 660 | escape-html "~1.0.3" 661 | etag "~1.8.1" 662 | fresh "0.5.2" 663 | http-errors "2.0.0" 664 | mime "1.6.0" 665 | ms "2.1.3" 666 | on-finished "2.4.1" 667 | range-parser "~1.2.1" 668 | statuses "2.0.1" 669 | 670 | serve-static@1.15.0: 671 | version "1.15.0" 672 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" 673 | integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 674 | dependencies: 675 | encodeurl "~1.0.2" 676 | escape-html "~1.0.3" 677 | parseurl "~1.3.3" 678 | send "0.18.0" 679 | 680 | set-blocking@^2.0.0: 681 | version "2.0.0" 682 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 683 | integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== 684 | 685 | setprototypeof@1.2.0: 686 | version "1.2.0" 687 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 688 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 689 | 690 | shell-quote@^1.7.3: 691 | version "1.7.4" 692 | resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" 693 | integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== 694 | 695 | side-channel@^1.0.4: 696 | version "1.0.4" 697 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 698 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 699 | dependencies: 700 | call-bind "^1.0.0" 701 | get-intrinsic "^1.0.2" 702 | object-inspect "^1.9.0" 703 | 704 | spawn-command@^0.0.2-1: 705 | version "0.0.2-1" 706 | resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" 707 | integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg== 708 | 709 | statuses@2.0.1: 710 | version "2.0.1" 711 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 712 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 713 | 714 | string-width@^3.0.0, string-width@^3.1.0: 715 | version "3.1.0" 716 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 717 | integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== 718 | dependencies: 719 | emoji-regex "^7.0.1" 720 | is-fullwidth-code-point "^2.0.0" 721 | strip-ansi "^5.1.0" 722 | 723 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 724 | version "4.2.3" 725 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 726 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 727 | dependencies: 728 | emoji-regex "^8.0.0" 729 | is-fullwidth-code-point "^3.0.0" 730 | strip-ansi "^6.0.1" 731 | 732 | strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: 733 | version "5.2.0" 734 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 735 | integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== 736 | dependencies: 737 | ansi-regex "^4.1.0" 738 | 739 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 740 | version "6.0.1" 741 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 742 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 743 | dependencies: 744 | ansi-regex "^5.0.1" 745 | 746 | supports-color@^7.1.0: 747 | version "7.2.0" 748 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 749 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 750 | dependencies: 751 | has-flag "^4.0.0" 752 | 753 | supports-color@^8.1.0: 754 | version "8.1.1" 755 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 756 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 757 | dependencies: 758 | has-flag "^4.0.0" 759 | 760 | to-regex-range@^5.0.1: 761 | version "5.0.1" 762 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 763 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 764 | dependencies: 765 | is-number "^7.0.0" 766 | 767 | toidentifier@1.0.1: 768 | version "1.0.1" 769 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 770 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 771 | 772 | tree-kill@^1.2.2: 773 | version "1.2.2" 774 | resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" 775 | integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== 776 | 777 | tslib@^2.1.0: 778 | version "2.4.1" 779 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" 780 | integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== 781 | 782 | type-is@~1.6.18: 783 | version "1.6.18" 784 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 785 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 786 | dependencies: 787 | media-typer "0.3.0" 788 | mime-types "~2.1.24" 789 | 790 | unpipe@1.0.0, unpipe@~1.0.0: 791 | version "1.0.0" 792 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 793 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 794 | 795 | utils-merge@1.0.1: 796 | version "1.0.1" 797 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 798 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 799 | 800 | vary@~1.1.2: 801 | version "1.1.2" 802 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 803 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 804 | 805 | which-module@^2.0.0: 806 | version "2.0.0" 807 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 808 | integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== 809 | 810 | wrap-ansi@^5.1.0: 811 | version "5.1.0" 812 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" 813 | integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== 814 | dependencies: 815 | ansi-styles "^3.2.0" 816 | string-width "^3.0.0" 817 | strip-ansi "^5.0.0" 818 | 819 | wrap-ansi@^7.0.0: 820 | version "7.0.0" 821 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 822 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 823 | dependencies: 824 | ansi-styles "^4.0.0" 825 | string-width "^4.1.0" 826 | strip-ansi "^6.0.0" 827 | 828 | y18n@^4.0.0: 829 | version "4.0.3" 830 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" 831 | integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== 832 | 833 | y18n@^5.0.5: 834 | version "5.0.8" 835 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 836 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 837 | 838 | yargs-parser@^13.1.2: 839 | version "13.1.2" 840 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" 841 | integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== 842 | dependencies: 843 | camelcase "^5.0.0" 844 | decamelize "^1.2.0" 845 | 846 | yargs-parser@^21.0.0: 847 | version "21.1.1" 848 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" 849 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 850 | 851 | yargs@^13.3.0: 852 | version "13.3.2" 853 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" 854 | integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== 855 | dependencies: 856 | cliui "^5.0.0" 857 | find-up "^3.0.0" 858 | get-caller-file "^2.0.1" 859 | require-directory "^2.1.1" 860 | require-main-filename "^2.0.0" 861 | set-blocking "^2.0.0" 862 | string-width "^3.0.0" 863 | which-module "^2.0.0" 864 | y18n "^4.0.0" 865 | yargs-parser "^13.1.2" 866 | 867 | yargs@^17.3.1: 868 | version "17.6.1" 869 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.1.tgz#712508771045019cda059bc1ba3ae091aaa1402e" 870 | integrity sha512-leBuCGrL4dAd6ispNOGsJlhd0uZ6Qehkbu/B9KCR+Pxa/NVdNwi+i31lo0buCm6XxhJQFshXCD0/evfV4xfoUg== 871 | dependencies: 872 | cliui "^8.0.1" 873 | escalade "^3.1.1" 874 | get-caller-file "^2.0.5" 875 | require-directory "^2.1.1" 876 | string-width "^4.2.3" 877 | y18n "^5.0.5" 878 | yargs-parser "^21.0.0" 879 | --------------------------------------------------------------------------------