Merge pull request #88 from PretendoNetwork/dev

Dev
This commit is contained in:
Jonathan Barrow 2021-12-12 20:56:57 -05:00 committed by GitHub
commit 7626989ca2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 4248 additions and 189 deletions

View File

@ -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     。
゚   .   . ,    .  .
```

75
docs/en-US/welcome.md Normal file
View File

@ -0,0 +1,75 @@
# 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())
```

73
docs/it-IT/welcome.md Normal file
View File

@ -0,0 +1,73 @@
# 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())
```

View File

@ -16,5 +16,6 @@
"tester_roles": [
"role id"
]
}
},
"aes_key": "hex key here"
}

View File

@ -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."
}
}

View File

@ -2,6 +2,7 @@
"nav": {
"about": "About",
"faq": "FAQ",
"docs": "Docs",
"credits": "Credits",
"progress": "Progress",
"blog": "Blog"
@ -154,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"
}
]
},
@ -172,5 +178,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."
}
}

2460
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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",

View File

@ -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 {

View File

@ -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;

View File

@ -0,0 +1,221 @@
html,
body {
background: #131730;
}
a.logo-link {
margin: auto;
margin-left: 36px;
height: 40px;
text-decoration: none;
}
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%));
height: 100vh;
}
.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;
min-height: 100%;
}
.docs-wrapper .sidebar .section {
display: flex;
flex-flow: column;
width: 200px;
margin-left: 138px;
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;
}
.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;
}
}

View File

@ -1,91 +1,137 @@
/**
* Adapted from Shades of Purple Theme for Highlightjs.
*
* @author (c) Ahmad Awais <https://twitter.com/mrahmadawais/>
* @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;
}
pre code.hljs {
display: block;
overflow-x: auto;
padding: 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;
}

View File

@ -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;
}
@ -89,6 +93,7 @@ header nav a {
.locale-dropdown {
margin-left: auto;
z-index: 2;
height: 45px;
}
/* Misc */
@ -297,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;
@ -348,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;
}
@ -379,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;
@ -424,6 +482,186 @@ section.team {
color: var(--text-secondary);
}
section.team-helpers {
position: relative;
margin-top: 160px;
}
section.team-helpers .text {
max-width: 504px;
margin-bottom: 132px;
}
section.team-helpers .team-helpers-cards {
display: inline-grid;
grid-template-columns: repeat(6, 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 30s linear infinite;
min-width: 480px;
}
section.team-helpers .row.second .helper-card {
animation: scrollHelpersLTR 30s linear infinite;
}
section.team-helpers .helper-card:hover {
background: #252A51;
transition: 200ms;
}
@keyframes scrollHelpersRTL {
0% {
transform: translatex(0%);
}
100% {
transform: translateX(calc( ( ( 100% + 20px ) * -6 ) + -7px)); /* Don't question this, it just works. */
}
}
@keyframes scrollHelpersLTR {
0% {
transform: translateX(calc( ( ( 100% + 20px ) * -6 ) + -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.update-signup {
position: relative;
width: 100%;
display: flex;
flex-flow: column;
justify-items: center;
align-items: center;
text-align: center;
margin-top: 160px;
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);
gap: 18px;
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;
height: 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;
@ -435,10 +673,14 @@ section.team {
display: grid;
grid-template-columns: auto 1fr;
grid-gap: 20px;
margin-top: 22px;
}
.feature-progress-chart {
max-width: 100px;
}
.feature-progress-chart canvas.percentage-chart {
pointer-events: none; /* Fixes issue #48 */
}
.feature-list-wrapper h3 {
margin: 0;
}
@ -547,10 +789,85 @@ section.team {
/* Footer */
footer {
text-align: center;
width: 100%;
display: grid;
grid-template-columns: repeat(3, fit-content(100%)) 1fr;
gap: 7.7vw;
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) {
@ -575,11 +892,6 @@ footer {
@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%;
}
@ -607,12 +919,6 @@ footer {
.hero-image {
display: none;
}
.hero .title {
font-size: 2.5rem;
}
.hero .subtitle {
font-size: 1.5rem;
}
.hero .text {
width: 100%;
}
@ -650,9 +956,6 @@ footer {
padding: 50px 20px;
border-radius: 10px;
}
.sect .title {
font-size: 2rem;
}
.sect .text {
width: 100%;
}
@ -661,21 +964,57 @@ footer {
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 {
@ -685,6 +1024,87 @@ footer {
}
@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;
}
@ -704,6 +1124,19 @@ footer {
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) {

View File

@ -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;
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>

After

Width:  |  Height:  |  Size: 314 B

View File

@ -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];

View File

@ -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');
}
@ -29,8 +31,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 +185,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);
});
@ -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,71 @@ 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');
});
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', { 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);
});
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', { 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');
});
@ -255,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}`
@ -281,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;

78
src/routers/docs.js Normal file
View File

@ -0,0 +1,78 @@
const { Router } = require('express');
const util = require('../util');
const router = new Router();
const fs = require('fs');
const path = require('path');
const marked = require('marked');
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/search', {
layout: 'main',
locale,
localeString,
currentPage: request.params.slug,
});
});
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 page from the URL
const pageName = request.params.slug;
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;
}
let content;
// 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 <iframe />
content = content
.replace(/(?<!`)\[yt-iframe]\(/g, '<div class="aspectratio-fallback"><iframe src="https://www.youtube-nocookie.com/embed/')
.replace(/(?<=<iframe src="https:\/\/www\.youtube-nocookie\.com\/embed\/.{11})\)/g, '" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>');
// 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,
localeString,
content,
currentPage: request.params.slug,
missingInLocale,
showQuickLinks
});
});
module.exports = router;

View File

@ -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
});
});

View File

@ -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();
@ -23,6 +25,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'),
@ -45,7 +48,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 +63,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',
@ -72,6 +75,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);
@ -116,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;
}
}
}
}));

View File

@ -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
};

View File

@ -9,7 +9,9 @@
<div class="user">
<img src="{{account.mii.image_url}}" class="mii" />
<p class="miiname">{{account.mii.name}}</p>
<p class="username">PNID: {{account.username}}</p>
<p class="username" value="{{account.username}}">PNID: {{account.username}}</p>
<a class="button secondary" id="download-cemu-files" href="/account/online-files" download>Download account files</a>
<p class="cemu-warning">(will not work with Nintendo Network)</p>
</div>
</div>

View File

@ -0,0 +1,47 @@
<link rel="stylesheet" href="/assets/css/register.css" />
<div class="wrapper">
{{> header}}
<div class="register-wrapper">
<h1 class="title dot">Register</h1>
<form action="/account/register" method="post" class="register">
<div>
<input name="email" id="email" type="email" placeholder="Email" value="{{ email }}" required>
</div>
<div>
<input name="username" id="username" placeholder="Username" value="{{ username }}" minlength=6 maxlength=16 required>
</div>
<div>
<input name="mii_name" id="mii_name" placeholder="Mii Name (Max 10 characters)" value="{{ mii_name }}" maxlength=10 required>
</div>
<div>
<input name="password" id="password" type="password" placeholder="Password" autocomplete="new-password" required>
</div>
<div>
<input name="password_confirm" id="password_confirm" type="password" placeholder="Confirm Password" required>
</div>
<div>
<button type="submit">Register</button>
</div>
<div>
<a href="/account/login" class="login">
<button type="button">Already have an account?</button>
</a>
</div>
</form>
</div>
{{> footer }}
</div>
{{#if error}}
<div class="banner-notice error">
<div>
<p>{{ error }}</p>
</div>
</div>
{{/if}}

View File

@ -7,8 +7,8 @@
<div class="progress-hero">
<div class="hero-meta reduced-margin">
<svg xmlns="http://www.w3.org/2000/svg" width="48.87" height="71.093" viewBox="0 0 48.87 71.093"><g id="XMLID_6_" transform="translate(0)"><path id="XMLID_15_" d="M69.581,29.593c-2.029,1.068-.249,4.129,1.78,3.061,5.162-2.67,11.463-2.6,16.981-1.1,4.735,1.282,9.5,3.845,12.246,8.045,1.246,1.922,4.307.142,3.061-1.78C96.921,27.386,80.3,24.04,69.581,29.593Z" transform="translate(-60.112 -20.086)" fill="#9d6ff3"/><path id="XMLID_14_" d="M103.359,21.045c-3.951-6.159-10.751-10-17.657-11.89C77.763,6.948,68.721,7.019,61.281,10.9c-2.029,1.068-.249,4.129,1.78,3.061,6.586-3.453,14.667-3.311,21.644-1.388,5.981,1.638,12.1,4.913,15.521,10.252C101.507,24.783,104.569,23,103.359,21.045Z" transform="translate(-54.766 -7.693)" fill="#9d6ff3"/><path id="XMLID_9_" d="M65.995,47.8a20.7,20.7,0,0,0-12.958,4.45H47.27a2.579,2.579,0,0,0-2.67,2.456v47.239a2.763,2.763,0,0,0,2.67,2.67h5.838a2.639,2.639,0,0,0,2.528-2.67V87.564A21.228,21.228,0,1,0,65.995,47.8Zm0,33.178a12,12,0,1,1,12-12A12,12,0,0,1,65.995,80.978Z" transform="translate(-44.6 -33.522)" fill="#9d6ff3"/></g></svg>
<h1 class="title dot">{{ locale.blogPage.title }}</h1>
<p class="text">{{{ locale.blogPage.description }}}</p>
<h1 class="title dot">{{ localeHelper locale "blogPage" "title" }}</h1>
<p class="text">{{{ localeHelper locale "blogPage" "description" }}}</p>
</div>
</div>

View File

@ -29,7 +29,7 @@
</div>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/default.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>
<link rel="stylesheet" href="/assets/css/highlightjs.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
<script>hljs.highlightAll();</script>

View File

@ -0,0 +1,72 @@
<link rel="stylesheet" href="/assets/css/documentation.css" />
<div class="docs-wrapper">
<a href="/" class="logo-link">
<svg xmlns="http://www.w3.org/2000/svg" width="120" height="39.876">
<g id="logo_type" data-name="logo type" transform="translate(-553 -467)">
<g id="logo" transform="translate(553 467)">
<rect id="XMLID_158_" width="39.876" height="39.876" fill="#9d6ff3" opacity="0" />
<g id="XMLID_6_" transform="translate(8.222 1.418)">
<path id="XMLID_15_"
d="M69.149,28.312c-1.051.553-.129,2.139.922,1.585a12.365,12.365,0,0,1,8.794-.571,10.829,10.829,0,0,1,6.342,4.166c.645,1,2.231.074,1.585-.922C83.308,27.169,74.7,25.436,69.149,28.312Z"
transform="translate(-64.246 -23.389)" fill="#9d6ff3" />
<path id="XMLID_14_"
d="M82.64,14.608A15.565,15.565,0,0,0,73.5,8.45a17.535,17.535,0,0,0-12.647.9c-1.051.553-.129,2.139.922,1.585,3.411-1.788,7.6-1.714,11.209-.719,3.1.848,6.268,2.544,8.038,5.309C81.681,16.543,83.267,15.622,82.64,14.608Z"
transform="translate(-57.476 -7.693)" fill="#9d6ff3" />
<path id="XMLID_9_"
d="M55.68,47.8a10.719,10.719,0,0,0-6.71,2.3H45.983A1.336,1.336,0,0,0,44.6,51.376V75.84a1.431,1.431,0,0,0,1.383,1.383h3.023a1.367,1.367,0,0,0,1.309-1.383V68.392A10.993,10.993,0,1,0,55.68,47.8Zm0,17.182a6.213,6.213,0,1,1,6.213-6.213A6.216,6.216,0,0,1,55.68,64.982Z"
transform="translate(-44.6 -40.406)" fill="#9d6ff3" />
</g>
</g>
<text id="Pretendo" transform="translate(593 492)" fill="#fff" font-size="17"
font-family="Poppins-Bold, Poppins" font-weight="700">
<tspan x="0" y="0">Pretendo</tspan>
</text>
</g>
</svg>
</a>
{{> header}}
{{> docs-sidebar}}
<div class="content">
<div class="content-inner">
{{#if missingInLocale}}
<p class="missing-in-locale-notice">{{ localeHelper locale "docs" "missingInLocale" }}</p>
{{/if}}
{{#if showQuickLinks}}
<h1>Quick links</h1>
<div class="quick-links-grid">
<a href="/docs/troubleshoot-errors">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book" class="svg-inline--fa fa-book fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"></path></svg>
<div>
<p class="header">Got an error code?</p>
<p>Search</p>
</div>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>
</a>
<a href="/docs/beans">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book" class="svg-inline--fa fa-book fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"></path></svg>
<div>
<p class="header">Nintendo be like</p>
<p>Here's your DMCA and C&D</p>
</div>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>
</a>
</div>
{{/if}}
{{{ content }}}
</div>
</div>
</div>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js"></script>
<link rel="stylesheet" href="/assets/css/highlightjs.css">
<script>hljs.highlightAll();</script>

View File

@ -0,0 +1,40 @@
<link rel="stylesheet" href="/assets/css/documentation.css" />
<div class="docs-wrapper">
<a href="/" class="logo-link">
<svg xmlns="http://www.w3.org/2000/svg" width="120" height="39.876">
<g id="logo_type" data-name="logo type" transform="translate(-553 -467)">
<g id="logo" transform="translate(553 467)">
<rect id="XMLID_158_" width="39.876" height="39.876" fill="#9d6ff3" opacity="0" />
<g id="XMLID_6_" transform="translate(8.222 1.418)">
<path id="XMLID_15_"
d="M69.149,28.312c-1.051.553-.129,2.139.922,1.585a12.365,12.365,0,0,1,8.794-.571,10.829,10.829,0,0,1,6.342,4.166c.645,1,2.231.074,1.585-.922C83.308,27.169,74.7,25.436,69.149,28.312Z"
transform="translate(-64.246 -23.389)" fill="#9d6ff3" />
<path id="XMLID_14_"
d="M82.64,14.608A15.565,15.565,0,0,0,73.5,8.45a17.535,17.535,0,0,0-12.647.9c-1.051.553-.129,2.139.922,1.585,3.411-1.788,7.6-1.714,11.209-.719,3.1.848,6.268,2.544,8.038,5.309C81.681,16.543,83.267,15.622,82.64,14.608Z"
transform="translate(-57.476 -7.693)" fill="#9d6ff3" />
<path id="XMLID_9_"
d="M55.68,47.8a10.719,10.719,0,0,0-6.71,2.3H45.983A1.336,1.336,0,0,0,44.6,51.376V75.84a1.431,1.431,0,0,0,1.383,1.383h3.023a1.367,1.367,0,0,0,1.309-1.383V68.392A10.993,10.993,0,1,0,55.68,47.8Zm0,17.182a6.213,6.213,0,1,1,6.213-6.213A6.216,6.216,0,0,1,55.68,64.982Z"
transform="translate(-44.6 -40.406)" fill="#9d6ff3" />
</g>
</g>
<text id="Pretendo" transform="translate(593 492)" fill="#fff" font-size="17"
font-family="Poppins-Bold, Poppins" font-weight="700">
<tspan x="0" y="0">Pretendo</tspan>
</text>
</g>
</svg>
</a>
{{> header}}
{{> docs-sidebar}}
<div class="content">
<div class="content-inner">
<div class="card"></div>
</div>
</div>
</div>

View File

@ -5,15 +5,15 @@
<section class="hero">
<div class="hero-meta">
<h3 class="subtitle">{{ locale.hero.subtitle }}</h3>
<h1 class="title dot" {{#if locale.hero.titleSuffix}}data-title-suffix="{{locale.hero.titleSuffix}}"{{/if}}>{{ locale.hero.title }}</h1>
<h3 class="subtitle">{{ localeHelper locale "hero" "subtitle" }}</h3>
<h1 class="title dot" {{#if locale.hero.titleSuffix}}data-title-suffix="{{locale.hero.titleSuffix}}"{{/if}}>{{ localeHelper locale "hero" "title" }}</h1>
<p class="text">
{{ locale.hero.text }}
{{ localeHelper locale "hero" "text" }}
</p>
<div class="buttons">
<a href="/#about" class="do-button-margin">
<button class="button primary">
{{ locale.hero.buttons.readMore }}
{{ localeHelper locale "hero" "buttons" "readMore" }}
</button>
</a>
<a href="https://invite.gg/pretendo" class="do-button-margin" target="_blank">
@ -75,22 +75,24 @@
<section class="progress column-2">
<div class="left sect">
<div class="left-meta">
<h2 class="dot title" id="about" {{#if locale.aboutUs.titleSuffix}}data-title-suffix="{{locale.aboutUs.titleSuffix}}"{{/if}}>{{ locale.aboutUs.title }}</h2>
<h2 class="dot title" id="about" {{#if locale.aboutUs.titleSuffix}}data-title-suffix="{{locale.aboutUs.titleSuffix}}"{{/if}}>{{ localeHelper locale "aboutUs" "title" }}</h2>
{{#each locale.aboutUs.paragraphs}}
<p class="text">{{ this }}</p>
{{/each}}
</div>
</div>
<div class="right sect">
<h2 class="title">{{ locale.progress.title }}</h2>
<h2 class="title">
<a href="/progress">{{ localeHelper locale "progress" "title" }}</a>
</h2>
{{> progress-list data=featuredFeatureList purple=true boards=boards }}
</div>
</section>
<section class="faq">
<div class="sect-top sect">
<h2 class="dot title" id="faq" {{#if locale.faq.titleSuffix}}data-title-suffix="{{locale.faq.titleSuffix}}"{{/if}}>{{ locale.faq.title }}</h2>
<p class="text">{{ locale.faq.text }}</p>
<h2 class="dot title" id="faq" {{#if locale.faq.titleSuffix}}data-title-suffix="{{locale.faq.titleSuffix}}"{{/if}}>{{ localeHelper locale "faq" "title" }}</h2>
<p class="text">{{ localeHelper locale "faq" "text" }}</p>
</div>
<div class="questions column-2">
{{#doFaq locale.faq.QAs}}
@ -105,11 +107,35 @@
{{!-- Tmp! --}}
<script>document.querySelector("details").setAttribute("open", true)</script>
</section>
<section class="showcase">
<div class="sect-top sect">
<h2 class="dot title" id="showcase" {{#if locale.credits.titleSuffix}}data-title-suffix="{{locale.credits.titleSuffix}}"{{/if}}>What we make</h2>
<p class="text">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.</p>
</div>
<div class="grid">
<div class="item highlight">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book" class="svg-inline--fa fa-book fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"></path></svg>
<h1>Game Servers</h1>
<p>Bringing back your favorite games and content using custom servers</p>
</div>
<div class="item">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book" class="svg-inline--fa fa-book fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"></path></svg>
<h1>Juxtaposition</h1>
<p>A re-imagining of Miiverse, as if it were made in the modern era</p>
</div>
<div class="item">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="book" class="svg-inline--fa fa-book fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"></path></svg>
<h1>Cemu Support</h1>
<p>Play your favorite Wii U titles even without a console!</p>
</div>
</div>
</section>
<section class="team">
<div class="sect-top sect team-top">
<h2 class="dot title" id="credits" {{#if locale.credits.titleSuffix}}data-title-suffix="{{locale.credits.titleSuffix}}"{{/if}}>{{ locale.credits.title }}</h2>
<p class="text">{{ locale.credits.text }}</p>
<h2 class="dot title" id="credits" {{#if locale.credits.titleSuffix}}data-title-suffix="{{locale.credits.titleSuffix}}"{{/if}}>{{ localeHelper locale "credits" "title" }}</h2>
<p class="text">{{ localeHelper locale "credits" "text" }}</p>
</div>
<div class="team-cards">
{{#each locale.credits.people}}
@ -132,32 +158,86 @@
</div>
</section>
<section class="team team-helpers">
<div class="sect-top sect team-top">
<h2 class="dot title" id="special-thanks" {{#if locale.specialThanks.titleSuffix}}data-title-suffix="{{locale.specialThanks.titleSuffix}}"{{/if}}>{{ locale.specialThanks.title }}</h2>
<p class="text">{{ locale.specialThanks.text }}</p>
<section class="team-helpers">
<div class="sect-top sect">
<h2 class="dot title" id="special-thanks" {{#if locale.specialThanks.titleSuffix}}data-title-suffix="{{locale.specialThanks.titleSuffix}}"{{/if}}>{{ localeHelper locale "specialThanks" "title" }}</h2>
<p class="text">{{ localeHelper locale "specialThanks" "text" }}</p>
</div>
<div class="team-cards">
{{#each locale.specialThanks.people}}
<div class="card">
<div class="card-left">
<img src="{{ picture }}" class="pfp">
</div>
<div class="card-core">
{{#if special}}<span class="sub">{{ special }}</span>{{/if}}
<h3 class="title">
<div class="animation-wrapper">
<div class="row first">
<div class="team-helpers-cards">
{{#each specialThanksPeople.first}}
<a href="{{ github }}" class="helper-card{{#if special}} special{{/if}}">
<div class="img-wrapper">
<img src="{{ picture }}" class="pfp">
</div>
<span>{{ name }}</span>
<a href="{{ github }}" class="github" target="_blank">
<svg data-prefix="fab" data-icon="github" class="svg-inline--fa fa-github fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg>
</a>
</h3>
<p class="text">{{ caption }}</p>
<p>{{ caption }}</p>
</a>
{{/each}}
</div>
<div class="team-helpers-cards repeat first">
{{#each specialThanksPeople.first}}
<a href="{{ github }}" class="helper-card{{#if special}} special{{/if}}">
<div class="img-wrapper">
<img src="{{ picture }}" class="pfp">
</div>
<span>{{ name }}</span>
<p>{{ caption }}</p>
</a>
{{/each}}
</div>
</div>
<div class="row second">
<div class="team-helpers-cards">
{{#each specialThanksPeople.second}}
<a href="{{ github }}" class="helper-card{{#if special}} special{{/if}}">
<div class="img-wrapper">
<img src="{{ picture }}" class="pfp">
</div>
<span>{{ name }}</span>
<p>{{ caption }}</p>
</a>
{{/each}}
</div>
<div class="team-helpers-cards repeat first">
{{#each specialThanksPeople.second}}
<a href="{{ github }}" class="helper-card{{#if special}} special{{/if}}">
<div class="img-wrapper">
<img src="{{ picture }}" class="pfp">
</div>
<span>{{ name }}</span>
<p>{{ caption }}</p>
</a>
{{/each}}
</div>
<div class="team-helpers-cards repeat second">
{{#each specialThanksPeople.second}}
<a href="{{ github }}" class="helper-card{{#if special}} special{{/if}}">
<div class="img-wrapper">
<img src="{{ picture }}" class="pfp">
</div>
<span>{{ name }}</span>
<p>{{ caption }}</p>
</a>
{{/each}}
</div>
</div>
{{/each}}
</div>
</section>
<section class="update-signup">
<div class="sect hero-meta reduced-margin">
<svg xmlns="http://www.w3.org/2000/svg" width="48.87" height="71.093" viewBox="0 0 48.87 71.093"><g id="XMLID_6_" transform="translate(0)"><path id="XMLID_15_" d="M69.581,29.593c-2.029,1.068-.249,4.129,1.78,3.061,5.162-2.67,11.463-2.6,16.981-1.1,4.735,1.282,9.5,3.845,12.246,8.045,1.246,1.922,4.307.142,3.061-1.78C96.921,27.386,80.3,24.04,69.581,29.593Z" transform="translate(-60.112 -20.086)" fill="#9d6ff3"/><path id="XMLID_14_" d="M103.359,21.045c-3.951-6.159-10.751-10-17.657-11.89C77.763,6.948,68.721,7.019,61.281,10.9c-2.029,1.068-.249,4.129,1.78,3.061,6.586-3.453,14.667-3.311,21.644-1.388,5.981,1.638,12.1,4.913,15.521,10.252C101.507,24.783,104.569,23,103.359,21.045Z" transform="translate(-54.766 -7.693)" fill="#9d6ff3"/><path id="XMLID_9_" d="M65.995,47.8a20.7,20.7,0,0,0-12.958,4.45H47.27a2.579,2.579,0,0,0-2.67,2.456v47.239a2.763,2.763,0,0,0,2.67,2.67h5.838a2.639,2.639,0,0,0,2.528-2.67V87.564A21.228,21.228,0,1,0,65.995,47.8Zm0,33.178a12,12,0,1,1,12-12A12,12,0,0,1,65.995,80.978Z" transform="translate(-44.6 -33.522)" fill="#9d6ff3"/></g></svg>
<h1 class="title dot">Stay up to date</h1>
<p class="text">Our amazing team has spent countless hours helping out on making Pretendo better.</p>
</div>
<div class="floating-serverjoin">
<p>Get realtime updates to our progress</p>
<a href="https://invite.gg/pretendo" target="_blank">Join the server</a>
</div>
<div class="circle"></div>
</section>
{{> footer }}

View File

@ -51,7 +51,7 @@
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Twemoji setup -->
<script src="https://twemoji.maxcdn.com/v/latest/twemoji.min.js" crossorigin="anonymous"></script>

View File

@ -6,17 +6,17 @@
<div class="localization-wrapper">
<div class="localization-widget">
<h1 class="title dot">{{ locale.localizationPage.title }}</h1>
<p class="caption">{{ locale.localizationPage.description }}</p>
<h1 class="title dot">{{ localeHelper locale "localizationPage" "title" }}</h1>
<p class="caption">{{ localeHelper locale "localizationPage" "description" }}</p>
<a href="https://github.com/PretendoNetwork/Pretendo/blob/master/CONTRIBUTING.md#localization" target="_blank" class="localization-instr">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--theme-light)" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
{{ locale.localizationPage.instructions }}
{{ localeHelper locale "localizationPage" "instructions" }}
</a>
<form class="localization-form" autocomplete="off">
<label for="url">{{ locale.localizationPage.fileInput }}</label>
<label for="url">{{ localeHelper locale "localizationPage" "fileInput" }}</label>
<div class="input-wrapper">
<input type="url" id="url" placeholder="{{ locale.localizationPage.filePlaceholder }}" required />
<button type="submit" class="submit-btn">{{ locale.localizationPage.button }}</button>
<input type="url" id="url" placeholder="{{ localeHelper locale "localizationPage" "filePlaceholder" }}" required />
<button type="submit" class="submit-btn">{{ localeHelper locale "localizationPage" "button" }}</button>
</div>
</form>
</div>

View File

@ -0,0 +1,50 @@
<div class="sidebar">
<div class="section">
<h5>Getting started</h5>
<a href="/docs/welcome">Welcome</a>
<a href="/docs/installing-juxt" >Installing Juxt</a>
<a href="/docs/search">Search</a>
</div>
<div class="section">
<h5>Error codes - Juxt</h5>
<a href="/docs/JXT-598-0000">JXT-598-0000</a>
<a href="/docs/JXT-598-0001">JXT-598-0001</a>
<a href="/docs/JXT-598-0002">JXT-598-0002</a>
<a href="/docs/JXT-598-0003">JXT-598-0003</a>
<a href="/docs/JXT-598-0009">JXT-598-0009</a>
<a href="/docs/JXT-598-0010">JXT-598-0010</a>
<a href="/docs/JXT-598-0011">JXT-598-0011</a>
<a href="/docs/JXT-598-0015">JXT-598-0015</a>
<a href="/docs/JXT-598-0020">JXT-598-0020</a>
<a href="/docs/JXT-598-1XXX">JXT-598-1XXX</a>
<a href="/docs/JXT-598-2XXX">JXT-598-2XXX</a>
<a href="/docs/JXT-598-3XXX">JXT-598-3XXX</a>
<a href="/docs/JXT-598-4XXX">JXT-598-4XXX</a>
<a href="/docs/JXT-598-5XXX">JXT-598-5XXX</a>
</div>
<div class="section">
<h5>Error codes - Beans</h5>
<a href="/docs/Black Beans">Black Beans</a>
<a href="/docs/black-eyed-peas">Black-Eyed Peas</a>
<a href="/docs/Cannellini Beans">Cannellini Beans</a>
<a href="/docs/Chickpeas (Garbanzo Beans)">Chickpeas (Garbanzo Beans)</a>
<a href="/docs/Great Northern Beans">Great Northern Beans</a>
<a href="/docs/Kidney Beans">Kidney Beans</a>
<a href="/docs/Lima Beans">Lima Beans</a>
<a href="/docs/Pinto Beans">Pinto Beans</a>
<a href="/docs/Fava Beans">Fava Beans</a>
<a href="/docs/Navy Beans">Navy Beans</a>
</div>
</div>
<script>
function selectSidebarElement(element) {
element.scrollIntoView({ block: "center" });
element.classList.add('active');
}
selectSidebarElement(document.querySelector("div.sidebar a[href='/docs/{{currentPage}}']"));
</script>

View File

@ -1 +1,53 @@
<footer>Copyright 2021 - Design by mrjvs, development by Jip Fr & monty</footer>
<footer>
<div>
<svg class="logotype" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 39.876" preserveAspectRatio="xMinYMin meet">
<g id="logo_type" data-name="logo type" transform="translate(-553 -467)">
<g id="logo" transform="translate(553 467)">
<rect id="XMLID_158_" width="39.876" height="39.876" fill="#9d6ff3" opacity="0" />
<g id="XMLID_6_" transform="translate(8.222 1.418)">
<path id="XMLID_15_"
d="M69.149,28.312c-1.051.553-.129,2.139.922,1.585a12.365,12.365,0,0,1,8.794-.571,10.829,10.829,0,0,1,6.342,4.166c.645,1,2.231.074,1.585-.922C83.308,27.169,74.7,25.436,69.149,28.312Z"
transform="translate(-64.246 -23.389)" fill="#9d6ff3" />
<path id="XMLID_14_"
d="M82.64,14.608A15.565,15.565,0,0,0,73.5,8.45a17.535,17.535,0,0,0-12.647.9c-1.051.553-.129,2.139.922,1.585,3.411-1.788,7.6-1.714,11.209-.719,3.1.848,6.268,2.544,8.038,5.309C81.681,16.543,83.267,15.622,82.64,14.608Z"
transform="translate(-57.476 -7.693)" fill="#9d6ff3" />
<path id="XMLID_9_"
d="M55.68,47.8a10.719,10.719,0,0,0-6.71,2.3H45.983A1.336,1.336,0,0,0,44.6,51.376V75.84a1.431,1.431,0,0,0,1.383,1.383h3.023a1.367,1.367,0,0,0,1.309-1.383V68.392A10.993,10.993,0,1,0,55.68,47.8Zm0,17.182a6.213,6.213,0,1,1,6.213-6.213A6.216,6.216,0,0,1,55.68,64.982Z"
transform="translate(-44.6 -40.406)" fill="#9d6ff3" />
</g>
</g>
<text id="Pretendo" transform="translate(593 492)" fill="#fff" font-size="17"
font-family="Poppins-Bold, Poppins" font-weight="700">
<tspan x="0" y="0">Pretendo</tspan>
</text>
</g>
</svg>
<p>Copyright 2021</p>
<p>Site by <a href="https://mrjvs.com/" target="_blank">mrjvs</a>, <a href="https://jipfr.nl/" target="_blank">jipfr</a> & <a href="https://ashmonty.com/" target="_blank">monty</a></p>
</div>
<div>
<h1>Socials</h1>
<a href="https://twitter.com/PretendoNetwork/" target="_blank">Twitter</a>
<a href="https://patreon.com/PretendoNetwork" target="_blank">Patreon</a>
<a href="https://invite.gg/pretendo" target="_blank">Discord</a>
<a href="https://github.com/PretendoNetwork" target="_blank">GitHub</a>
</div>
<div>
<h1>Useful links</h1>
<a style="display: none;" href="/docs">Docs</a>
<a href="/faq">FAQ</a>
<a href="/progress">Progress</a>
<a href="/blog">Blog</a>
<a href="/account" style="display: none; /* Hiding for now since it's not ready */">Account</a>
</div>
<div class="discord-server-card">
<h1>Want to keep updated?</h1>
<h2>Join our Discord server!</h2>
<a href="https://invite.gg/pretendo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
Join now!</a>
</div>
</footer>

View File

@ -25,11 +25,12 @@
</a>
<nav>
<a href="/#about">{{ locale.nav.about }}</a>
<a href="/#faq">{{ locale.nav.faq }}</a>
<a href="/#credits">{{ locale.nav.credits }}</a>
<a href="/progress" class="keep-on-mobile">{{ locale.nav.progress }}</a>
<a href="/blog" class="keep-on-mobile">{{ locale.nav.blog }}</a>
<a href="/#about">{{ localeHelper locale "nav" "about" }}</a>
<a href="/#faq">{{ localeHelper locale "nav" "faq" }}</a>
<a href="/#credits">{{ localeHelper locale "nav" "credits" }}</a>
<a style="display: none;" href="/docs">{{ localeHelper locale "nav" "docs"}}</a>
<a href="/progress" class="keep-on-mobile">{{ localeHelper locale "nav" "progress"}}</a>
<a href="/blog" class="keep-on-mobile">{{ localeHelper locale "nav" "blog" }}</a>
</nav>
<!-- Ordered the locales in the same way YouTube's language selector orders them -->
@ -117,5 +118,4 @@
<div class="item"><span class="lang"></span></div>
</div>
</div>
</header>

View File

@ -3,7 +3,7 @@
<div>
<div class="feature-progress-chart">
<p class="percentage-label">{{ data.percent }}</p>
<canvas></canvas>
<canvas class="percentage-chart"></canvas>
</div>
</div>
</div>

View File

@ -5,8 +5,8 @@
<div class="progress-hero">
<div class="hero-meta reduced-margin">
<svg xmlns="http://www.w3.org/2000/svg" width="48.87" height="71.093" viewBox="0 0 48.87 71.093"><g id="XMLID_6_" transform="translate(0)"><path id="XMLID_15_" d="M69.581,29.593c-2.029,1.068-.249,4.129,1.78,3.061,5.162-2.67,11.463-2.6,16.981-1.1,4.735,1.282,9.5,3.845,12.246,8.045,1.246,1.922,4.307.142,3.061-1.78C96.921,27.386,80.3,24.04,69.581,29.593Z" transform="translate(-60.112 -20.086)" fill="#9d6ff3"/><path id="XMLID_14_" d="M103.359,21.045c-3.951-6.159-10.751-10-17.657-11.89C77.763,6.948,68.721,7.019,61.281,10.9c-2.029,1.068-.249,4.129,1.78,3.061,6.586-3.453,14.667-3.311,21.644-1.388,5.981,1.638,12.1,4.913,15.521,10.252C101.507,24.783,104.569,23,103.359,21.045Z" transform="translate(-54.766 -7.693)" fill="#9d6ff3"/><path id="XMLID_9_" d="M65.995,47.8a20.7,20.7,0,0,0-12.958,4.45H47.27a2.579,2.579,0,0,0-2.67,2.456v47.239a2.763,2.763,0,0,0,2.67,2.67h5.838a2.639,2.639,0,0,0,2.528-2.67V87.564A21.228,21.228,0,1,0,65.995,47.8Zm0,33.178a12,12,0,1,1,12-12A12,12,0,0,1,65.995,80.978Z" transform="translate(-44.6 -33.522)" fill="#9d6ff3"/></g></svg>
<h1 class="title dot">{{ locale.progressPage.title }}</h1>
<p class="text">{{ locale.progressPage.description }}</p>
<h1 class="title dot">{{ localeHelper locale "progressPage" "title" }}</h1>
<p class="text">{{ localeHelper locale "progressPage" "description" }}</p>
</div>
</div>