From 5681fe85ba3b79a2e5b93bec35eddf92f19269db Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Wed, 8 Dec 2021 11:27:58 +0100 Subject: [PATCH 01/15] fix(locales): correct Japanese language code mapping --- src/server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server.js b/src/server.js index d1ca148..a45414b 100644 --- a/src/server.js +++ b/src/server.js @@ -45,7 +45,7 @@ app.use(expressLocale({ es: 'es-ES', fr: 'fr-FR', 'fr-CA': 'fr-FR', 'fr-CH': 'fr-FR', it: 'it-IT', 'it-CH': 'it-IT', - jp: 'ja-JP', + ja: 'ja-JP', ko: 'ko-KR', pt: 'pt-BR', ro: 'ro-RO', @@ -60,7 +60,7 @@ app.use(expressLocale({ 'es', 'es-ES', 'fr', 'fr-FR', 'fr-CA', 'fr-CH', 'it', 'it-IT', 'it-CH', - 'jp', 'ja-JP', + 'ja', 'ja-JP', 'ko', 'ko-KR', 'pt', 'pt-BR', 'ro', 'ro-RO', From 13e63f1a59b6b711e4061eef575cc62da8b14245 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Wed, 8 Dec 2021 18:41:29 +0100 Subject: [PATCH 02/15] feat(docs): add base documentation page layout --- locales/US_en.json | 1 + public/assets/css/documentation.css | 162 +++++++++++++++++ public/assets/css/highlightjs.css | 228 ++++++++++++++---------- public/assets/css/main.css | 1 + public/assets/images/arrow-right.svg | 1 + src/routers/docs.js | 92 ++++++++++ src/server.js | 2 + views/docs.handlebars | 136 ++++++++++++++ views/layouts/blog-opengraph.handlebars | 2 +- views/partials/docs-sidebar.handlebars | 40 +++++ views/partials/header.handlebars | 1 + 11 files changed, 574 insertions(+), 92 deletions(-) create mode 100644 public/assets/css/documentation.css create mode 100644 public/assets/images/arrow-right.svg create mode 100644 src/routers/docs.js create mode 100644 views/docs.handlebars create mode 100644 views/partials/docs-sidebar.handlebars diff --git a/locales/US_en.json b/locales/US_en.json index 3b5df33..8a3583b 100644 --- a/locales/US_en.json +++ b/locales/US_en.json @@ -2,6 +2,7 @@ "nav": { "about": "About", "faq": "FAQ", + "docs": "Docs", "credits": "Credits", "progress": "Progress", "blog": "Blog" diff --git a/public/assets/css/documentation.css b/public/assets/css/documentation.css new file mode 100644 index 0000000..b4d56d4 --- /dev/null +++ b/public/assets/css/documentation.css @@ -0,0 +1,162 @@ +html, body { + background: #131730; +} +a.logo-link { + margin:auto; + margin-left: 36px; + height: 40px; +} +header { + width: calc(100% - 72px); + background: #131730; + padding: 12px 36px; + margin: 0; +} +header a.logo-link { + display: none; +} +header nav a:first-child { + margin-left: -24px; +} + +.docs-wrapper { + display: grid; + grid-template-columns: repeat(2, fit-content(100%)); + grid-template-rows: repeat(2, fit-content(100%)); + min-height: 100%; +} + +.docs-wrapper .sidebar { + display: flex; + flex-flow: column; + align-items: center; + width: clamp(270px, 30vw, 500px); + background: #161931; + max-height: calc(100vh - 69px); + overflow-y: scroll; +} +.docs-wrapper .sidebar .section { + display: flex; + flex-flow: column; + width: 200px; + margin-left: 30px; + margin-bottom: 72px; +} +.docs-wrapper .sidebar .section:first-child { + margin-top: 72px; +} +.docs-wrapper .sidebar .section h5 { + margin: 0; + font-weight: normal; + text-transform: uppercase; + color: var(--text-secondary-2); + margin-bottom: 12px; +} +.docs-wrapper .sidebar .section a { + position: relative; + text-decoration: none; + color: var(--text-secondary); + width: fit-content; + margin-bottom: 12px; +} +.docs-wrapper .sidebar .section a.active, +.docs-wrapper .sidebar .section a:hover { + color: var(--text); +} +.docs-wrapper .sidebar .section a.active::before { + /* This filter thing is jank, if anyone knows a better way to do this please fix */ + filter: invert(51%) sepia(12%) saturate(2930%) hue-rotate(218deg) + brightness(99%) contrast(92%); + position: absolute; + left: -30px; + content: url(../images/arrow-right.svg); +} + +.docs-wrapper .content { + width: calc(100vw - clamp(270px, 30vw, 500px) - (72px * 2)); + background: var(--background); + padding: 72px; + max-height: calc(100vh - 69px - (72px * 2)); + overflow-y: scroll; +} +.docs-wrapper .content-inner { + max-width: 900px; +} +.docs-wrapper .content p { + color: var(--text-secondary); +} +.docs-wrapper .content h1:first-child { + margin-top: 0; +} +.docs-wrapper .content .quick-links-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-gap: 24px; + margin-bottom: 60px; +} +.docs-wrapper .quick-links-grid a { + text-decoration: none; + background: #252a51; + border-radius: 6px; + color: var(--text-secondary); + display: flex; + align-items: center; + padding: 20px; +} +.docs-wrapper .quick-links-grid svg:first-child { + height: 36px; + margin-right: 24px; + margin-left: 4px; + color: var(--theme-light); +} +.docs-wrapper .quick-links-grid p.header { + font-size: 22px; + font-weight: 600; + color: var(--text); + margin: 0; +} +.docs-wrapper .quick-links-grid p { + margin: 0; +} +.docs-wrapper .quick-links-grid svg:last-child { + height: 36px; + margin-left: auto; +} + +/* Scrollbar styling 'cause it's fancy */ +.docs-wrapper .sidebar::-webkit-scrollbar, +.docs-wrapper .content::-webkit-scrollbar, +.docs-wrapper .content pre code::-webkit-scrollbar { + width: 12px; + height: 12px; +} +.docs-wrapper .sidebar::-webkit-scrollbar-track, +.docs-wrapper .content::-webkit-scrollbar-track, +.docs-wrapper .content pre code::-webkit-scrollbar-track { + background: none; +} +.docs-wrapper .sidebar::-webkit-scrollbar-thumb, +.docs-wrapper .content::-webkit-scrollbar-thumb, +.docs-wrapper .content pre code::-webkit-scrollbar-thumb { + background-color: var(--text-secondary-2); + border-radius: 24px; + border: 3px solid #161931; +} +.docs-wrapper .content::-webkit-scrollbar-thumb { + border: 3px solid var(--background); +} +.docs-wrapper .content pre code::-webkit-scrollbar-thumb { + border: 3px solid #0D0F20; +} +.docs-wrapper .sidebar { + scrollbar-width: thin; + scrollbar-color: var(--text-secondary-2) #161931; +} +.docs-wrapper .content { + scrollbar-width: thin; + scrollbar-color: var(--text-secondary-2) var(--background); +} +.docs-wrapper .content pre codear { + scrollbar-width: thin; + scrollbar-color: var(--text-secondary-2) #0D0F20; +} diff --git a/public/assets/css/highlightjs.css b/public/assets/css/highlightjs.css index d0def53..d52a4c9 100644 --- a/public/assets/css/highlightjs.css +++ b/public/assets/css/highlightjs.css @@ -1,91 +1,137 @@ -/** - * Adapted from Shades of Purple Theme — for Highlightjs. - * - * @author (c) Ahmad Awais - * @link GitHub Repo → https://github.com/ahmadawais/Shades-of-Purple-HighlightJS - * @version 1.5.0 - */ - - .hljs { - background: var(--btn-secondary); - color: #e3dfff; - font-weight: normal; - } - - .hljs-subst { - color: #e3dfff; - } - - .hljs-title { - color: #fad000; - font-weight: normal; - } - - .hljs-name { - color: #a1feff; - } - - .hljs-tag { - color: #ffffff; - } - - .hljs-attr { - color: #f8d000; - font-style: italic; - } - - .hljs-built_in, - .hljs-selector-tag, - .hljs-section { - color: #fb9e00; - } - - .hljs-keyword { - color: #fb9e00; - } - - .hljs-string, - .hljs-attribute, - .hljs-symbol, - .hljs-bullet, - .hljs-addition, - .hljs-code, - .hljs-regexp, - .hljs-selector-class, - .hljs-selector-attr, - .hljs-selector-pseudo, - .hljs-template-tag, - .hljs-quote, - .hljs-deletion { - color: #4cd213; - } - - .hljs-meta, - .hljs-meta .hljs-string { - color: #fb9e00; - } - - .hljs-comment { - color: #ac65ff; - } - - .hljs-keyword, - .hljs-selector-tag, - .hljs-literal, - .hljs-name, - .hljs-strong { - font-weight: normal; - } - - .hljs-literal, - .hljs-number { - color: #fa658d; - } - - .hljs-emphasis { - font-style: italic; - } - - .hljs-strong { - font-weight: bold; - } \ No newline at end of file +pre code.hljs { + display: block; + overflow-x: auto; + padding: 12px 36px; + border-radius: 10px; + font-family: Poppins, Arial, Helvetica, sans-serif; +} +code.hljs { + padding: 3px 5px; +} +.hljs { + background: #0D0F20; + color: #d6deeb; +} +.hljs-keyword { + color: #c792ea; + font-style: italic; +} +.hljs-built_in { + color: #addb67; + font-style: italic; +} +.hljs-type { + color: #82aaff; +} +.hljs-literal { + color: #ff5874; +} +.hljs-number { + color: #f78c6c; +} +.hljs-regexp { + color: #5ca7e4; +} +.hljs-string { + color: #ecc48d; +} +.hljs-subst { + color: #d3423e; +} +.hljs-symbol { + color: #82aaff; +} +.hljs-class { + color: #ffcb8b; +} +.hljs-function { + color: #82aaff; +} +.hljs-title { + color: #dcdcaa; + font-style: italic; +} +.hljs-params { + color: #7fdbca; +} +.hljs-comment { + color: #637777; + font-style: italic; +} +.hljs-doctag { + color: #7fdbca; +} +.hljs-meta, +.hljs-meta .hljs-keyword { + color: #82aaff; +} +.hljs-meta .hljs-string { + color: #ecc48d; +} +.hljs-section { + color: #82b1ff; +} +.hljs-attr, +.hljs-name, +.hljs-tag { + color: #7fdbca; +} +.hljs-attribute { + color: #80cbc4; +} +.hljs-variable { + color: #addb67; +} +.hljs-bullet { + color: #d9f5dd; +} +.hljs-code { + color: #80cbc4; +} +.hljs-emphasis { + color: #c792ea; + font-style: italic; +} +.hljs-strong { + color: #addb67; + font-weight: 700; +} +.hljs-formula { + color: #c792ea; +} +.hljs-link { + color: #ff869a; +} +.hljs-quote { + color: #697098; + font-style: italic; +} +.hljs-selector-tag { + color: #ff6363; +} +.hljs-selector-id { + color: #fad430; +} +.hljs-selector-class { + color: #addb67; + font-style: italic; +} +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #c792ea; + font-style: italic; +} +.hljs-template-tag { + color: #c792ea; +} +.hljs-template-variable { + color: #addb67; +} +.hljs-addition { + color: #addb67ff; + font-style: italic; +} +.hljs-deletion { + color: #ef535090; + font-style: italic; +} diff --git a/public/assets/css/main.css b/public/assets/css/main.css index 2c99878..5212890 100644 --- a/public/assets/css/main.css +++ b/public/assets/css/main.css @@ -89,6 +89,7 @@ header nav a { .locale-dropdown { margin-left: auto; z-index: 2; + height: 45px; } /* Misc */ diff --git a/public/assets/images/arrow-right.svg b/public/assets/images/arrow-right.svg new file mode 100644 index 0000000..939b57c --- /dev/null +++ b/public/assets/images/arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/routers/docs.js b/src/routers/docs.js new file mode 100644 index 0000000..4e4999f --- /dev/null +++ b/src/routers/docs.js @@ -0,0 +1,92 @@ +const { Router } = require('express'); +const util = require('../util'); +const logger = require('../logger'); +const router = new Router(); + +const fs = require('fs'); +const path = require('path'); +const marked = require('marked'); +const matter = require('gray-matter'); +/* +const postList = () => { + const files = fs.readdirSync('blogposts'); + + // We get the info for each blogpost, ignoring the ones starting with _ + const posts = files + .filter(filename => !filename.startsWith('_')) + .filter(filename => filename.endsWith('.md')) // Ignores other files/folders + .map((filename) => { + const slug = filename.replace('.md', ''); + const rawPost = fs.readFileSync( + path.join('blogposts', `${filename}`), + 'utf-8' + ); + const { data: postInfo } = matter(rawPost); + return { + slug, + postInfo, + }; + }); + + posts.sort((a, b) => { + return new Date(b.postInfo.date) - new Date(a.postInfo.date); + }); + + return posts; +}; +*/ +router.get('/', async (request, response) => { + + const reqLocale = request.locale; + const locale = util.getLocale(reqLocale.region, reqLocale.language); + + const localeString = reqLocale.toString(); + + response.render('docs', { + layout: 'main', + locale, + localeString, + }); +}); +/* +router.get('/:slug', async (request, response, next) => { + + const reqLocale = request.locale; + const locale = util.getLocale(reqLocale.region, reqLocale.language); + + const localeString = reqLocale.toString(); + + // Get the name of the post from the URL + const postName = request.params.slug; + + // Get the markdown file corresponding to the post + let rawPost; + try { + rawPost = fs.readFileSync(path.join('blogposts', `${postName}.md`), 'utf-8'); + } catch(err) { + logger.error(err); + next(); + return; + } + // Convert the post info into JSON and separate it and the content + // eslint-disable-next-line prefer-const + let { data: postInfo, content } = matter(rawPost); + + // Replace [yt-iframe](videoID) with the full '); + + // Convert the content into HTML + const htmlPost = marked(content); + + response.render('blog/blogpost', { + layout: 'blog-opengraph', + locale, + localeString, + postInfo, + htmlPost, + }); +}); +*/ +module.exports = router; diff --git a/src/server.js b/src/server.js index a45414b..3e0ed4a 100644 --- a/src/server.js +++ b/src/server.js @@ -23,6 +23,7 @@ logger.info('Importing page routers'); const routers = { home: require('./routers/home'), faq: require('./routers/faq'), + docs: require('./routers/docs'), progress: require('./routers/progress'), account: require('./routers/account'), blog: require('./routers/blog'), @@ -72,6 +73,7 @@ app.use(expressLocale({ app.use('/', routers.home); app.use('/faq', routers.faq); +app.use('/docs', routers.docs); app.use('/progress', routers.progress); app.use('/account', routers.account); app.use('/localization', routers.localization); diff --git a/views/docs.handlebars b/views/docs.handlebars new file mode 100644 index 0000000..f0e298a --- /dev/null +++ b/views/docs.handlebars @@ -0,0 +1,136 @@ + + +
+ + + + + + + Pretendo + + + + + + {{> header}} + + {{> docs-sidebar}} + +
+
+

Quick links

+ + +

Other documentation

+

We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu.

+

We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu.

+

We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu.

+
+                
+function returnTrue() {
+  class trueOrFalseObject {
+    constructor(trueOrFalse) {
+      this.trueOrFalse = trueOrFalse;
+    }
+    get trueOrFalse() {
+      return this.trueOrFalse();
+    }
+    convertNumberToBoolean(trueOrFalse) {
+      if (convertStringToNumber(trueOrFalse) === 0) {
+        return true;
+      } else if (convertStringToNumber(trueOrFalse) == 1) {
+        return false;
+      }
+    }
+    convertStringToNumber(trueOrFalse) {
+      if (trueOrFalse === "true") {
+        return 0;
+      } else if (trueOrFalse === "false") {
+        return true * 69 - 1 - false * 69 * 420 - 69 + 2;
+      }
+    }
+    trueOrFalse() {
+      return this.convertNumberToBoolean(trueOrFalse);
+    }
+  }
+
+  let objectWhichWeKnowIsTrue = new trueOrFalseObject("true");
+
+  function checkIfTrueOrFalse(objectToCheckIfTrueOrFalse) {
+    if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) {
+      return objectWhichWeKnowIsTrue.trueOrFalse;
+      console.log(
+        "Successfully checked if the object is true or false. Result: the object is true."
+      );
+      // TODO: fix text not console logging
+    } else {
+      objectWhichWeKnowIsTrue = new trueOrFalseObject("false");
+      if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) {
+        return objectWhichWeKnowIsTrue.trueOrFalse;
+        console.log(
+          "Successfully checked if the object is true or false. Result: the object is false."
+        );
+        // TODO: fix text not console logging
+      } else {
+        // something went horribly wrong
+      }
+      objectWhichWeKnowIsTrue = new trueOrFalseObject("true");
+    }
+  }
+
+  const isTrueTrueOrFalse = checkIfTrueOrFalse("true");
+  const isfalseTrueOrFalse = checkIfTrueOrFalse("false");
+
+  const trueOrFalseJSON = {
+    true: isTrueTrueOrFalse,
+    false: isfalseTrueOrFalse,
+  };
+
+  return trueOrFalseJSON.true
+}
+
+console.log(returnTrue())
+                 
+            
+
+
+
+ + + + + diff --git a/views/layouts/blog-opengraph.handlebars b/views/layouts/blog-opengraph.handlebars index 520af6c..4bc6cc0 100644 --- a/views/layouts/blog-opengraph.handlebars +++ b/views/layouts/blog-opengraph.handlebars @@ -51,7 +51,7 @@ - + diff --git a/views/partials/docs-sidebar.handlebars b/views/partials/docs-sidebar.handlebars new file mode 100644 index 0000000..55cfb9c --- /dev/null +++ b/views/partials/docs-sidebar.handlebars @@ -0,0 +1,40 @@ + \ No newline at end of file diff --git a/views/partials/header.handlebars b/views/partials/header.handlebars index 7b3b5ea..37a9b50 100644 --- a/views/partials/header.handlebars +++ b/views/partials/header.handlebars @@ -28,6 +28,7 @@ {{ locale.nav.about }} {{ locale.nav.faq }} {{ locale.nav.credits }} + {{ locale.nav.docs }} {{ locale.nav.progress }} {{ locale.nav.blog }} From c330d2dd01c975d37410b0750ad7f8fb3fc76e22 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Wed, 8 Dec 2021 18:41:48 +0100 Subject: [PATCH 03/15] chore: bump highlight.js version --- views/blog/blogpost.handlebars | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/views/blog/blogpost.handlebars b/views/blog/blogpost.handlebars index 0433e3b..2dc00b7 100644 --- a/views/blog/blogpost.handlebars +++ b/views/blog/blogpost.handlebars @@ -29,7 +29,7 @@ - + + - - \ No newline at end of file + From aabcf0e337bc865f2b0a2e457d6490bb01494ce2 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Wed, 8 Dec 2021 23:29:54 +0100 Subject: [PATCH 04/15] feat(docs): Add render caching, add sidebar element selection, add missing locale notice, minor changes --- docs/en-US/installing-juxt.md | 12 +++ docs/en-US/welcome.md | 95 +++++++++++++++++ docs/it-IT/welcome.md | 95 +++++++++++++++++ locales/IT_it.json | 4 + locales/US_en.json | 3 + public/assets/css/documentation.css | 73 +++++++++++-- public/assets/css/highlightjs.css | 2 +- src/routers/docs.js | 99 +++++++++--------- views/docs.handlebars | 136 ------------------------- views/docs/docs.handlebars | 49 +++++++++ views/docs/search.handlebars | 40 ++++++++ views/partials/docs-sidebar.handlebars | 66 +++++++----- 12 files changed, 449 insertions(+), 225 deletions(-) create mode 100644 docs/en-US/installing-juxt.md create mode 100644 docs/en-US/welcome.md create mode 100644 docs/it-IT/welcome.md delete mode 100644 views/docs.handlebars create mode 100644 views/docs/docs.handlebars create mode 100644 views/docs/search.handlebars diff --git a/docs/en-US/installing-juxt.md b/docs/en-US/installing-juxt.md new file mode 100644 index 0000000..7f2e4db --- /dev/null +++ b/docs/en-US/installing-juxt.md @@ -0,0 +1,12 @@ +# Installing Juxt + +The first step to installing Juxt is playing a round of Among Us as an impostor. I promise it will all make sense ina second. + +``` +.    。    •   ゚  。   . +.      .     。   。 . +.   。      ඞ 。 .    •     • +゚   Red was not An Impostor.  。 . +'    1 Impostor remains     。 +゚   .   . ,    .  . +``` \ No newline at end of file diff --git a/docs/en-US/welcome.md b/docs/en-US/welcome.md new file mode 100644 index 0000000..1f0f132 --- /dev/null +++ b/docs/en-US/welcome.md @@ -0,0 +1,95 @@ +# Quick links + + + +# Other documentation + +We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu. + +We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu. + +We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu. + +```javascript +function returnTrue() { + class trueOrFalseObject { + constructor(trueOrFalse) { + this.trueOrFalse = trueOrFalse; + } + get trueOrFalse() { + return this.trueOrFalse(); + } + convertNumberToBoolean(trueOrFalse) { + if (convertStringToNumber(trueOrFalse) === 0) { + return true; + } else if (convertStringToNumber(trueOrFalse) == 1) { + return false; + } + } + convertStringToNumber(trueOrFalse) { + if (trueOrFalse === "true") { + return 0; + } else if (trueOrFalse === "false") { + return true * 69 - 1 - false * 69 * 420 - 69 + 2; + } + } + trueOrFalse() { + return this.convertNumberToBoolean(trueOrFalse); + } + } + + let objectWhichWeKnowIsTrue = new trueOrFalseObject("true"); + + function checkIfTrueOrFalse(objectToCheckIfTrueOrFalse) { + if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) { + return objectWhichWeKnowIsTrue.trueOrFalse; + console.log( + "Successfully checked if the object is true or false. Result: the object is true." + ); + // TODO: fix text not console logging + } else { + objectWhichWeKnowIsTrue = new trueOrFalseObject("false"); + if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) { + return objectWhichWeKnowIsTrue.trueOrFalse; + console.log( + "Successfully checked if the object is true or false. Result: the object is false." + ); + // TODO: fix text not console logging + } else { + // something went horribly wrong + } + objectWhichWeKnowIsTrue = new trueOrFalseObject("true"); + } + } + + const isTrueTrueOrFalse = checkIfTrueOrFalse("true"); + const isfalseTrueOrFalse = checkIfTrueOrFalse("false"); + + const trueOrFalseJSON = { + true: isTrueTrueOrFalse, + false: isfalseTrueOrFalse, + }; + + return trueOrFalseJSON.true +} + +console.log(returnTrue()) +``` diff --git a/docs/it-IT/welcome.md b/docs/it-IT/welcome.md new file mode 100644 index 0000000..e7e6b22 --- /dev/null +++ b/docs/it-IT/welcome.md @@ -0,0 +1,95 @@ +# Link rapidi + + + +# Altra documentazione + +Siamo un gruppo di programmer che spendono il loro tempo libero a sviluppare e fare reverse-engineering per i server online per la 3DS e Wii U. + +Siamo un gruppo di programmer che spendono il loro tempo libero a sviluppare e fare reverse-engineering per i server online per la 3DS e Wii U. + +Siamo un gruppo di programmer che spendono il loro tempo libero a sviluppare e fare reverse-engineering per i server online per la 3DS e Wii U. + +```javascript +function returnTrue() { + class trueOrFalseObject { + constructor(trueOrFalse) { + this.trueOrFalse = trueOrFalse; + } + get trueOrFalse() { + return this.trueOrFalse(); + } + convertNumberToBoolean(trueOrFalse) { + if (convertStringToNumber(trueOrFalse) === 0) { + return true; + } else if (convertStringToNumber(trueOrFalse) == 1) { + return false; + } + } + convertStringToNumber(trueOrFalse) { + if (trueOrFalse === "true") { + return 0; + } else if (trueOrFalse === "false") { + return true * 69 - 1 - false * 69 * 420 - 69 + 2; + } + } + trueOrFalse() { + return this.convertNumberToBoolean(trueOrFalse); + } + } + + let objectWhichWeKnowIsTrue = new trueOrFalseObject("true"); + + function checkIfTrueOrFalse(objectToCheckIfTrueOrFalse) { + if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) { + return objectWhichWeKnowIsTrue.trueOrFalse; + console.log( + "Successfully checked if the object is true or false. Result: the object is true." + ); + // TODO: fix text not console logging + } else { + objectWhichWeKnowIsTrue = new trueOrFalseObject("false"); + if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) { + return objectWhichWeKnowIsTrue.trueOrFalse; + console.log( + "Successfully checked if the object is true or false. Result: the object is false." + ); + // TODO: fix text not console logging + } else { + // something went horribly wrong + } + objectWhichWeKnowIsTrue = new trueOrFalseObject("true"); + } + } + + const isTrueTrueOrFalse = checkIfTrueOrFalse("true"); + const isfalseTrueOrFalse = checkIfTrueOrFalse("false"); + + const trueOrFalseJSON = { + true: isTrueTrueOrFalse, + false: isfalseTrueOrFalse, + }; + + return trueOrFalseJSON.true +} + +console.log(returnTrue()) +``` diff --git a/locales/IT_it.json b/locales/IT_it.json index d560281..a4bb3ec 100644 --- a/locales/IT_it.json +++ b/locales/IT_it.json @@ -2,6 +2,7 @@ "nav": { "about": "Info", "faq": "FAQ", + "docs": "Documentazione", "credits": "Riconoscimenti", "progress": "Progresso", "blog": "Blog" @@ -173,5 +174,8 @@ "fileInput": "File da testare", "filePlaceholder": "https://il.link.di/un_file.json", "button": "Testa file" + }, + "docs": { + "missingInLocale": "Questa pagina non è disponibile nella tua lingua. Per favore, controlla la versione in inglese sotto." } } \ No newline at end of file diff --git a/locales/US_en.json b/locales/US_en.json index 8a3583b..2f28f14 100644 --- a/locales/US_en.json +++ b/locales/US_en.json @@ -173,5 +173,8 @@ "fileInput": "File to test", "filePlaceholder": "https://a.link.to/the_file.json", "button": "Test file" + }, + "docs": { + "missingInLocale": "This page is unavailable in your locale. Please check the English version below." } } \ No newline at end of file diff --git a/public/assets/css/documentation.css b/public/assets/css/documentation.css index b4d56d4..7f56e7f 100644 --- a/public/assets/css/documentation.css +++ b/public/assets/css/documentation.css @@ -1,10 +1,12 @@ -html, body { +html, +body { background: #131730; } a.logo-link { - margin:auto; + margin: auto; margin-left: 36px; height: 40px; + text-decoration: none; } header { width: calc(100% - 72px); @@ -15,7 +17,7 @@ header { header a.logo-link { display: none; } -header nav a:first-child { +header nav a:first-child { margin-left: -24px; } @@ -23,7 +25,7 @@ header nav a:first-child { display: grid; grid-template-columns: repeat(2, fit-content(100%)); grid-template-rows: repeat(2, fit-content(100%)); - min-height: 100%; + height: 100vh; } .docs-wrapper .sidebar { @@ -34,12 +36,13 @@ header nav a:first-child { background: #161931; max-height: calc(100vh - 69px); overflow-y: scroll; + min-height: 100%; } .docs-wrapper .sidebar .section { display: flex; flex-flow: column; width: 200px; - margin-left: 30px; + margin-left: 138px; margin-bottom: 72px; } .docs-wrapper .sidebar .section:first-child { @@ -146,7 +149,7 @@ header nav a:first-child { border: 3px solid var(--background); } .docs-wrapper .content pre code::-webkit-scrollbar-thumb { - border: 3px solid #0D0F20; + border: 3px solid #0d0f20; } .docs-wrapper .sidebar { scrollbar-width: thin; @@ -158,5 +161,61 @@ header nav a:first-child { } .docs-wrapper .content pre codear { scrollbar-width: thin; - scrollbar-color: var(--text-secondary-2) #0D0F20; + scrollbar-color: var(--text-secondary-2) #0d0f20; +} +.docs-wrapper .content .missing-in-locale-notice { + background: #252a51; + padding: 24px; + border-radius: 6px; +} + + +.input-wrapper { + display: flex; + margin-top: 8px; +} + +.localization-form input { + appearance: none; + -webkit-appearance: none; + border: 0; + font-family: Poppins, Arial, Helvetica, sans-serif; + font-size: 1rem; + background-color: var(--btn-secondary); + border: none; + border-radius: 4px 0 0 4px; + padding: 12px 24px; + color: var(--text-secondary); + width: 20px; + flex: 2 10%; +} + +.search input::placeholder { + color: var(--text-secondary-2); +} + +.search input:focus { + background-color: #fff; + color: var(--btn-secondary); + transition: 200ms; + outline: none; +} + +.search button { + appearance: none; + -webkit-appearance: none; + border: 0; + font-family: Poppins, Arial, Helvetica, sans-serif; + font-size: 1rem; + color: var(--text); + padding: 12px 36px; + background: var(--btn); + cursor: pointer; +} + +@media screen and (max-width: 1080px) { + .docs-wrapper .sidebar .section { + margin-left: 60px; + width: 184px; + } } diff --git a/public/assets/css/highlightjs.css b/public/assets/css/highlightjs.css index d52a4c9..e71ac73 100644 --- a/public/assets/css/highlightjs.css +++ b/public/assets/css/highlightjs.css @@ -1,7 +1,7 @@ pre code.hljs { display: block; overflow-x: auto; - padding: 12px 36px; + padding: 36px; border-radius: 10px; font-family: Poppins, Arial, Helvetica, sans-serif; } diff --git a/src/routers/docs.js b/src/routers/docs.js index 4e4999f..f8a9b7f 100644 --- a/src/routers/docs.js +++ b/src/routers/docs.js @@ -1,92 +1,85 @@ const { Router } = require('express'); const util = require('../util'); -const logger = require('../logger'); const router = new Router(); const fs = require('fs'); const path = require('path'); const marked = require('marked'); -const matter = require('gray-matter'); -/* -const postList = () => { - const files = fs.readdirSync('blogposts'); - // We get the info for each blogpost, ignoring the ones starting with _ - const posts = files - .filter(filename => !filename.startsWith('_')) - .filter(filename => filename.endsWith('.md')) // Ignores other files/folders - .map((filename) => { - const slug = filename.replace('.md', ''); - const rawPost = fs.readFileSync( - path.join('blogposts', `${filename}`), - 'utf-8' - ); - const { data: postInfo } = matter(rawPost); - return { - slug, - postInfo, - }; - }); +// Here we'll store the rendered markdown files for future requests +const cachedPages = {}; - posts.sort((a, b) => { - return new Date(b.postInfo.date) - new Date(a.postInfo.date); - }); - - return posts; -}; -*/ router.get('/', async (request, response) => { + response.redirect('/docs/welcome'); +}); +router.get('/search', async (request, response) => { const reqLocale = request.locale; const locale = util.getLocale(reqLocale.region, reqLocale.language); const localeString = reqLocale.toString(); - response.render('docs', { + response.render('docs/search', { layout: 'main', locale, localeString, + currentPage: request.params.slug, }); }); -/* -router.get('/:slug', async (request, response, next) => { +router.get('/:slug', async (request, response, next) => { const reqLocale = request.locale; const locale = util.getLocale(reqLocale.region, reqLocale.language); const localeString = reqLocale.toString(); - // Get the name of the post from the URL - const postName = request.params.slug; + // Get the name of the page from the URL + const pageName = request.params.slug; - // Get the markdown file corresponding to the post - let rawPost; - try { - rawPost = fs.readFileSync(path.join('blogposts', `${postName}.md`), 'utf-8'); - } catch(err) { - logger.error(err); + let markdownLocale = localeString; + let missingInLocale = false; + // Check if the MD file exists in the user's locale, if not try en-US and show notice, or finally log error and show 404. + if (fs.existsSync(path.join('docs', localeString, `${pageName}.md`))) { + null; + } else if (fs.existsSync(path.join('docs', 'en-US', `${pageName}.md`))) { + markdownLocale = 'en-US'; + missingInLocale = true; + } else { next(); return; } - // Convert the post info into JSON and separate it and the content - // eslint-disable-next-line prefer-const - let { data: postInfo, content } = matter(rawPost); - // Replace [yt-iframe](videoID) with the full '); + let content; + // If the page has already been rendered, use the cached version + if (cachedPages[markdownLocale]?.[pageName]) { + content = cachedPages[markdownLocale]?.[pageName]; + } else { + // Get the markdown file corresponding to the page. + content = fs.readFileSync(path.join('docs', markdownLocale, `${pageName}.md`), 'utf-8'); - // Convert the content into HTML - const htmlPost = marked(content); + // Replace [yt-iframe](videoID) with the full '); - response.render('blog/blogpost', { - layout: 'blog-opengraph', + // Convert the content into HTML + content = marked(content); + + // Push the content into the cache + if (!cachedPages[markdownLocale]) { + cachedPages[markdownLocale] = {}; + } + cachedPages[markdownLocale][pageName] = content; + } + + response.render('docs/docs', { + layout: 'main', locale, localeString, - postInfo, - htmlPost, + content, + currentPage: request.params.slug, + missingInLocale, }); }); -*/ + module.exports = router; diff --git a/views/docs.handlebars b/views/docs.handlebars deleted file mode 100644 index f0e298a..0000000 --- a/views/docs.handlebars +++ /dev/null @@ -1,136 +0,0 @@ - - -
- - - - - - - Pretendo - - - - - - {{> header}} - - {{> docs-sidebar}} - -
-
-

Quick links

- - -

Other documentation

-

We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu.

-

We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu.

-

We are a bunch of programmers spending our free time reverse engineering and coding game servers for 3ds and wiiu.

-
-                
-function returnTrue() {
-  class trueOrFalseObject {
-    constructor(trueOrFalse) {
-      this.trueOrFalse = trueOrFalse;
-    }
-    get trueOrFalse() {
-      return this.trueOrFalse();
-    }
-    convertNumberToBoolean(trueOrFalse) {
-      if (convertStringToNumber(trueOrFalse) === 0) {
-        return true;
-      } else if (convertStringToNumber(trueOrFalse) == 1) {
-        return false;
-      }
-    }
-    convertStringToNumber(trueOrFalse) {
-      if (trueOrFalse === "true") {
-        return 0;
-      } else if (trueOrFalse === "false") {
-        return true * 69 - 1 - false * 69 * 420 - 69 + 2;
-      }
-    }
-    trueOrFalse() {
-      return this.convertNumberToBoolean(trueOrFalse);
-    }
-  }
-
-  let objectWhichWeKnowIsTrue = new trueOrFalseObject("true");
-
-  function checkIfTrueOrFalse(objectToCheckIfTrueOrFalse) {
-    if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) {
-      return objectWhichWeKnowIsTrue.trueOrFalse;
-      console.log(
-        "Successfully checked if the object is true or false. Result: the object is true."
-      );
-      // TODO: fix text not console logging
-    } else {
-      objectWhichWeKnowIsTrue = new trueOrFalseObject("false");
-      if (objectToCheckIfTrueOrFalse === objectWhichWeKnowIsTrue.trueOrFalse) {
-        return objectWhichWeKnowIsTrue.trueOrFalse;
-        console.log(
-          "Successfully checked if the object is true or false. Result: the object is false."
-        );
-        // TODO: fix text not console logging
-      } else {
-        // something went horribly wrong
-      }
-      objectWhichWeKnowIsTrue = new trueOrFalseObject("true");
-    }
-  }
-
-  const isTrueTrueOrFalse = checkIfTrueOrFalse("true");
-  const isfalseTrueOrFalse = checkIfTrueOrFalse("false");
-
-  const trueOrFalseJSON = {
-    true: isTrueTrueOrFalse,
-    false: isfalseTrueOrFalse,
-  };
-
-  return trueOrFalseJSON.true
-}
-
-console.log(returnTrue())
-                 
-            
-
-
-
- - - - - diff --git a/views/docs/docs.handlebars b/views/docs/docs.handlebars new file mode 100644 index 0000000..a0e5f68 --- /dev/null +++ b/views/docs/docs.handlebars @@ -0,0 +1,49 @@ + + +
+ + + + + + + Pretendo + + + + + + {{> header}} + + {{> docs-sidebar}} + +
+
+ {{#if missingInLocale}} +

{{locale.docs.missingInLocale}}

+ {{/if}} + + {{{ content }}} +
+
+
+ + + + + + diff --git a/views/docs/search.handlebars b/views/docs/search.handlebars new file mode 100644 index 0000000..7184a73 --- /dev/null +++ b/views/docs/search.handlebars @@ -0,0 +1,40 @@ + + +
+ + + + + + + Pretendo + + + + + + {{> header}} + + {{> docs-sidebar}} + +
+
+
+
+
+
+ diff --git a/views/partials/docs-sidebar.handlebars b/views/partials/docs-sidebar.handlebars index 55cfb9c..cd54be5 100644 --- a/views/partials/docs-sidebar.handlebars +++ b/views/partials/docs-sidebar.handlebars @@ -1,40 +1,50 @@ \ No newline at end of file + + + \ No newline at end of file From c65c656a7592a2deec88caa61e131d3ee132f742 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Thu, 9 Dec 2021 18:23:44 +0100 Subject: [PATCH 05/15] chore: Remove render caching Turns out it wasn't needed after all --- src/routers/docs.js | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/routers/docs.js b/src/routers/docs.js index f8a9b7f..a531f11 100644 --- a/src/routers/docs.js +++ b/src/routers/docs.js @@ -6,9 +6,6 @@ const fs = require('fs'); const path = require('path'); const marked = require('marked'); -// Here we'll store the rendered markdown files for future requests -const cachedPages = {}; - router.get('/', async (request, response) => { response.redirect('/docs/welcome'); }); @@ -50,27 +47,16 @@ router.get('/:slug', async (request, response, next) => { } let content; - // If the page has already been rendered, use the cached version - if (cachedPages[markdownLocale]?.[pageName]) { - content = cachedPages[markdownLocale]?.[pageName]; - } else { - // Get the markdown file corresponding to the page. - content = fs.readFileSync(path.join('docs', markdownLocale, `${pageName}.md`), 'utf-8'); + // Get the markdown file corresponding to the page. + content = fs.readFileSync(path.join('docs', markdownLocale, `${pageName}.md`), 'utf-8'); - // Replace [yt-iframe](videoID) with the full '); + // Replace [yt-iframe](videoID) with the full '); - // Convert the content into HTML - content = marked(content); - - // Push the content into the cache - if (!cachedPages[markdownLocale]) { - cachedPages[markdownLocale] = {}; - } - cachedPages[markdownLocale][pageName] = content; - } + // Convert the content into HTML + content = marked(content); response.render('docs/docs', { layout: 'main', From eb35ec8feb39f67e8d4e957a2e5b1811e5aa696c Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Thu, 9 Dec 2021 18:33:18 +0100 Subject: [PATCH 06/15] feat: add showQuickLinks boolean --- docs/en-US/welcome.md | 20 -------------------- docs/it-IT/welcome.md | 22 ---------------------- src/routers/docs.js | 7 +++++++ views/docs/docs.handlebars | 23 +++++++++++++++++++++++ 4 files changed, 30 insertions(+), 42 deletions(-) diff --git a/docs/en-US/welcome.md b/docs/en-US/welcome.md index 1f0f132..7feaafd 100644 --- a/docs/en-US/welcome.md +++ b/docs/en-US/welcome.md @@ -1,24 +1,4 @@ -# Quick links - # Other documentation diff --git a/docs/it-IT/welcome.md b/docs/it-IT/welcome.md index e7e6b22..1fbbc7a 100644 --- a/docs/it-IT/welcome.md +++ b/docs/it-IT/welcome.md @@ -1,25 +1,3 @@ -# Link rapidi - - - # Altra documentazione Siamo un gruppo di programmer che spendono il loro tempo libero a sviluppare e fare reverse-engineering per i server online per la 3DS e Wii U. diff --git a/src/routers/docs.js b/src/routers/docs.js index a531f11..5773ad1 100644 --- a/src/routers/docs.js +++ b/src/routers/docs.js @@ -58,6 +58,12 @@ router.get('/:slug', async (request, response, next) => { // Convert the content into HTML content = marked(content); + // A boolean to show the quick links grid or not. + let showQuickLinks = false; + if (pageName === 'welcome') { + showQuickLinks = true; + } + response.render('docs/docs', { layout: 'main', locale, @@ -65,6 +71,7 @@ router.get('/:slug', async (request, response, next) => { content, currentPage: request.params.slug, missingInLocale, + showQuickLinks }); }); diff --git a/views/docs/docs.handlebars b/views/docs/docs.handlebars index a0e5f68..3bee4af 100644 --- a/views/docs/docs.handlebars +++ b/views/docs/docs.handlebars @@ -37,6 +37,29 @@

{{locale.docs.missingInLocale}}

{{/if}} + {{#if showQuickLinks}} +

Quick links

+ + {{/if}} + {{{ content }}} From 248174964849a72f4aae42efcf235850bb44a0f4 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Thu, 9 Dec 2021 21:03:01 +0100 Subject: [PATCH 07/15] feat(locales): add automatic locale fallback --- src/server.js | 25 +++++++++++++++++++++++++ views/blog/blog.handlebars | 4 ++-- views/docs/docs.handlebars | 2 +- views/home.handlebars | 24 ++++++++++++------------ views/localization.handlebars | 12 ++++++------ views/partials/header.handlebars | 12 ++++++------ views/progress.handlebars | 4 ++-- 7 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/server.js b/src/server.js index 3e0ed4a..d74e17a 100644 --- a/src/server.js +++ b/src/server.js @@ -9,6 +9,8 @@ const logger = require('./logger'); const util = require('./util'); const config = require('../config.json'); +const defaultLocale = require('../locales/US_en.json'); + const { http: { port } } = config; const app = express(); @@ -118,6 +120,29 @@ app.engine('handlebars', handlebars({ }, neq(value1, value2) { return value1 !== value2; + }, + localeHelper(...args) { + let userLocaleString = args[0]; + + /* + * Removes the first and the last argument, and then loops through the rest to + * get the string in the user's locale. If not available, it will return it in + * the default locale. + */ + + args.slice(1, -1).forEach(arg => { + userLocaleString = userLocaleString?.[arg]; + }); + + if (!userLocaleString) { + let defaultLocaleString = defaultLocale; + args.slice(1, -1).forEach(arg => { + defaultLocaleString = defaultLocaleString?.[arg]; + }); + return defaultLocaleString; + } else { + return userLocaleString; + } } } })); diff --git a/views/blog/blog.handlebars b/views/blog/blog.handlebars index 714709b..ea2cba0 100644 --- a/views/blog/blog.handlebars +++ b/views/blog/blog.handlebars @@ -7,8 +7,8 @@
-

{{ locale.blogPage.title }}

-

{{{ locale.blogPage.description }}}

+

{{ localeHelper locale "blogPage" "title" }}

+

{{{ localeHelper locale "blogPage" "description" }}}

diff --git a/views/docs/docs.handlebars b/views/docs/docs.handlebars index 3bee4af..d5b7c12 100644 --- a/views/docs/docs.handlebars +++ b/views/docs/docs.handlebars @@ -34,7 +34,7 @@
{{#if missingInLocale}} -

{{locale.docs.missingInLocale}}

+

{{ localeHelper locale "docs" "missingInLocale" }}

{{/if}} {{#if showQuickLinks}} diff --git a/views/home.handlebars b/views/home.handlebars index 1604ea8..b1dc370 100644 --- a/views/home.handlebars +++ b/views/home.handlebars @@ -5,15 +5,15 @@
-

{{ locale.hero.subtitle }}

-

{{ locale.hero.title }}

+

{{ localeHelper locale "hero" "subtitle" }}

+

{{ localeHelper locale "hero" "title" }}

- {{ locale.hero.text }} + {{ localeHelper locale "hero" "text" }}

@@ -75,22 +75,22 @@
-

{{ locale.aboutUs.title }}

+

{{ localeHelper locale "aboutUs" "title" }}

{{#each locale.aboutUs.paragraphs}}

{{ this }}

{{/each}}
-

{{ locale.progress.title }}

+

{{ localeHelper locale "progress" "title" }}

{{> progress-list data=featuredFeatureList purple=true boards=boards }}
-

{{ locale.faq.title }}

-

{{ locale.faq.text }}

+

{{ localeHelper locale "faq" "title" }}

+

{{ localeHelper locale "faq" "text" }}

{{#doFaq locale.faq.QAs}} @@ -108,8 +108,8 @@
-

{{ locale.credits.title }}

-

{{ locale.credits.text }}

+

{{ localeHelper locale "credits" "title" }}

+

{{ localeHelper locale "credits" "text" }}

{{#each locale.credits.people}} @@ -134,8 +134,8 @@
-

{{ locale.specialThanks.title }}

-

{{ locale.specialThanks.text }}

+

{{ localeHelper locale "specialThanks" "title" }}

+

{{ localeHelper locale "specialThanks" "text" }}

{{#each locale.specialThanks.people}} diff --git a/views/localization.handlebars b/views/localization.handlebars index 72ca568..74f8c83 100644 --- a/views/localization.handlebars +++ b/views/localization.handlebars @@ -6,17 +6,17 @@
diff --git a/views/partials/header.handlebars b/views/partials/header.handlebars index 37a9b50..012690b 100644 --- a/views/partials/header.handlebars +++ b/views/partials/header.handlebars @@ -25,12 +25,12 @@ diff --git a/views/progress.handlebars b/views/progress.handlebars index f0507d0..0bbd7aa 100644 --- a/views/progress.handlebars +++ b/views/progress.handlebars @@ -5,8 +5,8 @@
-

{{ locale.progressPage.title }}

-

{{ locale.progressPage.description }}

+

{{ localeHelper locale "progressPage" "title" }}

+

{{ localeHelper locale "progressPage" "description" }}

From d212e447237eba1b8b71663d537ec9ec3bede076 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Fri, 10 Dec 2021 15:16:07 +0100 Subject: [PATCH 08/15] feat: Implement @mrjvs's design --- public/assets/css/blogpost.css | 8 +- public/assets/css/main.css | 320 ++++++++++++++++++++++++++++++- views/home.handlebars | 116 +++++++++-- views/partials/footer.handlebars | 56 +++++- 4 files changed, 471 insertions(+), 29 deletions(-) diff --git a/public/assets/css/blogpost.css b/public/assets/css/blogpost.css index 30c8a2d..b4bd9f6 100644 --- a/public/assets/css/blogpost.css +++ b/public/assets/css/blogpost.css @@ -15,8 +15,7 @@ header { .blog-card { padding: 60px; max-width: 1100px; - margin: auto; - margin-top: 50px; + margin: 50px auto; color: var(--text-secondary); } @@ -197,11 +196,6 @@ header { margin-bottom: 30px; } -footer { - padding-top: 40px; - margin-top: auto; -} - @media screen and (max-width: 800px) { .blog-card { padding: 40px; diff --git a/public/assets/css/main.css b/public/assets/css/main.css index 5212890..6cb1020 100644 --- a/public/assets/css/main.css +++ b/public/assets/css/main.css @@ -26,6 +26,10 @@ body, .main-body { font-family: Poppins, Arial, Helvetica, sans-serif; } +.main-body { + overflow-y: hidden; /* Fixes the dowuble scrollbars caused by the last background circle */ +} + .animateDot { animation: dotAnimation 10s infinite; } @@ -298,6 +302,13 @@ section.progress .right { border-top-left-radius: 10px; border-bottom-left-radius: 10px; } +section.progress .right .title a { + text-decoration: none; + color: var(--text); +} +section.progress .right .title a:hover { + text-decoration: underline; +} section.progress .right:before { content: ""; width: 300vw; @@ -349,6 +360,52 @@ section.faq { text-decoration: underline; } +section.showcase { + position: relative; + margin-top: 160px; + padding: 220px 0; +} +section.showcase::before { + content: ""; + width: 400vw; + margin-left: -50vw; + background: linear-gradient(180deg, rgba(19, 22, 36, 0) 0%, #131624 100%); + position: absolute; + top: 0; + bottom: 0; + z-index: -1; +} +section.showcase .text { + max-width: 504px; + margin-bottom: 132px; +} +section.showcase .grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 24px; +} +section.showcase .grid .item { + background: #252A51; + border-radius: 10px; + padding: 42px 36px; +} +section.showcase .grid .item.highlight { + border: 2px solid #9D6FF3; +} +section.showcase .grid .item svg { + height: 36px; + color: #9D6FF3; +} +section.showcase .grid .item h1 { + margin-top: 14px; + margin-bottom: 6px; + font-weight: 600; +} +section.showcase .grid .item p { + margin: 0; + color: var(--text-secondary) +} + section.team { margin-top: 220px; } @@ -425,6 +482,187 @@ section.team { color: var(--text-secondary); } +section.team-helpers { + position: relative; + margin-top: 160px; + margin-bottom: 160px; +} +section.team-helpers .text { + max-width: 504px; + margin-bottom: 132px; +} +section.team-helpers .team-helpers-cards { + display: inline-grid; + grid-template-columns: repeat(5, 1fr); + grid-gap: 20px; + margin-right: 20px; + color: var(--text-secondary); + width: max-content; +} +section.team-helpers .animation-wrapper { + transform: rotate(-5deg); + overflow-x: hidden; + position:relative; + top: -90px; + padding: 20px; /* Needed for the star not to get cut off */ +} +section.team-helpers .animation-wrapper::after { + content: ""; + position: absolute; + top: 0; + width: 101%; /* If set to 100% it doesn't cover it completely */ + left: -0.5%; + height: 100%; + background: linear-gradient(90deg, var(--background) 0%, rgba(27, 31, 59, 0) 20%, rgba(27, 31, 59, 0) 80%, var(--background) 100%); + z-index: 1; + pointer-events: none; +} +section.team-helpers .animation-wrapper .row { + white-space: nowrap; +} +section.team-helpers .animation-wrapper .row.second { + margin-top: 20px; +} +section.team-helpers .helper-card { + text-decoration: none; + display: flex; + flex-direction: row; + align-items: center; + padding: 14px 24px; + background: #16192D; + border-radius: 12px; + animation: scrollHelpersRTL 25s linear infinite; +} +section.team-helpers .row.second .helper-card { + animation: scrollHelpersLTR 25s linear infinite; +} +section.team-helpers .helper-card:hover { + background: #252A51; + transition: 200ms; +} +@keyframes scrollHelpersRTL { + 0% { + transform: translatex(0%); + } + 100% { + transform: translateX(calc( ( ( 100% + 20px ) * -5 ) + -7px)); + } +} +@keyframes scrollHelpersLTR { + 0% { + transform: translateX(calc( ( ( 100% + 20px ) * -5 ) + -7px)); + } + 100% { + transform: translatex(0%); + } +} +section.team-helpers .helper-card.special { + position: relative; + box-shadow: 0px 0px 0px 2px rgba(211, 225, 87, 0.6) inset; +} +section.team-helpers .helper-card.special::after { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='31.571' height='30.218' viewBox='0 0 31.571 30.218'%3E%3Cpath id='Icon_awesome-star' data-name='Icon awesome-star' d='M15.533,1.05,11.68,8.863,3.058,10.12a1.889,1.889,0,0,0-1.044,3.222L8.251,19.42,6.776,28.006A1.887,1.887,0,0,0,9.514,30l7.713-4.054L24.94,30a1.889,1.889,0,0,0,2.738-1.989L26.2,19.42l6.237-6.078A1.889,1.889,0,0,0,31.4,10.12L22.774,8.863,18.92,1.05a1.89,1.89,0,0,0-3.387,0Z' transform='translate(-1.441 0.001)' fill='%23d3e848'/%3E%3C/svg%3E%0A"); + position: absolute; + width: 30px; + height: 30px; + top: -13px; + right: -13px; +} +section.team-helpers .row.second .helper-card { + position:relative; + left: calc(-250% - 50px); +} +section.team-helpers .helper-card .img-wrapper { + background: #fff; + border-radius: 100%; + margin-right: 14px; + width: 48px; + height: 48px; +} +section.team-helpers .helper-card .pfp { + border-radius: 100%; + width: 48px; + height: 48px; +} +section.team-helpers .helper-card span { + color: var(--text); + font-weight: 600; + margin-right: 0.6ch; +} +section.team-helpers .helper-card p { + color: var(--text-secondary); +} +/* These two fix the spacing being inconsistent on some card, thus "jumping" on repeat. I'm fairly certain it isn't my fault */ +section.team-helpers .row.first .team-helpers-cards.repeat.first a:nth-child(3){ + position: relative; + left: 5px; +} +section.team-helpers .row.second .team-helpers-cards.repeat.first a.special, +section.team-helpers .row.second .team-helpers-cards.repeat.second a:nth-child(1){ + left: calc(-250% - 45px); +} + +section.update-signup { + position: relative; + width: 100%; + display: flex; + flex-flow: column; + justify-items: center; + align-items: center; + text-align: center; + padding-top: 240px; + padding-bottom: 300px; +} +section.update-signup svg { + width: 4rem; + height: 4rem; + margin-bottom: 42px; +} +section.update-signup .text { + margin-top: 8px; + max-width: 423px; +} +section.update-signup .floating-serverjoin { + display: grid; + grid-template-columns: repeat(2, auto); + width: 100%; + max-width: 576px; + + background: #15182D; + border-radius: 6px; + padding: 18px; + + overflow-x: hidden; +} +section.update-signup .floating-serverjoin p { + color: var(--text-secondary); + margin: auto; + margin-left: 0; +} +section.update-signup .floating-serverjoin a { + color: var(--text); + text-decoration: none; + background: var(--theme); + margin: 0; + margin-left: auto; + padding: 9px 18px; + border-radius: 5px; + width: fit-content; +} +section.update-signup div.circle { + display: block; + background: #202442; + /* the next 4 lines make it so the circle is always the same aspect ratio and covers enough of the screen */ + width: 2591px; + height: 1454px; + min-width: 135vw; + min-height: 76vw; /* yes, this is supposed to be in vw */ + border-radius: 100%; + position: absolute; + top: 0; + z-index: -1; +} + /* Progress */ .all-progress-lists { margin-top: 50px; @@ -436,6 +674,7 @@ section.team { display: grid; grid-template-columns: auto 1fr; grid-gap: 20px; + margin-top: 22px; } .feature-progress-chart { max-width: 100px; @@ -548,10 +787,85 @@ section.team { /* Footer */ footer { - text-align: center; + width: 100%; + display: grid; + grid-template-columns: repeat(3, fit-content(100%)) 1fr; + gap: 148px; color: var(--text-secondary); - margin-top: 290px; - margin-bottom: 40px; + margin-top: 120px; + position: relative; + padding: 60px 0; +} +footer::after { + content: ""; + width: 400vw; + height: 100%; + position: absolute; + top: 0; + left: -50vw; + background: #15182D; + z-index: -1; +} +footer div { + display: flex; + flex-flow: column; + width: fit-content; +} +footer svg.logotype { + height: 56px; + width: fit-content; + margin: -10px 0 24px -10px; +} +footer p { + margin: 0; +} +footer h1 { + font-size: 20px; + margin-top: 0; + color: var(--text); +} +footer a { + color: var(--text-secondary); + text-decoration: none; + width: fit-content; +} +footer a:hover { + color: var(--text); + text-decoration: underline; +} +footer div.discord-server-card { + background: #222641; + border-radius: 12px; + padding: 30px 90px 30px 36px; + justify-self: end; +} +footer div.discord-server-card h1 { + font-size: 25px; + margin: 0; +} +footer div.discord-server-card h2 { + color: var(--text); + font-size: 22px; + margin: 0; +} +footer div.discord-server-card a { + display: flex; + align-items: center; + color: #CAB1FB; + font-size: 22px; + text-decoration: none; + width: fit-content; + margin-left: -2px; + margin-top: 12px; +} +footer div.discord-server-card a:hover { + text-decoration: underline; + +} +footer div.discord-server-card svg { + height: 24px; + stroke-width: 3px; + margin-right: 4px; } @media screen and (min-width: 701px) and (max-width: 1500px) { diff --git a/views/home.handlebars b/views/home.handlebars index b1dc370..175589a 100644 --- a/views/home.handlebars +++ b/views/home.handlebars @@ -82,7 +82,9 @@
-

{{ localeHelper locale "progress" "title" }}

+

+ {{ localeHelper locale "progress" "title" }} +

{{> progress-list data=featuredFeatureList purple=true boards=boards }}
@@ -105,6 +107,30 @@ {{!-- Tmp! --}}
+ +
+
+

What we make

+

An open source project that aims to recreate all Nintendo servers for 3DS and Wiiu. This way the services can persist after officially killed by Nintendo.

+
+
+
+ +

Juxtaposition

+

A Miiverse replacement

+
+
+ +

Juxtaposition

+

A Miiverse replacement

+
+
+ +

Juxtaposition

+

A Miiverse replacement

+
+
+
@@ -132,32 +158,86 @@
-
-
+
+

{{ localeHelper locale "specialThanks" "title" }}

{{ localeHelper locale "specialThanks" "text" }}

-
- {{#each locale.specialThanks.people}} -
-
- -
-
- {{#if special}}{{ special }}{{/if}} -

+
+
+
+ {{#each locale.specialThanks.people}} + +
+ +
{{ name }} -
- - -

-

{{ caption }}

+

{{ caption }}

+ + {{/each}} +
+
+ {{#each locale.specialThanks.people}} + +
+ +
+ {{ name }} +

{{ caption }}

+
+ {{/each}} +
+
+
+
+ {{#each locale.specialThanks.people}} + +
+ +
+ {{ name }} +

{{ caption }}

+
+ {{/each}} +
+
+ {{#each locale.specialThanks.people}} + +
+ +
+ {{ name }} +

{{ caption }}

+
+ {{/each}} +
+
+ {{#each locale.specialThanks.people}} + +
+ +
+ {{ name }} +

{{ caption }}

+
+ {{/each}}
- {{/each}}
+ {{> footer }} diff --git a/views/partials/footer.handlebars b/views/partials/footer.handlebars index a674ead..9afd672 100644 --- a/views/partials/footer.handlebars +++ b/views/partials/footer.handlebars @@ -1 +1,55 @@ -
Copyright 2021 - Design by mrjvs, development by Jip Fr & monty
\ No newline at end of file + \ No newline at end of file From ade69a1bb0e0ca2301f4d5dad9cc8889e6f90847 Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Sun, 12 Dec 2021 14:51:35 +0100 Subject: [PATCH 09/15] fix: chart.js throwing error on hover #48 --- public/assets/css/main.css | 3 +++ views/partials/progress-list.handlebars | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/public/assets/css/main.css b/public/assets/css/main.css index 6cb1020..7f9a80e 100644 --- a/public/assets/css/main.css +++ b/public/assets/css/main.css @@ -679,6 +679,9 @@ section.update-signup div.circle { .feature-progress-chart { max-width: 100px; } +.feature-progress-chart canvas.percentage-chart { + pointer-events: none; /* Fixes issue #48 */ +} .feature-list-wrapper h3 { margin: 0; } diff --git a/views/partials/progress-list.handlebars b/views/partials/progress-list.handlebars index 91e6460..7d06b36 100644 --- a/views/partials/progress-list.handlebars +++ b/views/partials/progress-list.handlebars @@ -3,7 +3,7 @@

{{ data.percent }}

- +
From 918cab90049ed92f37d5d56d855b824f1c07861e Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Dec 2021 09:24:17 -0500 Subject: [PATCH 10/15] Added register page --- package-lock.json | 2446 ++++++++++++++++++++++++++++- public/assets/css/register.css | 95 ++ src/routers/account.js | 52 + views/account_register.handlebars | 47 + 4 files changed, 2638 insertions(+), 2 deletions(-) create mode 100644 public/assets/css/register.css create mode 100644 views/account_register.handlebars diff --git a/package-lock.json b/package-lock.json index ec7f793..ce84c29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,2448 @@ { "name": "website", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "colors": "^1.4.0", + "cookie-parser": "^1.4.5", + "discord-oauth2": "github:ryanblenis/discord-oauth2", + "express": "^4.17.1", + "express-handlebars": "^4.0.4", + "express-locale": "^2.0.0", + "fs-extra": "^9.1.0", + "got": "^11.8.2", + "gray-matter": "^4.0.3", + "marked": "^3.0.4", + "morgan": "^1.10.0", + "trello": "^0.11.0" + }, + "devDependencies": { + "eslint": "^7.32.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "node_modules/@types/keyv": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", + "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "16.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", + "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==" + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argparse/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "optional": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "dependencies": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/discord-oauth2": { + "version": "2.9.0", + "resolved": "git+ssh://git@github.com/ryanblenis/discord-oauth2.git#ca0093d5b34efdd6ec2ce45a4a2678b3282cea31", + "integrity": "sha512-J3w3djV6I4PtnLp3lZga4m41DPjqXtyETV8rMG9FSIev5i5mxpkrsfXRni3Jc+qYxH86LcLa7zUwnWHHXpcu0g==", + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/es6-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=" + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-handlebars": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-4.0.4.tgz", + "integrity": "sha512-WxbQorVc7V9ORzp9YpG3fLAzrfIrKcScSezuFxTZRFJSx/P2f7QJ9ZyADV8cyPuomyzUxAJnw6t8dnriLfBNvg==", + "dependencies": { + "glob": "^7.1.6", + "graceful-fs": "^4.2.4", + "handlebars": "^4.7.6", + "object.assign": "^4.1.0", + "promise": "^8.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/express-locale": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/express-locale/-/express-locale-2.0.0.tgz", + "integrity": "sha512-SUwsgOTV8lplAkgyfKSwKH3ZVSKUrAa+b48acPGXpwWX211WZ/BYWX2WcZO57+xLOqPYb6rSNpWCFnhGrt0moA==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/got": { + "version": "11.8.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", + "integrity": "sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz", + "integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/marked": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.4.tgz", + "integrity": "sha512-jBo8AOayNaEcvBhNobg6/BLhdsK3NvnKWJg33MAAPbvTWiG4QBn9gpW1+7RssrKu4K1dKlN+0goVQwV41xEfOA==", + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/restler": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/restler/-/restler-3.3.0.tgz", + "integrity": "sha1-+TpZteG8LFrQwrlz94EpshgbYHY=", + "dependencies": { + "iconv-lite": "0.2.11", + "qs": "1.2.0", + "xml2js": "0.4.0", + "yaml": "0.2.3" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/restler/node_modules/iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/restler/node_modules/qs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.0.tgz", + "integrity": "sha1-7Qeb4oaCFH5v2aNMwrDB4OxkU+4=" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/trello": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/trello/-/trello-0.11.0.tgz", + "integrity": "sha512-WMjfSTA+ybGnd36ZoMX7Ia7wfpU9KP2lsafv9mjLwFcE1ECp8b9/rX3uW4ivNO7jVLnHRyQ1pHsirbMvK0Ix2Q==", + "dependencies": { + "es6-promise": "~3.0.2", + "object-assign": "~4.1.0", + "restler": "~3.3.0" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uglify-js": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.2.tgz", + "integrity": "sha512-zGVwKslUAD/EeqOrD1nQaBmXIHl1Vw371we8cvS8I6mYK9rmgX5tv8AAeJdfsQ3Kk5mGax2SVV/AizxdNGhl7Q==", + "optional": true, + "dependencies": { + "commander": "~2.20.3" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xml2js": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.0.tgz", + "integrity": "sha1-Ek/EEUtBKcgQgA7LKshs8lRiy5o=", + "dependencies": { + "sax": "0.5.x", + "xmlbuilder": ">=0.4.2" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-0.2.3.tgz", + "integrity": "sha1-tUUOkudu82td0k42YAkeuu7z5cc=", + "engines": { + "node": "*" + } + } + }, "dependencies": { "@babel/code-frame": { "version": "7.12.11", @@ -225,7 +2665,8 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv": { "version": "6.12.6", @@ -511,6 +2952,7 @@ }, "discord-oauth2": { "version": "git+ssh://git@github.com/ryanblenis/discord-oauth2.git#ca0093d5b34efdd6ec2ce45a4a2678b3282cea31", + "integrity": "sha512-J3w3djV6I4PtnLp3lZga4m41DPjqXtyETV8rMG9FSIev5i5mxpkrsfXRni3Jc+qYxH86LcLa7zUwnWHHXpcu0g==", "from": "discord-oauth2@github:ryanblenis/discord-oauth2" }, "doctrine": { diff --git a/public/assets/css/register.css b/public/assets/css/register.css new file mode 100644 index 0000000..d231b8f --- /dev/null +++ b/public/assets/css/register.css @@ -0,0 +1,95 @@ +.wrapper { + display: flex; + flex-flow: column; + min-height: 100vh; +} + +.register-wrapper { + margin: auto; +} + +form.register { + padding: 48px; + background-color: #151934; + border-radius: 12px; + max-width: calc(90vw - 92px); + width: 400px; +} + +form.register input { + appearance: none; + -webkit-appearance: none; + display: block; + border: 0; + font-family: Poppins, Arial, Helvetica, sans-serif; + font-size: 1rem; + background-color: var(--btn-secondary); + border: none; + border-radius: 4px; + padding: 12px; + color: var(--text); + width: calc(100% - 24px); + margin-bottom: 12px; +} + +form.register input::placeholder { + color: var(--text-secondary); +} + +form.register input:focus { + background-color: #fff; + color: var(--btn-secondary); + transition: 200ms; + outline: none; +} + +form.register button { + appearance: none; + -webkit-appearance: none; + display: block; + border: 0; + border-radius: 4px; + font-family: Poppins, Arial, Helvetica, sans-serif; + font-size: 1rem; + color: var(--text); + padding: 12px; + background: var(--btn); + cursor: pointer; + width: 100%; +} + +form.register .login { + text-decoration: none; +} + +form.register .login button { + background: var(--btn-secondary); + margin-top: 18px; +} + +footer { + margin-top: 23px; +} + +@keyframes banner-notice { + 0% {top: -150px} + 20% {top: 35px} + 80% {top: 35px} + 100% {top: -150px} +} +.banner-notice { + display: flex; + justify-content: center; + position: fixed; + top: -150px; + width: 100%; + animation: banner-notice 5s; +} +.banner-notice div { + padding: 4px 36px; + border-radius: 5px; + z-index: 3; +} +.banner-notice.error div { + background: #A9375B; +} \ No newline at end of file diff --git a/src/routers/account.js b/src/routers/account.js index 3930d56..d8a5895 100644 --- a/src/routers/account.js +++ b/src/routers/account.js @@ -211,6 +211,58 @@ router.post('/login', async (request, response) => { response.redirect('/account'); }); +router.get('/register', async (request, response) => { + const renderData = { + layout: 'main', + locale: util.getLocale(request.locale.region, request.locale.language), + localeString: request.locale.toString(), + error: request.cookies.error, + email: request.cookies.email, + username: request.cookies.username, + mii_name: request.cookies.mii_name, + }; + + response.clearCookie('error'); + response.clearCookie('email'); + response.clearCookie('username'); + response.clearCookie('mii_name'); + + response.render('account_register', renderData); +}); + +router.post('/register', async (request, response) => { + const { email, username, mii_name, password, password_confirm } = request.body; + + response.cookie('email', email, { domain: '.pretendo.network' }); + response.cookie('username', username, { domain: '.pretendo.network' }); + response.cookie('mii_name', mii_name, { domain: '.pretendo.network' }); + + const apiResponse = await util.apiPostGetRequest('/v1/register', {}, { + email, username, mii_name, password, password_confirm + }); + + if (apiResponse.statusCode !== 200) { + response.cookie('error', apiResponse.body.error, { domain: '.pretendo.network' }); + return response.redirect('/account/register'); + } + + const tokens = apiResponse.body; + + response.cookie('refresh_token', tokens.refresh_token, { domain: '.pretendo.network' }); + response.cookie('access_token', tokens.access_token, { domain: '.pretendo.network' }); + response.cookie('token_type', tokens.token_type, { domain: '.pretendo.network' }); + + response.clearCookie('error'); + response.clearCookie('email'); + response.clearCookie('username'); + response.clearCookie('mii_name'); + + response.redirect('/account'); +}); + + +https://cdn.pretendo.cc/mii/1730592963/standard.tga + router.get('/connect/discord', async (request, response) => { let tokens; try { diff --git a/views/account_register.handlebars b/views/account_register.handlebars new file mode 100644 index 0000000..ad74278 --- /dev/null +++ b/views/account_register.handlebars @@ -0,0 +1,47 @@ + + +
+ + {{> header}} + + +
+

Register

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+ + {{> footer }} + +
+ +{{#if error}} + +{{/if}} \ No newline at end of file From 3da33fa3d2e70af235ddd55ebdb6f6c63864f1c0 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Dec 2021 09:31:32 -0500 Subject: [PATCH 11/15] removed random string? --- src/routers/account.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/routers/account.js b/src/routers/account.js index d8a5895..7554d71 100644 --- a/src/routers/account.js +++ b/src/routers/account.js @@ -29,8 +29,8 @@ router.get('/', async (request, response) => { }; // Reset message cookies - response.clearCookie('linked'); - response.clearCookie('error'); + response.clearCookie('linked', { domain: '.pretendo.network' }); + response.clearCookie('error', { domain: '.pretendo.network' }); // Attempt to get user data let apiResponse = await util.apiGetRequest('/v1/user', { @@ -183,7 +183,7 @@ router.get('/login', async (request, response) => { error: request.cookies.error }; - response.clearCookie('error'); + response.clearCookie('error', { domain: '.pretendo.network' }); response.render('account_login', renderData); }); @@ -222,10 +222,10 @@ router.get('/register', async (request, response) => { mii_name: request.cookies.mii_name, }; - response.clearCookie('error'); - response.clearCookie('email'); - response.clearCookie('username'); - response.clearCookie('mii_name'); + response.clearCookie('error', { domain: '.pretendo.network' }); + response.clearCookie('email', { domain: '.pretendo.network' }); + response.clearCookie('username', { domain: '.pretendo.network' }); + response.clearCookie('mii_name', { domain: '.pretendo.network' }); response.render('account_register', renderData); }); @@ -252,17 +252,14 @@ router.post('/register', async (request, response) => { response.cookie('access_token', tokens.access_token, { domain: '.pretendo.network' }); response.cookie('token_type', tokens.token_type, { domain: '.pretendo.network' }); - response.clearCookie('error'); - response.clearCookie('email'); - response.clearCookie('username'); - response.clearCookie('mii_name'); + response.clearCookie('error', { domain: '.pretendo.network' }); + response.clearCookie('email', { domain: '.pretendo.network' }); + response.clearCookie('username', { domain: '.pretendo.network' }); + response.clearCookie('mii_name', { domain: '.pretendo.network' }); response.redirect('/account'); }); - -https://cdn.pretendo.cc/mii/1730592963/standard.tga - router.get('/connect/discord', async (request, response) => { let tokens; try { From 135ba1064d1916581a621e8602bbe6e84f3c2e7f Mon Sep 17 00:00:00 2001 From: Ash Monty Date: Sun, 12 Dec 2021 17:42:33 +0100 Subject: [PATCH 12/15] feat(styles): add mobile layout, minor changes --- locales/US_en.json | 5 + public/assets/css/main.css | 179 +++++++++++++++++++++++++------ src/routers/home.js | 23 ++++ views/home.handlebars | 10 +- views/partials/footer.handlebars | 2 +- 5 files changed, 181 insertions(+), 38 deletions(-) diff --git a/locales/US_en.json b/locales/US_en.json index 2f28f14..c058455 100644 --- a/locales/US_en.json +++ b/locales/US_en.json @@ -155,6 +155,11 @@ "caption": "Research on Nintendo datastructures", "picture": "https://cdn.discordapp.com/avatars/186572995848830987/b55c0d4e7bfd792edf0689f83a25d8ea.png?size=128", "github": "https://github.com/Kinnay" + }, + { + "name": "The localizers", + "caption": "Localizing, duh.", + "picture": "https://via.placeholder.com/128" } ] }, diff --git a/public/assets/css/main.css b/public/assets/css/main.css index 7f9a80e..c81191e 100644 --- a/public/assets/css/main.css +++ b/public/assets/css/main.css @@ -437,7 +437,7 @@ section.team { .card { width: calc(100% - 54px); min-width: 100px; - max-width: 460px; + max-width: 460px; padding: 18px 27px; display: grid; grid-template-columns: 110px 1fr; @@ -485,7 +485,6 @@ section.team { section.team-helpers { position: relative; margin-top: 160px; - margin-bottom: 160px; } section.team-helpers .text { max-width: 504px; @@ -493,7 +492,7 @@ section.team-helpers .text { } section.team-helpers .team-helpers-cards { display: inline-grid; - grid-template-columns: repeat(5, 1fr); + grid-template-columns: repeat(6, 1fr); grid-gap: 20px; margin-right: 20px; color: var(--text-secondary); @@ -531,10 +530,11 @@ section.team-helpers .helper-card { padding: 14px 24px; background: #16192D; border-radius: 12px; - animation: scrollHelpersRTL 25s linear infinite; + animation: scrollHelpersRTL 30s linear infinite; + min-width: 480px; } section.team-helpers .row.second .helper-card { - animation: scrollHelpersLTR 25s linear infinite; + animation: scrollHelpersLTR 30s linear infinite; } section.team-helpers .helper-card:hover { background: #252A51; @@ -545,12 +545,12 @@ section.team-helpers .helper-card:hover { transform: translatex(0%); } 100% { - transform: translateX(calc( ( ( 100% + 20px ) * -5 ) + -7px)); + transform: translateX(calc( ( ( 100% + 20px ) * -6 ) + -7px)); /* Don't question this, it just works. */ } } @keyframes scrollHelpersLTR { 0% { - transform: translateX(calc( ( ( 100% + 20px ) * -5 ) + -7px)); + transform: translateX(calc( ( ( 100% + 20px ) * -6 ) + -7px)); } 100% { transform: translatex(0%); @@ -597,10 +597,6 @@ section.team-helpers .row.first .team-helpers-cards.repeat.first a:nth-child(3){ position: relative; left: 5px; } -section.team-helpers .row.second .team-helpers-cards.repeat.first a.special, -section.team-helpers .row.second .team-helpers-cards.repeat.second a:nth-child(1){ - left: calc(-250% - 45px); -} section.update-signup { position: relative; @@ -610,6 +606,7 @@ section.update-signup { justify-items: center; align-items: center; text-align: center; + margin-top: 160px; padding-top: 240px; padding-bottom: 300px; } @@ -625,6 +622,7 @@ section.update-signup .text { section.update-signup .floating-serverjoin { display: grid; grid-template-columns: repeat(2, auto); + gap: 18px; width: 100%; max-width: 576px; @@ -648,6 +646,7 @@ section.update-signup .floating-serverjoin a { padding: 9px 18px; border-radius: 5px; width: fit-content; + height: fit-content; } section.update-signup div.circle { display: block; @@ -793,7 +792,7 @@ footer { width: 100%; display: grid; grid-template-columns: repeat(3, fit-content(100%)) 1fr; - gap: 148px; + gap: 7.7vw; color: var(--text-secondary); margin-top: 120px; position: relative; @@ -893,11 +892,6 @@ footer div.discord-server-card svg { @media screen and (max-width: 900px) { - h1.dot:not([data-title-suffix]):after, h2.dot:not([data-title-suffix]):after { - width: 0.5rem; - height: 0.5rem; - } - .all-progress-lists { grid-template-columns: 100%; } @@ -925,12 +919,6 @@ footer div.discord-server-card svg { .hero-image { display: none; } - .hero .title { - font-size: 2.5rem; - } - .hero .subtitle { - font-size: 1.5rem; - } .hero .text { width: 100%; } @@ -968,9 +956,6 @@ footer div.discord-server-card svg { padding: 50px 20px; border-radius: 10px; } - .sect .title { - font-size: 2rem; - } .sect .text { width: 100%; } @@ -979,21 +964,57 @@ footer div.discord-server-card svg { font-size: 1.1rem; } + + section.showcase { + margin-top: 0; + } + section.showcase .grid { + grid-template-columns: 1fr; + grid-template-rows: repeat(3, 1fr); + } + + section.team, + section.team-helpers { + margin-top: 100px; + } .team .team-top .text { width: 100%; } - .team-cards .card { /* I needed a little bit of a higher priority */ - grid-template-columns: 60px 1fr; - width: 100vw; - margin-left: -5vw; - margin-right: -2.5vw; - border-radius: 0; + section.team-helpers .sect-top { + text-align: center; + } + section.team-helpers .sect-top .text { + width: 100%; + max-width: none; + } + section.team-helpers .animation-wrapper { + transform: none; + overflow-x: visible; + margin-left: -10vw; /* Fixes the loop being visible */ + } + section.team-helpers .animation-wrapper::after { + background: none; } + section.update-signup { + margin-top: 0; + padding-top: 90px; + padding-bottom: 90px; + } footer { margin-top: 100px; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, fit-content(100%)); + } + footer div { + justify-self: center; + } + footer div.discord-server-card { + grid-column: 1 / span 4; + width: calc(100% - 126px); + justify-self: normal; } .text { @@ -1003,6 +1024,87 @@ footer div.discord-server-card svg { } @media screen and (max-width: 580px) { + + .sect .title { + font-size: 2rem; + } + h1.dot:not([data-title-suffix]):after, h2.dot:not([data-title-suffix]):after { + width: 0.5rem; + height: 0.5rem; + } + + .hero .title { + font-size: 2.5rem; + } + .hero .subtitle { + font-size: 1.5rem; + } + + section.showcase { + padding: 160px 0; + } + section.showcase p.text { + margin-bottom: 82px; + } + section.showcase .grid .item { + padding: 24px 24px; + } + + .team .team-top { + text-align: left; + } + .team-cards .card { + grid-template-columns: 60px 1fr; + width: calc(95vw - 36px); + margin-left: -1vw; + margin-right: -1vw; + padding: 18px; + max-width: none; + } + + section.team-helpers .team-helpers-cards { + grid-gap: 12px; + margin-right: 12px; + } + section.team-helpers .animation-wrapper .helper-card { + padding: 7px 18px; + } + + section.team-helpers .animation-wrapper .row.second { + margin-top: 12px; + } + section.team-helpers .helper-card { + animation: scrollHelpersRTLMobile 25s linear infinite; + } + section.team-helpers .row.second .helper-card { + animation: scrollHelpersLTRMobile 25s linear infinite; + } + @keyframes scrollHelpersRTLMobile { + 0% { + transform: translatex(0%); + } + 100% { + transform: translateX(calc( ( ( 100% + 12px ) * -6 ) + -6px)); + } + } + @keyframes scrollHelpersLTRMobile { + 0% { + transform: translateX(calc( ( ( 100% + 12px ) * -6 ) + -6px)); + } + 100% { + transform: translatex(0%); + } + } + + section.update-signup .floating-serverjoin { + width: calc(100% - 36px); + grid-template-columns: 1fr; + grid-template-rows: repeat(2, fit-content(100%)); + } + section.update-signup .floating-serverjoin > * { + margin: auto !important; + } + .selected-locale .locale-names { display: none; } @@ -1022,6 +1124,19 @@ footer div.discord-server-card svg { right: 12px; } + footer { + grid-template-columns: 1fr; + grid-template-rows: repeat(4, fit-content(100%)); + } + footer div { + justify-self: start; + } + footer div.discord-server-card { + grid-column: 1 / span 1; + padding: 30px; + width: calc(100% - 60px); + } + } @media screen and (max-width: 480px) { diff --git a/src/routers/home.js b/src/routers/home.js index d956afc..3985122 100644 --- a/src/routers/home.js +++ b/src/routers/home.js @@ -12,12 +12,35 @@ router.get('/', async (request, response) => { const cache = await getTrelloCache(); + // Builds the arrays of people for the special thanks section + + // Shuffles the special thanks people + let specialThanksPeople = locale.specialThanks.people.slice(); + function shuffleArray(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + } + shuffleArray(specialThanksPeople); + + // Slices the array in half + const specialThanksFirstRow = specialThanksPeople.slice(0, 3); + const specialThanksSecondRow = specialThanksPeople.slice(3, 6); + + // Builds the final array to be sent to the view, and duplicates each row. + specialThanksPeople = { + first: specialThanksFirstRow.concat(specialThanksFirstRow), + second: specialThanksSecondRow.concat(specialThanksSecondRow) + }; + response.render('home', { layout: 'main', featuredFeatureList: cache.sections[0], boards, locale, localeString: reqLocale.toString(), + specialThanksPeople }); }); diff --git a/views/home.handlebars b/views/home.handlebars index 175589a..81bbfec 100644 --- a/views/home.handlebars +++ b/views/home.handlebars @@ -166,7 +166,7 @@
- {{#each locale.specialThanks.people}} + {{#each specialThanksPeople.first}}
@@ -177,7 +177,7 @@ {{/each}}
- {{#each locale.specialThanks.people}} + {{#each specialThanksPeople.first}}
@@ -190,7 +190,7 @@
- {{#each locale.specialThanks.people}} + {{#each specialThanksPeople.second}}
@@ -201,7 +201,7 @@ {{/each}}
- {{#each locale.specialThanks.people}} + {{#each specialThanksPeople.second}}
@@ -212,7 +212,7 @@ {{/each}}
- {{#each locale.specialThanks.people}} + {{#each specialThanksPeople.second}}
diff --git a/views/partials/footer.handlebars b/views/partials/footer.handlebars index 9afd672..26ae647 100644 --- a/views/partials/footer.handlebars +++ b/views/partials/footer.handlebars @@ -28,7 +28,7 @@

Socials

-
Twitter + Twitter Patreon Discord GitHub From f8f651d6415d3de3d94feae16a886d4823617fbe Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Dec 2021 20:48:20 -0500 Subject: [PATCH 13/15] Added Cemu files download --- example.config.json | 3 +- package-lock.json | 14 +++++ package.json | 1 + public/assets/css/account.css | 11 ++++ public/assets/js/account.js | 2 +- src/routers/account.js | 100 ++++++++++++++++++++++++++++++++-- src/util.js | 19 ++++++- views/account.handlebars | 4 +- 8 files changed, 145 insertions(+), 9 deletions(-) diff --git a/example.config.json b/example.config.json index 8a1654d..6e28a91 100644 --- a/example.config.json +++ b/example.config.json @@ -16,5 +16,6 @@ "tester_roles": [ "role id" ] - } + }, + "aes_key": "hex key here" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ce84c29..8c9d79c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "adm-zip": "^0.5.9", "colors": "^1.4.0", "cookie-parser": "^1.4.5", "discord-oauth2": "github:ryanblenis/discord-oauth2", @@ -306,6 +307,14 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/adm-zip": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz", + "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==", + "engines": { + "node": ">=6.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2668,6 +2677,11 @@ "dev": true, "requires": {} }, + "adm-zip": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz", + "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==" + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", diff --git a/package.json b/package.json index 09f8cd3..cb903f0 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "homepage": "https://github.com/PretendoNetwork/website#readme", "dependencies": { + "adm-zip": "^0.5.9", "colors": "^1.4.0", "cookie-parser": "^1.4.5", "discord-oauth2": "github:ryanblenis/discord-oauth2", diff --git a/public/assets/css/account.css b/public/assets/css/account.css index 9e2515b..8122bb6 100644 --- a/public/assets/css/account.css +++ b/public/assets/css/account.css @@ -25,6 +25,17 @@ border-radius: 100%; background: var(--btn-secondary); } +.account-sidebar .user #download-cemu-files { + width: 100%; + padding: 4px 16px; + cursor: pointer; + background: #383f6b; + font-size: 0.9rem; + margin: 8px 0 0; +} +.account-sidebar .user .cemu-warning { + font-size: 0.7rem; +} /* Settings */ .settings-wrapper { diff --git a/public/assets/js/account.js b/public/assets/js/account.js index ceed879..2e6da46 100644 --- a/public/assets/js/account.js +++ b/public/assets/js/account.js @@ -1,5 +1,5 @@ -document.getElementById('remove-discord-connection').addEventListener('click', () => { +document.getElementById('remove-discord-connection')?.addEventListener('click', () => { // TODO: Refresh access token if expired (move this to the backend maybe?) const tokenType = document.cookie.split('; ').find(row => row.startsWith('token_type=')).split('=')[1]; diff --git a/src/routers/account.js b/src/routers/account.js index 7554d71..0af5271 100644 --- a/src/routers/account.js +++ b/src/routers/account.js @@ -1,9 +1,11 @@ const { Router } = require('express'); const crypto = require('crypto'); const DiscordOauth2 = require('discord-oauth2'); +const AdmZip = require('adm-zip'); const util = require('../util'); const config = require('../../config.json'); const router = new Router(); +const aesKey = Buffer.from(config.aes_key, 'hex'); // Create OAuth client const discordOAuth = new DiscordOauth2({ @@ -15,7 +17,7 @@ const discordOAuth = new DiscordOauth2({ router.get('/', async (request, response) => { // Verify the user is logged in - if (!request.cookies.access_token || !request.cookies.refresh_token) { + if (!request.cookies.access_token || !request.cookies.refresh_token || !request.cookies.ph) { return response.redirect('/account/login'); } @@ -191,7 +193,7 @@ router.get('/login', async (request, response) => { router.post('/login', async (request, response) => { const { username, password } = request.body; - const apiResponse = await util.apiPostGetRequest('/v1/login', {}, { + let apiResponse = await util.apiPostGetRequest('/v1/login', {}, { username, password, grant_type: 'password' @@ -208,6 +210,22 @@ router.post('/login', async (request, response) => { response.cookie('access_token', tokens.access_token, { domain : '.pretendo.network' }); response.cookie('token_type', tokens.token_type, { domain : '.pretendo.network' }); + apiResponse = await util.apiGetRequest('/v1/user', { + 'Authorization': `${tokens.token_type} ${tokens.access_token}` + }); + + const account = apiResponse.body; + + const hashedPassword = util.nintendoPasswordHash(password, account.pid); + const hashedPasswordBuffer = Buffer.from(hashedPassword, 'hex'); + + const cipher = crypto.createCipheriv('aes-256-cbc', aesKey, Buffer.alloc(16)); + + let encryptedBody = cipher.update(hashedPasswordBuffer); + encryptedBody = Buffer.concat([encryptedBody, cipher.final()]); + + response.cookie('ph', encryptedBody.toString('hex'), { domain: '.pretendo.network' }); + response.redirect('/account'); }); @@ -304,9 +322,9 @@ router.get('/connect/discord', async (request, response) => { const tokens = apiResponse.body; - response.cookie('refresh_token', tokens.refresh_token, { domain : '.pretendo.network' }); - response.cookie('access_token', tokens.access_token, { domain : '.pretendo.network' }); - response.cookie('token_type', tokens.token_type, { domain : '.pretendo.network' }); + response.cookie('refresh_token', tokens.refresh_token, { domain: '.pretendo.network' }); + response.cookie('access_token', tokens.access_token, { domain: '.pretendo.network' }); + response.cookie('token_type', tokens.token_type, { domain: '.pretendo.network' }); apiResponse = await util.apiPostGetRequest('/v1/connections/add/discord', { 'Authorization': `${tokens.token_type} ${tokens.access_token}` @@ -330,4 +348,76 @@ router.get('/connect/discord', async (request, response) => { response.cookie('linked', 'Discord', { domain: '.pretendo.network' }).redirect('/account'); }); +router.get('/online-files', async (request, response) => { + + // Verify the user is logged in + if (!request.cookies.access_token || !request.cookies.refresh_token|| !request.cookies.ph) { + return response.redirect('/account/login'); + } + + // Attempt to get user data + let apiResponse = await util.apiGetRequest('/v1/user', { + 'Authorization': `${request.cookies.token_type} ${request.cookies.access_token}` + }); + + if (apiResponse.statusCode !== 200) { + // Assume expired, refresh and retry request + apiResponse = await util.apiPostGetRequest('/v1/login', {}, { + refresh_token: request.cookies.refresh_token, + grant_type: 'refresh_token' + }); + + if (apiResponse.statusCode !== 200) { + // TODO: Error message + return response.status(apiResponse.statusCode).json({ + error: 'Bad' + }); + } + + const tokens = apiResponse.body; + + response.cookie('refresh_token', tokens.refresh_token, { domain: '.pretendo.network' }); + response.cookie('access_token', tokens.access_token, { domain: '.pretendo.network' }); + response.cookie('token_type', tokens.token_type, { domain: '.pretendo.network' }); + + apiResponse = await util.apiGetRequest('/v1/user', { + 'Authorization': `${tokens.token_type} ${tokens.access_token}` + }); + } + + // If still failed, something went horribly wrong + if (apiResponse.statusCode !== 200) { + // TODO: Error message + return response.status(apiResponse.statusCode).json({ + error: 'Bad' + }); + } + + const account = apiResponse.body; + + const decipher = crypto.createDecipheriv('aes-256-cbc', aesKey, Buffer.alloc(16)); + + let decryptedPasswordHash = decipher.update(Buffer.from(request.cookies.ph, 'hex')); + decryptedPasswordHash = Buffer.concat([decryptedPasswordHash, decipher.final()]); + + let accountDat = 'AccountInstance_00000000\n'; + accountDat += `AccountPasswordCache=${decryptedPasswordHash.toString('hex')}\n`; + accountDat += 'IsPasswordCacheEnabled=1\n'; + accountDat += `AccountId=${account.username}\n`; + accountDat += 'PersistentId=80000001'; + + const onlineFiles = new AdmZip(); + + onlineFiles.addFile('mlc01/usr/save/system/act/80000001/account.dat', Buffer.from(accountDat)); // Minimal account.dat + onlineFiles.addFile('otp.bin', Buffer.alloc(0x400)); // nulled OTP + onlineFiles.addFile('seeprom.bin', Buffer.alloc(0x200)); // nulled SEEPROM + + response.writeHead(200, { + 'Content-Disposition': 'attachment; filename="Online Files.zip"', + 'Content-Type': 'application/zip', + }); + + response.end(onlineFiles.toBuffer()); +}); + module.exports = router; \ No newline at end of file diff --git a/src/util.js b/src/util.js index 5ff9a1d..5ad2251 100644 --- a/src/util.js +++ b/src/util.js @@ -1,5 +1,6 @@ const fs = require('fs-extra'); const got = require('got'); +const crypto = require('crypto'); const logger = require('./logger'); function fullUrl(request) { @@ -52,10 +53,26 @@ function apiDeleteGetRequest(path, headers, json) { }); } +function nintendoPasswordHash(password, pid) { + const pidBuffer = Buffer.alloc(4); + pidBuffer.writeUInt32LE(pid); + + const unpacked = Buffer.concat([ + pidBuffer, + Buffer.from('\x02\x65\x43\x46'), + Buffer.from(password) + ]); + + const hashed = crypto.createHash('sha256').update(unpacked).digest().toString('hex'); + + return hashed; +} + module.exports = { fullUrl, getLocale, apiGetRequest, apiPostGetRequest, - apiDeleteGetRequest + apiDeleteGetRequest, + nintendoPasswordHash }; \ No newline at end of file diff --git a/views/account.handlebars b/views/account.handlebars index ea5ca07..fe06330 100644 --- a/views/account.handlebars +++ b/views/account.handlebars @@ -9,7 +9,9 @@

{{account.mii.name}}

-

PNID: {{account.username}}

+

PNID: {{account.username}}

+ Download account files +

(will not work with Nintendo Network)

From 1e12f6a84ba450d276908a884004dbcb74518903 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Dec 2021 20:50:57 -0500 Subject: [PATCH 14/15] temp remove docs links, not done --- views/partials/footer.handlebars | 42 +++++++++++++++----------------- views/partials/header.handlebars | 3 +-- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/views/partials/footer.handlebars b/views/partials/footer.handlebars index 9afd672..b85d176 100644 --- a/views/partials/footer.handlebars +++ b/views/partials/footer.handlebars @@ -1,7 +1,6 @@ \ No newline at end of file diff --git a/views/partials/header.handlebars b/views/partials/header.handlebars index 012690b..8c5f4e6 100644 --- a/views/partials/header.handlebars +++ b/views/partials/header.handlebars @@ -28,7 +28,7 @@ {{ localeHelper locale "nav" "about" }} {{ localeHelper locale "nav" "faq" }} {{ localeHelper locale "nav" "credits" }} - {{ localeHelper locale "nav" "docs"}} + {{ localeHelper locale "nav" "docs"}} {{ localeHelper locale "nav" "progress"}} {{ localeHelper locale "nav" "blog" }} @@ -118,5 +118,4 @@
- From 31a675e1cec7e063c6e1ebc11060e7bf8c8214c5 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 12 Dec 2021 20:53:11 -0500 Subject: [PATCH 15/15] Changed what we do section text --- views/home.handlebars | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/views/home.handlebars b/views/home.handlebars index 175589a..0a680b0 100644 --- a/views/home.handlebars +++ b/views/home.handlebars @@ -116,18 +116,18 @@
-

Juxtaposition

-

A Miiverse replacement

+

Game Servers

+

Bringing back your favorite games and content using custom servers

Juxtaposition

-

A Miiverse replacement

+

A re-imagining of Miiverse, as if it were made in the modern era

-

Juxtaposition

-

A Miiverse replacement

+

Cemu Support

+

Play your favorite Wii U titles even without a console!