From 909a2f81cc34e585ab671eab7affdc613475438e Mon Sep 17 00:00:00 2001 From: Evorp <3vorpgaming@gmail.com> Date: Sun, 12 May 2024 10:46:27 -0700 Subject: [PATCH] finally add prettier --- .prettierignore | 2 + .prettierrc | 18 + 404.html | 49 +- _includes/changelog.html | 65 +- _includes/empty_carousel.html | 2 +- _includes/matching_articles.html | 4 - _layouts/default.html | 626 +++++++++-------- _layouts/post.html | 315 ++++----- _layouts/redirect.html | 58 +- about.html | 71 +- addon.html | 14 +- addons.html | 10 +- changelogs/compliance32.html | 1 - changelogs/dungeons.html | 3 +- coffee.html | 159 ++--- css/404.scss | 44 +- css/about.scss | 114 ++-- css/dark.scss | 88 +-- css/download.scss | 404 +++++------ css/license.scss | 24 +- css/light.scss | 82 +-- css/main.scss | 240 +++---- css/mods.scss | 434 ++++++------ css/snow.scss | 68 +- discord/classicfaithful.html | 2 +- discord/faithful.html | 2 +- downloads.html | 2 +- faithful.html | 19 +- faithful32xDungeonsLatest.html | 3 +- faithful32xLatest.html | 3 +- faithful64xLatest.html | 3 +- faq.html | 1 - index.html | 216 ++++-- index.js | 627 +++++++++--------- js/404.js | 68 +- js/addons/addon-grid.js | 38 +- js/addons/addon-page.js | 92 +-- js/addons/addon-post-modal.js | 18 +- js/addons/addon-post-page.js | 30 +- js/addons/addon-post.js | 130 ++-- js/addons/index.js | 28 +- js/defaultFunctionality.js | 190 +++--- js/download/download-line.js | 49 +- js/download/download-table.js | 20 +- js/download/index.js | 34 +- js/faq.js | 32 +- js/favorite-addons.js | 74 ++- js/mods/components/clearDatabase.js | 30 +- js/mods/components/customModal.js | 12 +- js/mods/components/localDownload.js | 229 +++---- js/mods/components/modpackCard.js | 8 +- js/mods/components/modpackModal.js | 112 ++-- .../mods/downloadMinecraftVersion.js | 24 +- js/mods/components/mods/minecraftMod.js | 57 +- js/mods/components/mods/minecraftModsList.js | 18 +- js/mods/components/mods/minecraftVersions.js | 45 +- js/mods/components/zipOptions.js | 70 +- js/mods/core/MinecraftUtils.js | 47 +- js/mods/core/ResourcePackCreator.js | 418 ++++++------ js/mods/downloadFile.js | 47 +- js/mods/extensionjs.js | 38 +- js/mods/modpacks.js | 134 ++-- js/mods/mods.js | 278 ++++---- js/mods/polyfill.js | 24 +- js/mods/worker/downloadWorker.js | 76 ++- js/snow.js | 149 +++-- js/stats.js | 90 +-- js/theme.js | 57 +- license.html | 174 ++--- modpacks.html | 44 +- mods.html | 16 +- news.html | 11 +- package.json | 5 +- pnpm-lock.yaml | 55 ++ privacy.html | 29 +- secret-tools/modlistgenerator.html | 114 ++-- stats.html | 87 ++- twitter.html | 2 +- youtube.html | 2 +- 79 files changed, 3782 insertions(+), 3296 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..a4297f56 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +*.min.js +_layouts/compress.html \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..e77ce2da --- /dev/null +++ b/.prettierrc @@ -0,0 +1,18 @@ +{ + "semi": true, + "trailingComma": "all", + "singleQuote": false, + "printWidth": 100, + "useTabs": false, + "tabWidth": 2, + "bracketSpacing": true, + "arrowParens": "always", + "parser": "typescript", + "plugins": ["@shopify/prettier-plugin-liquid"], + "liquidSingleQuote": false, + "embeddedSingleQuote": false, + "overrides": [ + { "files": ["*.vue"], "options": { "parser": "vue" } }, + { "files": ["*.html"], "options": { "parser": "liquid-html" } } + ] +} diff --git a/404.html b/404.html index 1e065f22..95282030 100644 --- a/404.html +++ b/404.html @@ -1,18 +1,31 @@ ---- -layout: default -title: 404 -permalink: /404.html ---- -
-

Are you lost in The End?

-

- Unfortunately, the page you requested doesn't exist!
Try checking your spelling or going to the main page to find what you were looking for. -

-
- Boom - - -
-
- - +--- +layout: default +title: 404 +permalink: /404.html +--- +
+

Are you lost in The End?

+

+ Unfortunately, the page you requested doesn't exist!
+ Try checking your spelling or going to the main page to find + what you were looking for. +

+
+ Boom + + +
+
+ + diff --git a/_includes/changelog.html b/_includes/changelog.html index 005e4d9b..c69551a2 100644 --- a/_includes/changelog.html +++ b/_includes/changelog.html @@ -9,11 +9,10 @@

Changelog

{%- assign counter = counter | plus: 1 -%} {% if counter < CHANGELOG_LIMIT %} - - {%- if page.single-changelog == nul -%} -

{{ version.first[0] }}

+ {%- if page["single-changelog"] == nul -%} +

{{ version.first[0] }}

{%- endif -%} - {%- if page.expanded-changelog != nul -%} + {%- if page["expanded-changelog"] != nul -%} {%- for type in version.first[1] -%}

{{ type.first[0] }}:

{%- for game-version in type.first[1] -%} @@ -21,27 +20,24 @@

{{ game-version.first[0] }}:

@@ -61,38 +57,35 @@

{{ category.first[0] }}:

{%- endfor -%} {%- endif -%}
- {%- endif -%} {%- endfor -%} -{%- assign counter = 0 -%} - -{%- if page.single-changelog == null -%} - + {%- assign counter = 0 -%} -
- gif of creeper textures + gif of creeper textures

FREE AND OPEN-SOURCE

- The project is made possible entirely by talented volunteer artists and developers working in - their free time. -

- All of our textures, as well as the code of all our related projects, are available on GitHub. Take - a look and see how the magic happens! + The project is made possible entirely by talented volunteer artists and developers working + in their free time. +
+
+ All of our textures, as well as the code of all our related projects, are available on + GitHub. Take a look and see how the magic happens!

CROSS-PLATFORM

Faithful is available for both the most popular Java Edition versions as well as Bedrock Edition. -

- This means it can be used on all devices that support manual installation of resource packs, from - phones to even certain consoles. +
+
+ This means it can be used on all devices that support manual installation of resource packs, + from phones to even certain consoles.

-
- VIEW DOWNLOADS - + VIEW DOWNLOADS
- placeholder + placeholder
- placeholder + placeholder

MADE BY THE COMMUNITY

- As a community-driven pack, all our textures are voted on before being added, and we prioritise - community feedback above all. -

- Simply read our contribution handbook and follow the steps — it's that easy to make your mark on - Faithful forever! + As a community-driven pack, all our textures are voted on before being added, and we + prioritise community feedback above all. +
+
+ Simply read our contribution handbook and follow the steps — it's that easy to make your + mark on Faithful forever!

HOW TO CONTRIBUTE + rel="noreferrer" + >HOW TO CONTRIBUTE
@@ -97,20 +99,17 @@

A HISTORY OF EXPERTISE

We've got over a decade of experience making quality textures for Minecraft, with a rich history spanning from the first releases up to today. -

- Being one of the first ever texture packs to be developed, starting all the way back in 2010, Faithful - has secured its place among the most well-known Minecraft projects. +
+
+ Being one of the first ever texture packs to be developed, starting all the way back in + 2010, Faithful has secured its place among the most well-known Minecraft projects.

- - SEE OUR STATS - + SEE OUR STATS
- placeholder + placeholder

ANY MORE QUESTIONS?

- - VIEW OUR FAQ - -
\ No newline at end of file + VIEW OUR FAQ + diff --git a/addon.html b/addon.html index b43c879d..586b9e8b 100644 --- a/addon.html +++ b/addon.html @@ -5,14 +5,16 @@ addon_url: "%url%" addon-img: "%header_img%" --- - - + diff --git a/addons.html b/addons.html index 3f465207..df4f0dc0 100644 --- a/addons.html +++ b/addons.html @@ -2,9 +2,15 @@ layout: default title: Add-ons --- - + - + diff --git a/changelogs/compliance32.html b/changelogs/compliance32.html index f110c6d9..6102739c 100644 --- a/changelogs/compliance32.html +++ b/changelogs/compliance32.html @@ -1816,5 +1816,4 @@ - GUI: - Miscoloured pixel in smithing icon texture (Mr. Kirby 48) --- - {%- include changelog.html -%} diff --git a/changelogs/dungeons.html b/changelogs/dungeons.html index 8bb78274..7da9d149 100644 --- a/changelogs/dungeons.html +++ b/changelogs/dungeons.html @@ -66,5 +66,4 @@ - Outer parts of oak leaves in the main menu are not transparent. I have no idea why this happens, but the leaves work properly in all other levels. - (texture authors are only credited after a texture that's completely unique to Minecraft Dungeons.): --- - -{%- include changelog.html -%} \ No newline at end of file +{%- include changelog.html -%} diff --git a/coffee.html b/coffee.html index 6c89d6c3..77ff3954 100644 --- a/coffee.html +++ b/coffee.html @@ -1,77 +1,82 @@ ---- -layout: default -title: Coffee ---- - -
-

I'm a teapot

- - -
- - - - \ No newline at end of file +--- +layout: default +title: Coffee +--- +
+

I'm a teapot

+ + +
+ + + + diff --git a/css/404.scss b/css/404.scss index 012004da..8cb250dd 100644 --- a/css/404.scss +++ b/css/404.scss @@ -2,42 +2,42 @@ --- a, h1, p { - color: #ccc; + color: #ccc; } strong { - font-weight: bold; + font-weight: bold; } .hidden { - display: none + display: none } #animation_container { - position: relative; - height: 64px; - width: 128px; - margin: 100px auto 50px; + position: relative; + height: 64px; + width: 128px; + margin: 100px auto 50px; } #tnt { - position: absolute; - left: 32px; - cursor: url("../image/404/flint_and_steel.png") 16 16, pointer; - image-rendering: pixelated; - width: 64px; - height: 64px; + position: absolute; + left: 32px; + cursor: url("../image/404/flint_and_steel.png") 16 16, pointer; + image-rendering: pixelated; + width: 64px; + height: 64px; } #diamond { - position: absolute; - image-rendering: pixelated; - left: 32px; - width: 64px; - height: 64px; + position: absolute; + image-rendering: pixelated; + left: 32px; + width: 64px; + height: 64px; } #explosion { - position: absolute; - left: 32px; + position: absolute; + left: 32px; } .foreground { - background: rgba(0,0,0,0); + background: rgba(0,0,0,0); } .background { - background: #120E19 url(../image/background/the_end.jpg) no-repeat center; + background: #120E19 url(../image/background/the_end.jpg) no-repeat center; } diff --git a/css/about.scss b/css/about.scss index 0e49dc9a..842f4e62 100644 --- a/css/about.scss +++ b/css/about.scss @@ -4,96 +4,96 @@ @import "./variables"; .about-image { - max-height: 384px; - filter: drop-shadow(0 10px 10px #00000077); + max-height: 384px; + filter: drop-shadow(0 10px 10px #00000077); } // override container class for flex content .content-container { - display: flex; - align-items: center; - justify-content: center; - gap: 40px; + display: flex; + align-items: center; + justify-content: center; + gap: 40px; - p { - // add a bit of padding between the button and text - padding-bottom: 1.5rem; - } + p { + // add a bit of padding between the button and text + padding-bottom: 1.5rem; + } } .faq { - display: flex; - flex-direction: column; - align-items: center; - padding-top: 80px; - padding-bottom: 80px; + display: flex; + flex-direction: column; + align-items: center; + padding-top: 80px; + padding-bottom: 80px; - h1 { - margin-top: 0; - text-align: center; - } + h1 { + margin-top: 0; + text-align: center; + } } .about-button { - padding: 12px 22px; + padding: 12px 22px; // prevent weird button wrapping issues white-space: nowrap; - line-height: 1; - border-radius: $border-radius-0x; - transition: all 0.2s ease; - &:hover { - opacity: 0.66; - } + line-height: 1; + border-radius: $border-radius-0x; + transition: all 0.2s ease; + &:hover { + opacity: 0.66; + } } .green { // both light/dark mode use white text - p { - color: #fff; - } + p { + color: #fff; + } - .about-button { - background: white !important; - color: #76c944 !important; - } + .about-button { + background: white !important; + color: #76c944 !important; + } } .blue { - p { - color: #fff; - } + p { + color: #fff; + } - .about-button { - background: white !important; - color: #3498db !important; - } + .about-button { + background: white !important; + color: #3498db !important; + } } .pink { - p { - color: #fff; - } + p { + color: #fff; + } - .about-button { - background: white !important; - color: #ac1e63 !important; - } + .about-button { + background: white !important; + color: #ac1e63 !important; + } } @media (max-width: 1080px) { // center content and display vertically on mobile - .content-container { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - max-width: 95%; - } + .content-container { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + max-width: 95%; + } } @media (max-width: 1200px) { // override container class to fix margins - .container { - max-width: 95% !important; - } + .container { + max-width: 95% !important; + } } diff --git a/css/dark.scss b/css/dark.scss index ee991a9c..edf935ad 100644 --- a/css/dark.scss +++ b/css/dark.scss @@ -4,113 +4,113 @@ @import "./variables"; .background { - background: #131313 url(../image/background/bg_dark_background.png) repeat + background: #131313 url(../image/background/bg_dark_background.png) repeat } .foreground { - background: - #0C0C0C url(../image/background/bg_dark_foreground.png) repeat + background: + #0C0C0C url(../image/background/bg_dark_foreground.png) repeat } .placeholder { - background-image: url(https://database.faithfulpack.net/images/branding/logos/transparent/512/f32_logo.png), url(../image/background/bg_dark_foreground.png); + background-image: url(https://database.faithfulpack.net/images/branding/logos/transparent/512/f32_logo.png), url(../image/background/bg_dark_foreground.png); } .card { - background: #0C0C0C url(../image/background/bg_dark_background.png) repeat; + background: #0C0C0C url(../image/background/bg_dark_background.png) repeat; } #topNavbar, #topNavbar.fixed { - background: #0C0C0C url(../image/background/bg_dark_background.png) repeat !important; + background: #0C0C0C url(../image/background/bg_dark_background.png) repeat !important; } .outline { - background: #0C0C0C url(../image/background/bg_dark_background.png) !important; + background: #0C0C0C url(../image/background/bg_dark_background.png) !important; } .dropdown-menu { - background-color: #1C1C1C + background-color: #1C1C1C } .dropdown-item { - color: rgba(255, 255, 255, .7) + color: rgba(255, 255, 255, .7) } .dropdown-item:focus, .dropdown-item:hover { - color: rgba(255, 255, 255, .7) !important; - background-color: #141414 !important + color: rgba(255, 255, 255, .7) !important; + background-color: #141414 !important } ul, ol, li, h1, h2, h3, h4, h5, h6, p { - color: rgba(255, 255, 255, .7) + color: rgba(255, 255, 255, .7) } .btn-flag { - color: rgba(255, 255, 255, .7) !important + color: rgba(255, 255, 255, .7) !important } hr { - border-top: 1px solid rgba(255, 255, 255, .1) + border-top: 1px solid rgba(255, 255, 255, .1) } label, input { - color: rgba(255, 255, 255, .7); + color: rgba(255, 255, 255, .7); } #SearchBar { - color: #000; + color: #000; } .advice { - color: rgba(255, 255, 255, .7); + color: rgba(255, 255, 255, .7); } /** CUSTOM SCROLLBAR */ ::-webkit-scrollbar{ - background: #0E0E0E; + background: #0E0E0E; } ::-webkit-scrollbar-button, ::-webkit-scrollbar-thumb{ - background: #3E3E3E; - border: 1px solid #0E0E0E; + background: #3E3E3E; + border: 1px solid #0E0E0E; } ::-webkit-scrollbar-button:hover, ::-webkit-scrollbar-thumb:hover{ - background: #575757 + background: #575757 } ::-webkit-scrollbar-button:active, ::-webkit-scrollbar-thumb:active{ - background: #878787 + background: #878787 } .v-menu__content > * { - background-color: #0C0C0C !important; - & > * { - color: rgba(255, 255, 255, .7) !important; - } + background-color: #0C0C0C !important; + & > * { + color: rgba(255, 255, 255, .7) !important; + } } .content-container h1 { - color: rgba(255, 255, 255, .9); + color: rgba(255, 255, 255, .9); } .about-button { - background: white; - color: black; + background: white; + color: black; } .green { - background: #0d0d0d url("/image/background/bg_light_background.png") repeat; - background-blend-mode: screen; + background: #0d0d0d url("/image/background/bg_light_background.png") repeat; + background-blend-mode: screen; - h1 { - color: #76c944 !important; - } + h1 { + color: #76c944 !important; + } } .blue { - background: #0d0d0d url("/image/background/bg_light_background.png") repeat; - background-blend-mode: screen; + background: #0d0d0d url("/image/background/bg_light_background.png") repeat; + background-blend-mode: screen; - h1 { - color: #5ebbf9 !important; - } + h1 { + color: #5ebbf9 !important; + } } .pink { - background: #0d0d0d url("/image/background/bg_light_background.png") repeat; - background-blend-mode: screen; + background: #0d0d0d url("/image/background/bg_light_background.png") repeat; + background-blend-mode: screen; - h1 { - color: #fc53a5 !important; - } + h1 { + color: #fc53a5 !important; + } } diff --git a/css/download.scss b/css/download.scss index e1c18978..8985fcc0 100644 --- a/css/download.scss +++ b/css/download.scss @@ -4,321 +4,321 @@ @import "./variables"; h2 { - margin-top: 0.5rem; + margin-top: 0.5rem; } .collapsible, .content { - padding: .2rem; - border-radius: $border-radius-0x; - padding-left: .7rem; - padding-right: .7rem; + padding: .2rem; + border-radius: $border-radius-0x; + padding-left: .7rem; + padding-right: .7rem; } .collapsible:hover, .content:hover { - background-color: rgba(255, 255, 255, 0.1) !important; + background-color: rgba(255, 255, 255, 0.1) !important; } .content { - overflow: hidden; - transition: 5 0.2s ease-out; + overflow: hidden; + transition: 5 0.2s ease-out; } .content.active { - display: table-row; + display: table-row; } .outline { - background: #131313 url(../image/background/bg_light_background.png) repeat; - border-radius: $border-radius-0x; - padding: .7rem; - overflow-x: auto; - margin-bottom: 2rem; + background: #131313 url(../image/background/bg_light_background.png) repeat; + border-radius: $border-radius-0x; + padding: .7rem; + overflow-x: auto; + margin-bottom: 2rem; } th > p, td > p { - color: #ccc; - padding: .2rem; - margin-bottom: 0; - vertical-align: middle; + color: #ccc; + padding: .2rem; + margin-bottom: 0; + vertical-align: middle; } th { - text-align: center; - width: calc(40% / 3); + text-align: center; + width: calc(40% / 3); } th > p { - font-size: 20px; + font-size: 20px; } th.large { - text-align: left; - padding-left: .7rem; - width: 50% + text-align: left; + padding-left: .7rem; + width: 50% } td { - text-align: center; - vertical-align: middle; - width: calc(50% / 3); + text-align: center; + vertical-align: middle; + width: calc(50% / 3); } td > p { - font-size: 18px; + font-size: 18px; } td.small { - width: calc(50% / 6); + width: calc(50% / 6); } td.large { - text-align: left; - width: 45% + text-align: left; + width: 45% } td.before { - cursor: pointer; - width: 5% + cursor: pointer; + width: 5% } td.before-empty { - width: 5% + width: 5% } thead > tr { - padding: .2rem .7rem; - margin-bottom: .7rem; - background-color: #343A40; - border-radius: $border-radius-1x; - width: 100%; + padding: .2rem .7rem; + margin-bottom: .7rem; + background-color: #343A40; + border-radius: $border-radius-1x; + width: 100%; } table { - border-collapse: collapse; - width: 100%; + border-collapse: collapse; + width: 100%; } main span { - padding: .2rem .4rem; - border-radius: 3px; + padding: .2rem .4rem; + border-radius: 3px; } .download-table span.link-text { - padding: 0; + padding: 0; } .mobile { - display: none; + display: none; } .download-table .toggle { - user-select: none; + user-select: none; } .btn-dl { - padding: 0.1rem 0.4rem; - width: 110px; + padding: 0.1rem 0.4rem; + width: 110px; } .btn-dl > i { - font-size: small; - margin-right: 8px; + font-size: small; + margin-right: 8px; } .github { - background-color: rgb(255, 255, 255); - color: #111; + background-color: rgb(255, 255, 255); + color: #111; } .latest { - background-color: rgb(255, 255, 255); - color: #111; + background-color: rgb(255, 255, 255); + color: #111; } .blue { - background-color: rgb(60, 111, 221); - color: #fff; + background-color: rgb(60, 111, 221); + color: #fff; } .green { - background-color: rgb(80, 202, 24); - color: #111; + background-color: rgb(80, 202, 24); + color: #111; } .yellow { - background-color: rgb(214, 160, 23); - color: #111; + background-color: rgb(214, 160, 23); + color: #111; } .black { - background-color: #000; - color: #fff; + background-color: #000; + color: #fff; } .version { - background-color: rgb(192, 37, 68); - color: #fff; + background-color: rgb(192, 37, 68); + color: #fff; } @media (max-width: 760px) { - .outline { - margin: 0; - padding: 0; - } - - br + br { - display: none; - } - - .mobile { - display: block; - } - - .download-table { - &, tbody, tr { - width: 100%; - display: block; - } - - span { - padding: 0; - } - - thead { - display: none; - } - - tr { - display: block; - padding: 0.25rem 0.5rem; - display: flex; - align-items: stretch; - border-radius: 0; - - &:hover { - background-color: transparent !important; - } - - &:last-child { - border-bottom: 0px none; - } - - &.content.active { - display: flex; - } - } - - td { - p { - padding: 0; - } - - &.toggle { - flex: 0 0 24px; - padding: .2rem 0; - } - - &.details { - flex: 1 1 auto; - padding: .2rem .4rem; - - span { - padding: .2rem .4rem; - } - - .name { - display: block; - padding: 0; - } - - .date-mobile { - display: block; - } - } - - &.size, &.date, &.desktop { - display: none !important; - } - - &.downloads { - flex: 0 0 30px; - width: auto; - display: flex; - flex-direction: column; - justify-content: space-around; - - .btn-dl { - width: 30px; - height: 30px; - line-height: 30px; - text-align: center; - padding: 0; - - i { - display: block; - height: 30px; - line-height: 30px; - margin-right: 0 !important; - } - } - - .link-text { - display: none; - } - } - } - } + .outline { + margin: 0; + padding: 0; + } + + br + br { + display: none; + } + + .mobile { + display: block; + } + + .download-table { + &, tbody, tr { + width: 100%; + display: block; + } + + span { + padding: 0; + } + + thead { + display: none; + } + + tr { + display: block; + padding: 0.25rem 0.5rem; + display: flex; + align-items: stretch; + border-radius: 0; + + &:hover { + background-color: transparent !important; + } + + &:last-child { + border-bottom: 0px none; + } + + &.content.active { + display: flex; + } + } + + td { + p { + padding: 0; + } + + &.toggle { + flex: 0 0 24px; + padding: .2rem 0; + } + + &.details { + flex: 1 1 auto; + padding: .2rem .4rem; + + span { + padding: .2rem .4rem; + } + + .name { + display: block; + padding: 0; + } + + .date-mobile { + display: block; + } + } + + &.size, &.date, &.desktop { + display: none !important; + } + + &.downloads { + flex: 0 0 30px; + width: auto; + display: flex; + flex-direction: column; + justify-content: space-around; + + .btn-dl { + width: 30px; + height: 30px; + line-height: 30px; + text-align: center; + padding: 0; + + i { + display: block; + height: 30px; + line-height: 30px; + margin-right: 0 !important; + } + } + + .link-text { + display: none; + } + } + } + } } /** DOWNLOAD TABLES **/ /* .table { - background-color: #1c1c1c; - color: #ccc; - border-radius: $border-radius-1x; - overflow: hidden + background-color: #1c1c1c; + color: #ccc; + border-radius: $border-radius-1x; + overflow: hidden } .table thead th { - background-color: #343A40; - border: 0 + background-color: #343A40; + border: 0 } .table td { - border-top: 1px solid #343A40 + border-top: 1px solid #343A40 } .table tbody+tbody { - border: 0 + border: 0 } .table-hover tbody tr:hover { - color: #ccc; - background-color: rgba(0,0,0,.15) + color: #ccc; + background-color: rgba(0,0,0,.15) } .btn-invisible { - background-color: rgba(0,0,0,.25); - padding: 5px; - border-radius: $border-radius-1x; - border: 1px #0000; - color: #ccc; + background-color: rgba(0,0,0,.25); + padding: 5px; + border-radius: $border-radius-1x; + border: 1px #0000; + color: #ccc; } .btn-invisible:hover { - background-color: rgba(0,0,0,.75); - color: #fff; + background-color: rgba(0,0,0,.75); + color: #fff; } table { - width: 100% + width: 100% } th:nth-child(1) { - width: 32% + width: 32% } th:nth-child(2) { - width: 20% + width: 20% } th:nth-child(3) { - width: 28% + width: 28% } th:nth-child(4) { - width: 10% + width: 10% } @media screen and (max-width: 480px) { - th, td, tr { - display: block - } - tr > th:nth-child(1), tr > th:nth-child(2), tr > th:nth-child(3) { - width: 100% - } - th:nth-child(4) { - display: none - } + th, td, tr { + display: block + } + tr > th:nth-child(1), tr > th:nth-child(2), tr > th:nth-child(3) { + width: 100% + } + th:nth-child(4) { + display: none + } } */ \ No newline at end of file diff --git a/css/license.scss b/css/license.scss index 5f3c5cce..e5a44de8 100644 --- a/css/license.scss +++ b/css/license.scss @@ -2,26 +2,26 @@ --- .flag { - display: flex; - text-align: center; + display: flex; + text-align: center; - > div { - width: 40px; + > div { + width: 40px; - > img { - height: 16px; - vertical-align: text-top; - } - } + > img { + height: 16px; + vertical-align: text-top; + } + } } .dropdown-menu-right { - right: 0; - left: auto; + right: 0; + left: auto; } ol { - list-style-position: outside; + list-style-position: outside; } .license-download { diff --git a/css/light.scss b/css/light.scss index eb90ce44..70eefd22 100644 --- a/css/light.scss +++ b/css/light.scss @@ -4,102 +4,102 @@ @import "./variables"; .background { - background: #EEEDE5 url(../image/background/bg_light_background.png) repeat + background: #EEEDE5 url(../image/background/bg_light_background.png) repeat } .foreground { - background: - #EEEDE5 url(../image/background/bg_light_foreground.png) repeat + background: + #EEEDE5 url(../image/background/bg_light_foreground.png) repeat } .placeholder { - background-image: url(https://database.faithfulpack.net/images/branding/logos/transparent/512/f32_logo.png), url(../image/background/bg_light_foreground.png); + background-image: url(https://database.faithfulpack.net/images/branding/logos/transparent/512/f32_logo.png), url(../image/background/bg_light_foreground.png); } .card { - background: #EEEDE5 url(../image/background/bg_light_background.png) repeat; + background: #EEEDE5 url(../image/background/bg_light_background.png) repeat; } #topNavbar.fixed { - background: #EEEDE5 url(../image/background/bg_light_background.png); + background: #EEEDE5 url(../image/background/bg_light_background.png); } .outline { - background: #EEEDE5 url(../image/background/bg_light_background.png) !important; + background: #EEEDE5 url(../image/background/bg_light_background.png) !important; } .dropdown-menu { - background-color: #fff; + background-color: #fff; } .dropdown-item { - color: #212529; + color: #212529; } .dropdown-item:focus, .dropdown-item:hover { - color: #16181b; - background-color: #f8f9fa; + color: #16181b; + background-color: #f8f9fa; } hr { - border-top: 1px solid rgba(0, 0, 0, 0.1); + border-top: 1px solid rgba(0, 0, 0, 0.1); } label, input { - color: #212529; + color: #212529; } #SearchBar { - color: #fff; + color: #fff; } .advice { - color: #212529; + color: #212529; } /** CUSTOM SCROLLBAR */ ::-webkit-scrollbar{ - background: #F1F1F1 + background: #F1F1F1 } ::-webkit-scrollbar-button, ::-webkit-scrollbar-thumb{ - background: #C1C1C1; - border: 1px solid #F1F1F1; + background: #C1C1C1; + border: 1px solid #F1F1F1; } ::-webkit-scrollbar-button:hover, ::-webkit-scrollbar-thumb:hover{ - background: #A8A8A8 + background: #A8A8A8 } ::-webkit-scrollbar-button:active, ::-webkit-scrollbar-thumb:active{ - background: #787878 + background: #787878 } .v-list-item--highlighted > .v-list-item__content > .v-list-item__title { - color: $primary; + color: $primary; } .about-button { - background: black; - color: white; - &:hover { - color: white !important; - } + background: black; + color: white; + &:hover { + color: white !important; + } } .green { - background: #22a831 url("/image/background/bg_light_foreground.png") repeat; - background-blend-mode: multiply; + background: #22a831 url("/image/background/bg_light_foreground.png") repeat; + background-blend-mode: multiply; - h1 { - color: #fff; - } + h1 { + color: #fff; + } } .blue { - background: #3498db url("/image/background/bg_light_foreground.png") repeat; - background-blend-mode: multiply; + background: #3498db url("/image/background/bg_light_foreground.png") repeat; + background-blend-mode: multiply; - h1 { - color: #fff; - } + h1 { + color: #fff; + } } .pink { - background: #ac1e63 url("/image/background/bg_light_foreground.png") repeat; - background-blend-mode: multiply; + background: #ac1e63 url("/image/background/bg_light_foreground.png") repeat; + background-blend-mode: multiply; - h1 { - color: #fff; - } + h1 { + color: #fff; + } } \ No newline at end of file diff --git a/css/main.scss b/css/main.scss index 1516aa44..d6e01498 100644 --- a/css/main.scss +++ b/css/main.scss @@ -1420,11 +1420,11 @@ a.btn.disabled { * Bootstrap end */ html { - overflow-x: hidden + overflow-x: hidden } footer { - padding: 2rem 1rem; - text-align: center; + padding: 2rem 1rem; + text-align: center; position: relative; } footer #shadow { @@ -1458,9 +1458,9 @@ img:not(.img-gallery) { height: auto; } @media (min-width: 576px) { - footer { - padding: 4rem 2rem - } + footer { + padding: 4rem 2rem + } } @media (max-width: 760px) { footer { @@ -1491,8 +1491,8 @@ img:not(.img-gallery) { } /** MAIN STUFF **/ .container { - padding-top: 50px; - padding-bottom: 50px + padding-top: 50px; + padding-bottom: 50px } @media (max-width: 760px) { .container { @@ -1502,69 +1502,69 @@ img:not(.img-gallery) { } .right-reading { - direction: rtl + direction: rtl } .center { - display: block; - margin: auto !important + display: block; + margin: auto !important } .clickable:hover { - cursor: pointer + cursor: pointer } .disabled { - pointer-events: none + pointer-events: none } @media screen and (max-width: 768px) { - .display-3 { - font-size: 2.75rem - } - .display-4 { - font-size: 2.5rem - } - .h2 { - font-size: 1.25rem !important - } + .display-3 { + font-size: 2.75rem + } + .display-4 { + font-size: 2.5rem + } + .h2 { + font-size: 1.25rem !important + } .poster > img:nth-of-type(1) { height: 200px; width: 100%; } } @media screen and (min-width: 1000px) { - .small-screen-warning { - display: none - } + .small-screen-warning { + display: none + } } /** FANCY CARDS **/ .btn, .dropdown-menu, .fancy-card-1x, *.card, .fancy-card-2x { - overflow: hidden; - box-shadow: $card-shadow + overflow: hidden; + box-shadow: $card-shadow } .btn, .dropdown-menu, *.card *.card, .fancy-card-1x { - border-radius: $border-radius-0x + border-radius: $border-radius-0x } *.card, .fancy-card-2x { - border-radius: $border-radius-0x + border-radius: $border-radius-0x } .card-body > :first-child { - margin-top: 0 + margin-top: 0 } #changelog-title { - font-weight: 300; - color: rgba(255, 255, 255, .7) + font-weight: 300; + color: rgba(255, 255, 255, .7) } .card, .card p, .card > h2 > a { - color: rgba(255, 255, 255, .7) + color: rgba(255, 255, 255, .7) } .card > h2 > a:hover { - color: rgba(255, 255, 255, .9) + color: rgba(255, 255, 255, .9) } .card-img-top { - border-radius: $border-radius-0x; - cursor: pointer; - color: #000 + border-radius: $border-radius-0x; + cursor: pointer; + color: #000 } #ScreenshotCarousel { - background: #000 + background: #000 } /* carousel cards */ .item > .card { @@ -1596,25 +1596,25 @@ img:not(.img-gallery) { position: absolute; bottom: 0; margin: 8px; - color: rgba(255, 255, 255, .9); - text-shadow: $card-shadow; - font-size: 1.5rem; - font-weight: 500; + color: rgba(255, 255, 255, .9); + text-shadow: $card-shadow; + font-size: 1.5rem; + font-weight: 500; } .img-card > p { position: absolute; bottom: 16px; margin: 8px; color: rgba(255,255,255,.9); - text-shadow: $card-shadow; - font-size: 1.3rem; - font-weight: 400; + text-shadow: $card-shadow; + font-size: 1.3rem; + font-weight: 400; } .placeholder { - background-image: url(https://database.faithfulpack.net/images/branding/logos/transparent/512/f32_logo.png), url(/image/background/bg_light_foreground.png); - background-repeat: no-repeat, repeat; - background-position: center, center; - background-size: auto 75%, auto; + background-image: url(https://database.faithfulpack.net/images/branding/logos/transparent/512/f32_logo.png), url(/image/background/bg_light_foreground.png); + background-repeat: no-repeat, repeat; + background-position: center, center; + background-size: auto 75%, auto; } /** Custom Bootstrap-like **/ .block { @@ -1622,8 +1622,8 @@ img:not(.img-gallery) { width: 100%; } .display { - font-weight: 300; - line-height: 1.2 + font-weight: 300; + line-height: 1.2 } .banner { padding: 16px; @@ -1683,8 +1683,8 @@ a > .banner:hover { } /** NAVBAR **/ .dropdown-menu-center { - right: auto; - left: auto + right: auto; + left: auto } #topNavbar { position: relative; @@ -1703,9 +1703,9 @@ body.error #topNavbar { background: url(../image/background/bg_light_background.png) repeat; } #bottomNavbar { - display: inline-block; - width: auto; - margin: auto + display: inline-block; + width: auto; + margin: auto } #bottomNavbar .navbar-nav { justify-content: center @@ -1738,108 +1738,108 @@ body.error #topNavbar { /** OWL CAROUSEL **/ /* Make the image fully responsive (owl carousel) */ .carousel-inner img { - width: 100%; - height: 100% + width: 100%; + height: 100% } /* Carousel arrow hover animation */ .icon-hover { - transition: all .5s ease + transition: all .5s ease } .icon-hover:hover { - transform: scale(1.1) + transform: scale(1.1) } .icon-hover:focus, .icon-hover:active { - transform: scale(1) + transform: scale(1) } /** BASIC CAROUSEL **/ /* Make the image fully responsive (carousel) */ .carousel-inner img { - width: 100%; - height: 100% + width: 100%; + height: 100% } /* Carousel arrow hover animation */ .carousel-control-prev-icon, .carousel-control-next-icon { - transition: all 1s ease + transition: all 1s ease } .carousel-control-prev:hover .carousel-control-prev-icon { - margin-right: 25px + margin-right: 25px } .carousel-control-next:hover .carousel-control-next-icon { - margin-left: 25px + margin-left: 25px } /** CUSTOM SCROLLBAR **/ ::-webkit-scrollbar{ - width: 8px; + width: 8px; } ::-webkit-scrollbar-button{ - height: 8px + height: 8px } /* NAVBAR */ @media (min-width: 800px) { - .nav { - text-align: center - } - .nav { - display: inline-flex - } + .nav { + text-align: center + } + .nav { + display: inline-flex + } } .nav-link { - transition: all .1s ease-out + transition: all .1s ease-out } @media screen and (min-width: 800px) { - .nav-link:hover { - transform: scale(0.95) - } + .nav-link:hover { + transform: scale(0.95) + } } .nav-link:hover { - cursor: pointer + cursor: pointer } /** MODAL **/ .modal { - display: none; - position: fixed; - z-index: 1100; - padding-top: 100px; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgb(0,0,0); - background-color: rgba(0,0,0,.7) + display: none; + position: fixed; + z-index: 1100; + padding-top: 100px; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,.7) } .modal-content { - margin: auto; - display: block; - width: 70%; - max-width: 700px; - animation-name: zoom; - animation-duration: 0.6s + margin: auto; + display: block; + width: 70%; + max-width: 700px; + animation-name: zoom; + animation-duration: 0.6s } /* Add Animation */ .modal-content, .caption { - animation-name: zoom; - animation-duration: 0.6s + animation-name: zoom; + animation-duration: 0.6s } @keyframes zoom { - from {transform:scale(0)} - to {transform:scale(1)} + from {transform:scale(0)} + to {transform:scale(1)} } /* The Close Button */ .close { - position: absolute; - top: 15px; - right: 35px; - color: #f1f1f1; - font-size: 40px; - font-weight: 500; - transition: 0.3s + position: absolute; + top: 15px; + right: 35px; + color: #f1f1f1; + font-size: 40px; + font-weight: 500; + transition: 0.3s } .close:hover, .close:focus { - color: #bbb; - text-decoration: none; - cursor: pointer + color: #bbb; + text-decoration: none; + cursor: pointer } /*addons*/ .rem-button { @@ -1892,16 +1892,16 @@ body.error #topNavbar { } /* 100% Image Width on Smaller Screens */ @media only screen and (max-width: 700px) { - .modal-content { - width: 100% - } + .modal-content { + width: 100% + } } /* make images not draggable */ img[src$=".png"], img[src$=".gif"], img[src$=".jpg"] { - -webkit-user-drag: none; - -khtml-user-drag: none; - -moz-user-drag: none; - -o-user-drag: none; + -webkit-user-drag: none; + -khtml-user-drag: none; + -moz-user-drag: none; + -o-user-drag: none; } .addon-info-subtitle { @@ -2079,12 +2079,12 @@ img[src$=".png"], img[src$=".gif"], img[src$=".jpg"] { } & > div > div > div > label { - color: rgba(255,255,255,.8) !important; + color: rgba(255,255,255,.8) !important; font-size: 20px; } & > div > div > div > div > i { - color: rgba(255,255,255,.5) !important; + color: rgba(255,255,255,.5) !important; } } @@ -2166,4 +2166,4 @@ input[type=radio] { .faq-answer { padding-left: 20px; -} \ No newline at end of file +} diff --git a/css/mods.scss b/css/mods.scss index b220cf83..82cd773d 100644 --- a/css/mods.scss +++ b/css/mods.scss @@ -5,52 +5,52 @@ /* Versions btn for small screen */ @media (max-width: 777px) { - .btn-group { - flex-direction: column; - justify-content: center - } + .btn-group { + flex-direction: column; + justify-content: center + } - #bottomButtons .btn { - display: block; - width: 100% - } + #bottomButtons .btn { + display: block; + width: 100% + } - #bottomButtons { - margin-right: 0; - margin-bottom: 8px - } + #bottomButtons { + margin-right: 0; + margin-bottom: 8px + } } input[type=checkbox], input[type=radio], label { - cursor: pointer + cursor: pointer } .fa-info-circle { - margin-left: -5px + margin-left: -5px } .mod-radio-group input { - display: none; + display: none; } .mod-radio-group { - margin-top: -2px; + margin-top: -2px; } input[type=radio] + label { - border: 1px solid #ddd; - border-radius: 10px; - display: inline-flex; - flex-direction: row; - padding-right: 5px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - align-items: flex-end; - color: #ddd; - margin-right: 4px; - margin-top: 2px; + border: 1px solid #ddd; + border-radius: 10px; + display: inline-flex; + flex-direction: row; + padding-right: 5px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + align-items: flex-end; + color: #ddd; + margin-right: 4px; + margin-top: 2px; } input[type=radio] + label::before { @@ -58,8 +58,8 @@ input[type=radio] + label::before { width: 16px; height: 16px; position: relative; - margin: 5px; - filter: invert(100%); + margin: 5px; + filter: invert(100%); } input[type=radio] + label::before { @@ -69,67 +69,67 @@ input[type=radio]:checked + label::before { background: url('../image/icon/check-circle-fill.svg') no-repeat center; } input[type=radio]:checked + label { - border-color: $primary; + border-color: $primary; background: $primary; } #zipOptions ::-webkit-input-placeholder { - font-style: italic + font-style: italic } #zipOptions :-moz-placeholder { - font-style: italic + font-style: italic } #zipOptions ::-moz-placeholder { - font-style: italic + font-style: italic } #zipOptions :-ms-input-placeholder { - font-style: italic + font-style: italic } #zipOptions #archiveName.empty { - background: #ccc + background: #ccc } .customModalBackground { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: rgba(0,0,0,0.5) + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: rgba(0,0,0,0.5) } .customModal { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - padding: 10px; - z-index: 3000; - text-align: center + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding: 10px; + z-index: 3000; + text-align: center } .customModal > * { - display: inline-block; - vertical-align: middle + display: inline-block; + vertical-align: middle } .customModal > span.taille { - height: 100% + height: 100% } .customModal .customModalContent { - background: #232323; - color: rgba(255, 255, 255, .9); - border-radius: $border-radius-0x; - box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); - width: 600px; - max-width: 100%; - max-height: 100%; - overflow: auto; - text-align: left; - position: relative + background: #232323; + color: rgba(255, 255, 255, .9); + border-radius: $border-radius-0x; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); + width: 600px; + max-width: 100%; + max-height: 100%; + overflow: auto; + text-align: left; + position: relative } .customModal p { @@ -138,273 +138,273 @@ input[type=radio]:checked + label { #downloadModalContent #steps { display: flex; - align-items: center + align-items: center } #downloadModalContent #steps .btn-dark { - height: 2.2rem; - width: 2.2rem; - padding-top: 0; - padding-bottom: 0 + height: 2.2rem; + width: 2.2rem; + padding-top: 0; + padding-bottom: 0 } #downloadModalContent #steps .line { - height: 1px; - background-color: lightgray; + height: 1px; + background-color: lightgray; flex: 1 } #downloadModalContent #logs { - background: #171717; - height: 300px; - overflow-x: auto; - overflow-y: scroll + background: #171717; + height: 300px; + overflow-x: auto; + overflow-y: scroll } .progress { - background-color: #232323 + background-color: #232323 } .progress-bar, #downloadModalContent #zipProgressBar > * { - background-color: $primary + background-color: $primary } #downloadModalContent #zipProgressBar > * { - transition: unset + transition: unset } #logs .log { - padding-left: 4px; - height: 24px; - line-height: 24px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis + padding-left: 4px; + height: 24px; + line-height: 24px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis } #logs .log:nth-child(even) { - background-color: rgba(0,0,0,0.2) + background-color: rgba(0,0,0,0.2) } #logs .log.error { - background-color: rgba(255,25,25, 0.5) + background-color: rgba(255,25,25, 0.5) } .modal-header { - border-bottom: 1px solid #2D2E32 + border-bottom: 1px solid #2D2E32 } .modal-footer { - border-top: 1px solid #2D2E32 + border-top: 1px solid #2D2E32 } #SearchBar { - background-image: url(/image/css/search.svg); - background-position: 10px 12px; - background-repeat: no-repeat; - width: 100%; - font-size: 16px; - padding: 12px 20px 12px 40px; - border: 0 + background-image: url(/image/css/search.svg); + background-position: 10px 12px; + background-repeat: no-repeat; + width: 100%; + font-size: 16px; + padding: 12px 20px 12px 40px; + border: 0 } #SearchBar + .advice { - line-height: 20px; - min-height: 20px + line-height: 20px; + min-height: 20px } .advice { - margin: 1px 0 0; - font-size: 1em; - opacity: 0.75; + margin: 1px 0 0; + font-size: 1em; + opacity: 0.75; } .modNotChosen { - opacity: 0.7 + opacity: 0.7 } .version > * { - display: inline-block; - vertical-align: middle + display: inline-block; + vertical-align: middle } /* Mod bar */ .search-bar-container { - padding: 1.25rem 1.25rem .625rem + padding: 1.25rem 1.25rem .625rem } #noresults { - padding: 0 1.25rem + padding: 0 1.25rem } .mod-ul { - padding: 0 + padding: 0 } .mod-bar { - position: relative; - display: flex; - padding: .625rem 1.25rem + position: relative; + display: flex; + padding: .625rem 1.25rem } .mod-bar:hover { - background: rgba(127, 127, 127, .08) + background: rgba(127, 127, 127, .08) } .selected-mod { - background: rgba(127, 127, 127, .16) + background: rgba(127, 127, 127, .16) } .selected-mod:hover { - background: rgba(127, 127, 127, .24) + background: rgba(127, 127, 127, .24) } .mod-label { - position: absolute; - display: block; - margin: 0; - top: 0; - left: 0; - bottom: 0; - right: 0; - z-index: 1; - font-size: 0 + position: absolute; + display: block; + margin: 0; + top: 0; + left: 0; + bottom: 0; + right: 0; + z-index: 1; + font-size: 0 } .mod-bar-item { - width: 100%; + width: 100%; } .mod-title { - width: 100%; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - - div { - display: flex; - flex-direction: row; - padding: 5px; + width: 100%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + + div { + display: flex; + flex-direction: row; + padding: 5px; align-items: flex-end; - h4, h5 { - margin: 0; - } + h4, h5 { + margin: 0; + } - h5 { - margin-bottom: 2px; - } - } + h5 { + margin-bottom: 2px; + } + } } .mod-img { - position: relative; - text-align: center; - width: 65px; - height: 65px; - flex: none; - margin-right: 1.25rem; - display: flex; - align-items: center; - justify-content: center; - margin-top: 5px; - margin-bottom: -5px; - - &, .mod-img img { - image-rendering: pixelated; - border-radius: $border-radius-1x; - } - - img { - max-width: 100%; - max-height: 100%; - } + position: relative; + text-align: center; + width: 65px; + height: 65px; + flex: none; + margin-right: 1.25rem; + display: flex; + align-items: center; + justify-content: center; + margin-top: 5px; + margin-bottom: -5px; + + &, .mod-img img { + image-rendering: pixelated; + border-radius: $border-radius-1x; + } + + img { + max-width: 100%; + max-height: 100%; + } } .selected-mod .mod-img-overlay { - top: 0; - left: 0; - right: 0; - bottom: 0; - position: absolute; - width: 100%; - height: 100%; - border-radius: $border-radius-1x; - background: rgba(0, 123, 255, 0.64) center/75% url('../image/css/checked.svg') no-repeat + top: 0; + left: 0; + right: 0; + bottom: 0; + position: absolute; + width: 100%; + height: 100%; + border-radius: $border-radius-1x; + background: rgba(0, 123, 255, 0.64) center/75% url('../image/css/checked.svg') no-repeat } .mod-checkbox { - display: none; + display: none; } label.mod-radio { - margin-right: .25rem; + margin-right: .25rem; } .mod-radio { - vertical-align: middle; - margin-left: 5px; + vertical-align: middle; + margin-left: 5px; } .mod-info, .selected-mod .mod-radio-group { - position: relative; - z-index: 2 + position: relative; + z-index: 2 } .badge { - border-radius: $border-radius-0x !important; + border-radius: $border-radius-0x !important; } .advice-subtitle { - font-size: 100%; + font-size: 100%; } .advice-important { - color:#f14b4b; + color:#f14b4b; } /** MODPACKS **\ \** **/ #modpacks .card .card-image { - background-size: contain; - background-repeat: no-repeat; - background-position: center center + background-size: contain; + background-repeat: no-repeat; + background-position: center center } #modpacks .card .card-title { - min-height: 80px + min-height: 80px } #modpacks #modpackModal { - z-index: 1200 + z-index: 1200 } #modpacks #modpackModal #modList { - max-height: 400px; - overflow: auto; - background: rgba(0,0,0,.35) + max-height: 400px; + overflow: auto; + background: rgba(0,0,0,.35) } #modpacks #modpackModal #modList ul { - font-size: .8em; - list-style-type: none; - padding-left: 0; - padding-right: 0; - margin-bottom: 0 + font-size: .8em; + list-style-type: none; + padding-left: 0; + padding-right: 0; + margin-bottom: 0 } @media (max-width: 760px) { - .mod-bar { - padding: 0.625rem; - } + .mod-bar { + padding: 0.625rem; + } - .mod-img { - width: 32px; - height: 32px; - float: left; - margin-right: 0.625rem; - } + .mod-img { + width: 32px; + height: 32px; + float: left; + margin-right: 0.625rem; + } - .mod-title { - align-items: flex-start; + .mod-title { + align-items: flex-start; - div { - padding-top: 0; - display: block; + div { + padding-top: 0; + display: block; - .dash { - display: none; - } - } + .dash { + display: none; + } + } - .icon { - margin-top: -5px; - margin-right: -5px; - } - } + .icon { + margin-top: -5px; + margin-right: -5px; + } + } } #gone-fishin { @@ -415,10 +415,10 @@ label.mod-radio { } h1 { - text-align: center; - font-size: 4rem; + text-align: center; + font-size: 4rem; } h2 { - text-align: center; + text-align: center; } \ No newline at end of file diff --git a/css/snow.scss b/css/snow.scss index e19be2c8..6cc89f95 100644 --- a/css/snow.scss +++ b/css/snow.scss @@ -2,72 +2,72 @@ --- #snowflakeContainer { - position: absolute; - left: 0; - top: 0; - display: none + position: absolute; + left: 0; + top: 0; + display: none } .card { - background: - url(../image/background/snow_overlay.png), url(../image/background/bg_light_background.png) top center repeat-x; - background-position: top center; - background-color: #131313, #131313; - background-repeat: repeat-x, repeat; + background: + url(../image/background/snow_overlay.png), url(../image/background/bg_light_background.png) top center repeat-x; + background-position: top center; + background-color: #131313, #131313; + background-repeat: repeat-x, repeat; } .author-widget, .card-widget { - padding-top: 20px; + padding-top: 20px; } .card-body { - margin-top: 15px + margin-top: 15px } .card.author-widget { - padding-top: 1.25rem; + padding-top: 1.25rem; } .btn { - border: 0 !important; - padding-top: 15px; - background-image: url(../image/background/snow_overlay_small.png); - background-position: top center; - background-repeat: repeat-x + border: 0 !important; + padding-top: 15px; + background-image: url(../image/background/snow_overlay_small.png); + background-position: top center; + background-repeat: repeat-x } .btn-dl { - background-size: 20% auto; + background-size: 20% auto; } .snowflake0, .snowflake1, .snowflake2, .snowflake3 { - position: fixed; - image-rendering: pixelated; - user-select: none; - z-index: 1000; - pointer-events: none; - border-radius: 50%; - width: 16px; - height: 16px + position: fixed; + image-rendering: pixelated; + user-select: none; + z-index: 1000; + pointer-events: none; + border-radius: 50%; + width: 16px; + height: 16px } .snowflake0 { - background: url(../image/background/snow0.png) no-repeat center; - background-size: contain; + background: url(../image/background/snow0.png) no-repeat center; + background-size: contain; } .snowflake1 { - background: url(../image/background/snow1.png) no-repeat center; - background-size: contain; + background: url(../image/background/snow1.png) no-repeat center; + background-size: contain; } .snowflake2 { - background: url(../image/background/snow2.png) no-repeat center; - background-size: contain; + background: url(../image/background/snow2.png) no-repeat center; + background-size: contain; } .snowflake3 { - background: url(../image/background/snow3.png) no-repeat center; - background-size: contain; + background: url(../image/background/snow3.png) no-repeat center; + background-size: contain; } diff --git a/discord/classicfaithful.html b/discord/classicfaithful.html index 28c65b0e..d1a25e3a 100644 --- a/discord/classicfaithful.html +++ b/discord/classicfaithful.html @@ -6,4 +6,4 @@ permalink: /discord/classicfaithful embed-img: redirect/classicfaithful.png color: "#76C945" ---- \ No newline at end of file +--- diff --git a/discord/faithful.html b/discord/faithful.html index 0560806a..bb26f7a3 100644 --- a/discord/faithful.html +++ b/discord/faithful.html @@ -6,4 +6,4 @@ permalink: /discord/faithful embed-img: redirect/faithful.png color: "#76C945" ---- \ No newline at end of file +--- diff --git a/downloads.html b/downloads.html index 9c88f694..4b2ad736 100644 --- a/downloads.html +++ b/downloads.html @@ -7,4 +7,4 @@
- \ No newline at end of file + diff --git a/faithful.html b/faithful.html index f99b9dac..5a65d13e 100644 --- a/faithful.html +++ b/faithful.html @@ -2,12 +2,19 @@ layout: default title: Faithful --- - -

Kraineff was never officially approved by Faithful's original creator, Vattic, to distribute his textures on faithful.team or to sell them in any way.

+

+ Kraineff was never officially approved by Faithful's original creator, Vattic, to distribute his + textures on faithful.team or to sell them in any way. +

- If you are currently using Kraineff's fraudulent pack, we would like to ask you to stop using it, since that directly supports Kraineff. Additionally, it is recommended to leave his Discord server as soon as possible for the same reason. Faithful is now being run by what was Compliance and Emulated Vattic, now Faithful and Classic Faithful respectively. The only official website where you can find Faithful is this website – faithfulpack.net, with Discord servers being found at the bottom of this page. -

- Return to main page -

\ No newline at end of file + If you are currently using Kraineff's fraudulent pack, we would like to ask you to stop using it, + since that directly supports Kraineff. Additionally, it is recommended to leave his Discord server + as soon as possible for the same reason. Faithful is now being run by what was Compliance and + Emulated Vattic, now Faithful and Classic Faithful respectively. The only official website where + you can find Faithful is this website – faithfulpack.net, + with Discord servers being found at the bottom of this page.
+
+ Return to main page + diff --git a/faithful32xDungeonsLatest.html b/faithful32xDungeonsLatest.html index 78beeab9..50bc91fd 100644 --- a/faithful32xDungeonsLatest.html +++ b/faithful32xDungeonsLatest.html @@ -3,7 +3,6 @@ title: Latest Release permalink: faithful32xDungeons/latest --- - {%- assign found = false -%} {%- for post in site.posts -%} {%- if post.path contains "CD32" and found == false -%} @@ -13,4 +12,4 @@ {{ post }} {%- assign found = true -%} {%- endif -%} -{%- endfor -%} \ No newline at end of file +{%- endfor -%} diff --git a/faithful32xLatest.html b/faithful32xLatest.html index 86af75a9..5a77e314 100644 --- a/faithful32xLatest.html +++ b/faithful32xLatest.html @@ -3,7 +3,6 @@ title: Latest Release permalink: faithful32x/latest --- - {%- assign found = false -%} {%- for post in site.posts -%} {%- if post.path contains "C32" and found == false -%} @@ -13,4 +12,4 @@ {{ post }} {%- assign found = true -%} {%- endif -%} -{%- endfor -%} \ No newline at end of file +{%- endfor -%} diff --git a/faithful64xLatest.html b/faithful64xLatest.html index 700b0d9a..08c0c115 100644 --- a/faithful64xLatest.html +++ b/faithful64xLatest.html @@ -3,7 +3,6 @@ title: Latest Release permalink: faithful64x/latest --- - {%- assign found = false -%} {%- for post in site.posts -%} {%- if post.path contains "C64" and found == false -%} @@ -13,4 +12,4 @@ {{ post }} {%- assign found = true -%} {%- endif -%} -{%- endfor -%} \ No newline at end of file +{%- endfor -%} diff --git a/faq.html b/faq.html index 00970190..ef38f524 100644 --- a/faq.html +++ b/faq.html @@ -2,7 +2,6 @@ layout: default title: FAQ --- -
diff --git a/index.html b/index.html index 3613e096..44662ee4 100644 --- a/index.html +++ b/index.html @@ -3,19 +3,20 @@ title: Home no_container: true --- - @@ -24,26 +25,50 @@

Projects

- Faithful 32x - Faithful 32x wordmark + Faithful 32x + Faithful 32x wordmark
- The original Minecraft texture feel, with double the resolution and double the fun!
+ The original Minecraft texture feel, with double the resolution and double the fun!
- See Latest Version + See Latest Version
- Faithful 64x - Faithful 64x wordmark + Faithful 64x + Faithful 64x wordmark
- An even more detailed experience with quadruple-resolution textures!
+ An even more detailed experience with quadruple-resolution textures!
- See Latest Version + See Latest Version
@@ -53,65 +78,91 @@

Projects

- Classic Faithful 32x - Classic Faithful 32x Wordmark + Classic Faithful 32x + Classic Faithful 32x Wordmark
- The older yet refreshed look of Faithful, for when you need that nostalgic hit!
+ The older yet refreshed look of Faithful, for when you need that nostalgic hit!
- Classic Faithful 64x - Classic Faithful 64x Wordmark + Classic Faithful 64x + Classic Faithful 64x Wordmark
- The traditional Faithful style with fully refreshed and ultra high-resolution textures!
+ The traditional Faithful style with fully refreshed and ultra high-resolution textures!
- View Post + View Post

@@ -120,18 +171,46 @@

Add-ons

@@ -140,12 +219,16 @@

See More


News

- {%- for post in site.posts limit:6 -%} + {%- for post in site.posts limit: 6 -%} - {%- if post.header-img -%} - {{ image.basename }} + {%- if post["header-img"] -%} + {{ image.basename }} {%- else -%} - {{ post.title }} + {{ post.title }} {%- endif -%}

{{ post.title }}

@@ -164,29 +247,28 @@

{{ post.title }}

addons: [], NB_ITEMS: 3, LOADING_ID: "loading", - }; }, created() { - fetch('https://api.faithfulpack.net/v2/addons/approved') + fetch("https://api.faithfulpack.net/v2/addons/approved") .then((res) => res.json()) .then((val) => { - const res = [] + const res = []; - let items = val + let items = val; for (let i = 0; i < this.NB_ITEMS; i++) { // splice removes element from list and returns the retrieved elements // removes duplicate suggested add-ons - const element = items.splice((Math.random() * items.length) | 0, 1)[0] - res.push(element) + const element = items.splice((Math.random() * items.length) | 0, 1)[0]; + res.push(element); } - this.addons = res + this.addons = res; }) .catch((err) => { - console.error(err) - this.addons = [] + console.error(err); + this.addons = []; }); - } + }, }); - }) + }); diff --git a/index.js b/index.js index 3c46d2ce..85c24fff 100644 --- a/index.js +++ b/index.js @@ -1,315 +1,312 @@ -const express = require("express"); -const cors = require("cors"); -const { readdir, readFile, writeFile } = require("fs").promises; -const createDOMPurify = require("dompurify"); -const { JSDOM } = require("jsdom"); -const { parse, join } = require("path"); -const yaml = require("js-yaml"); - -require("dotenv").config(); - -const corsOptions = { - origin: "*", - methods: [], - allowedHeaders: [], - exposedHeaders: [], - credentials: true, -}; - -const DOMPurify = createDOMPurify(new JSDOM("").window); - -const app = express(); -app.disable("x-powered-by"); - -const NOT_FOUND_PAGE = __dirname + "/_site/404.html"; - -const ADDON_PAGE = __dirname + "/_site/addon.html"; -const COFFEE_PAGE = __dirname + "/_site/coffee.html"; -const ADDON_REPLACE_TOKEN = (token) => `%${token}%`; -const ADDON_FIELD_REPLACE = ["url", "name", "description", "authors", "header_img"]; - -app.get(["/coffee", "/teapot"], async (req, res) => { - let data = await readFile(COFFEE_PAGE, "utf8"); - - const titleEl = data.match(/(.+)<\/title>/); - if (titleEl) { - const titleStr = titleEl[1]; - const titleSplit = titleStr.split(" - "); - titleSplit[0] = req.path.includes("teapot") ? "Teapot" : "Coffee"; - data = data.replace(/<title>.+<\/title>/, `<title>${titleSplit.join(" - ")}`); - } - - res.status(418).send(data); - res.end(); -}); - -/** - * @typedef {[string, boolean, number?]} Extra - */ - -/** - * @type {Extra[]} - */ -const EXTRACT = [ - ["title", true], - ["permalink", true], - ["comments", true], - ["comments-id", true], - ["header-img", true], - ["discontinued", true], - ["long_text", false], - ["changelog", false, 1, true], - ["single-changelog", true], - ["expanded-changelog", true], - ["downloads", false, 2], - ["download", false], - ["main_changelog", true], -]; - -function cleanLine(line) { - if (line.startsWith('"')) line = line.substring(1); - if (line.endsWith('"')) line = line.slice(0, -1); - return line; -} - -/** - * definitions - * @param {string[]} input lines - * @param {Extra} extra extra def - * - * @return {{[tag]: string} | undefined} - */ -function extract(input, [tag, oneline, acceptedEmptyLines, isList]) { - const start = input.findIndex((l) => l.startsWith(`${tag}:`)); - if (start === -1) return undefined; - let i = start; - - if (oneline) return cleanLine(input[i].replace(`${tag}:`, "").trim()); - - acceptedEmptyLines ??= 1; - - let res = input[i].replace(`${tag}:`, ""); - i++; - - for (let emptyLines = 0; i < input.length; ++i) { - line = input[i]; - - if (!line.trim() === "") emptyLines = 0; - else emptyLines++; - - if ((isList && i > 0 && !/^\s/.test(line)) || emptyLines >= acceptedEmptyLines) break; - res += "\n" + line; - } - - return cleanLine(res.trim()); -} - -const EXTRACTED_POSTS_PATH = `${__dirname}/posts.json`; -let postsMap = undefined; -let postsMapLoading = false; - -async function generatePostJSON() { - if (postsMapLoading) return Promise.reject(new Error("Loading")); - if (!!postsMap) return Promise.resolve(postsMap); - - postsMapLoading = true; - - const dirPosts = `${__dirname}/_posts`; - const dirs = await readdir(dirPosts, { withFileTypes: true }); - const mdFiles = dirs.filter( - (e) => e.isFile() && e.name.endsWith(".md") && !e.name.startsWith("_"), - ); - const mdContents = await Promise.all( - mdFiles.map((e) => Promise.all([e, readFile(`${dirPosts}/${e.name}`, "utf8")])), - ); - - const result = mdContents - .map(([e, md]) => { - const tmp = { - name: parse(e.name).name, - }; - - const lines = md.split("\n").filter((l) => l.trim() !== "---"); - EXTRACT.forEach((e) => { - const extracted = extract(lines, e); - if ( - ["long_text", "downloads", "main_changelog"].indexOf(e[0]) !== -1 && - !!extracted - ) - tmp[e[0]] = DOMPurify.sanitize(extracted); - else tmp[e[0]] = extracted; - }); - - return tmp; - }) - .reduce((acc, cur) => { - acc[cur.name] = cur; - return acc; - }, {}); - - postsMap = result; - postsMapLoading = false; - - await writeFile(EXTRACTED_POSTS_PATH, JSON.stringify(result)); - - return result; -} - -app.get("/posts.json", cors(corsOptions), (_, res) => { - generatePostJSON() - .then(() => res.sendFile(EXTRACTED_POSTS_PATH)) - .catch((err) => res.status(403).send(err.message).end()); -}); - -function transformData(obj) { - if (obj === null) return {}; - if (!Array.isArray(obj) || typeof obj[0] === "string") return obj; - - return obj.reduce( - (acc, cur) => ({ - ...acc, - [Object.keys(cur)[0]]: transformData(Object.values(cur)[0]), - }), - {}, - ); -} - -/** - * @param {String} filePath path to the changelog - * @returns {Promise} JS Object returned - */ -async function extractChangelog(filePath) { - const data = await readFile(filePath, "utf8"); - // Split the file contents into an array of lines - const lines = data.trim().split("\n"); - - // Remove the first two and last three lines - lines.splice(0, 2); - lines.splice(-3); - - // Join the remaining lines into a single string - const yamlString = lines.join("\n"); - - // Parse the YAML string into a JavaScript object - const obj = await yaml.load(yamlString); - const root = Object.values(obj)[0]; - return transformData(root); -} - -const CHANGELOGS_DIR = "./changelogs"; -const CHANGELOGS = ["compliance32.html", "dungeons.html"]; -const CHANGELOGS_OBJ = []; -const CHANGELOGS_LOADING = []; - -CHANGELOGS.forEach((changelog, i) => { - CHANGELOGS_LOADING[i] = true; - - const changelogPath = join(__dirname, CHANGELOGS_DIR, changelog); - const stem = parse(changelogPath).name; - - extractChangelog(changelogPath).then((obj) => { - CHANGELOGS_OBJ[i] = obj; - CHANGELOGS_LOADING[i] = false; - }); - - app.get(`/changelogs/${stem}.json`, cors(corsOptions), (_, res) => { - if (CHANGELOGS_LOADING[i]) { - res.status(403).send("loading").end(); - return; - } - - return res.json(CHANGELOGS_OBJ[i]).end(); - }); -}); - -app.use( - express.static(__dirname + "/_site/", { - extensions: ["html", "htm"], - }), -); - -// redirect addon page because it is a "template" page -app.get("/addon", (req, res, next) => { - if (req.url === "/addon") { - req.url = "/addons"; - res.redirect("/addons"); - } - next(); -}); -app.get("/addon.html", (req, res, next) => { - req.url = "/addons"; - res.redirect("/addons"); - next(); -}); - -app.get("/addon/", (req, res, next) => { - if (req.url === "/addon/") { - req.url = "/addons"; - res.redirect("/addons"); - } - next(); -}); - -app.get("/addons/", (req, res, next) => { - if (req.url == "/addons/") { - req.url = "/addons"; - res.redirect("/addons"); - } - next(); -}); - -app.get("/addons/:name/?", async (req, res) => { - const addon = await fetch(`https://api.faithfulpack.net/v2/addons/${req.params.name}/all`) - .then((r) => r.json()) - // invalid slug, not our problem, move on - .catch(() => res.sendFile(NOT_FOUND_PAGE)); - - if (!addon || !addon.approval || addon.approval.status !== "approved") - return res.sendFile(NOT_FOUND_PAGE); - - const users = await fetch( - `https://api.faithfulpack.net/v2/users/${addon.authors.join(",")}`, - ).then((r) => r.json()); - - const authors = Array.isArray(users) ? users : [users]; - const headerURL = - addon.files.find((el) => el.use === "header")?.source || "/image/home/og_logo.png"; - - const authorArray = authors.map((user) => user.username).filter((e) => e); - - const dataReplaced = ADDON_FIELD_REPLACE.reduce((acc, token) => { - acc[token] = addon[token]; - return acc; - }, {}); - - dataReplaced.authors = authorArray.join(", "); - dataReplaced.url = `${req.originalUrl}`; - - // load addon post page - let data = await readFile(ADDON_PAGE, "utf8"); - - // replace header if existing - if (headerURL) dataReplaced.header_img = headerURL; - - // replace all header values - ADDON_FIELD_REPLACE.forEach((token) => { - data = data.replaceAll(ADDON_REPLACE_TOKEN(token), dataReplaced[token]); - }); - - // replace script value - //! please use Node v15+ for support of replaceAll - data = data - .replaceAll("'" + ADDON_REPLACE_TOKEN("data.addon") + "'", JSON.stringify(addon)) - .replaceAll("'" + ADDON_REPLACE_TOKEN("data.authors") + "'", JSON.stringify(authors)) - .replaceAll("'" + ADDON_REPLACE_TOKEN("data.slug") + "'", JSON.stringify(req.params.name)) - .replaceAll("'" + ADDON_REPLACE_TOKEN("data.files") + "'", JSON.stringify(addon.files)); - - res.send(data); - res.end(); -}); - -app.use((_req, res) => res.status(404).sendFile(NOT_FOUND_PAGE)); - -app.listen(process.env.PORT, () => - console.log(`Website listening at http://localhost:${process.env.PORT} in ${__dirname}`), -); +const express = require("express"); +const cors = require("cors"); +const { readdir, readFile, writeFile } = require("fs").promises; +const createDOMPurify = require("dompurify"); +const { JSDOM } = require("jsdom"); +const { parse, join } = require("path"); +const yaml = require("js-yaml"); + +require("dotenv").config(); + +const corsOptions = { + origin: "*", + methods: [], + allowedHeaders: [], + exposedHeaders: [], + credentials: true, +}; + +const DOMPurify = createDOMPurify(new JSDOM("").window); + +const app = express(); +app.disable("x-powered-by"); + +const NOT_FOUND_PAGE = __dirname + "/_site/404.html"; + +const ADDON_PAGE = __dirname + "/_site/addon.html"; +const COFFEE_PAGE = __dirname + "/_site/coffee.html"; +const ADDON_REPLACE_TOKEN = (token) => `%${token}%`; +const ADDON_FIELD_REPLACE = ["url", "name", "description", "authors", "header_img"]; + +app.get(["/coffee", "/teapot"], async (req, res) => { + let data = await readFile(COFFEE_PAGE, "utf8"); + + const titleEl = data.match(/(.+)<\/title>/); + if (titleEl) { + const titleStr = titleEl[1]; + const titleSplit = titleStr.split(" - "); + titleSplit[0] = req.path.includes("teapot") ? "Teapot" : "Coffee"; + data = data.replace(/<title>.+<\/title>/, `<title>${titleSplit.join(" - ")}`); + } + + res.status(418).send(data); + res.end(); +}); + +/** + * @typedef {[string, boolean, number?]} Extra + */ + +/** + * @type {Extra[]} + */ +const EXTRACT = [ + ["title", true], + ["permalink", true], + ["comments", true], + ["comments-id", true], + ["header-img", true], + ["discontinued", true], + ["long_text", false], + ["changelog", false, 1, true], + ["single-changelog", true], + ["expanded-changelog", true], + ["downloads", false, 2], + ["download", false], + ["main_changelog", true], +]; + +function cleanLine(line) { + if (line.startsWith('"')) line = line.substring(1); + if (line.endsWith('"')) line = line.slice(0, -1); + return line; +} + +/** + * definitions + * @param {string[]} input lines + * @param {Extra} extra extra def + * + * @return {{[tag]: string} | undefined} + */ +function extract(input, [tag, oneline, acceptedEmptyLines, isList]) { + const start = input.findIndex((l) => l.startsWith(`${tag}:`)); + if (start === -1) return undefined; + let i = start; + + if (oneline) return cleanLine(input[i].replace(`${tag}:`, "").trim()); + + acceptedEmptyLines ??= 1; + + let res = input[i].replace(`${tag}:`, ""); + i++; + + for (let emptyLines = 0; i < input.length; ++i) { + line = input[i]; + + if (!line.trim() === "") emptyLines = 0; + else emptyLines++; + + if ((isList && i > 0 && !/^\s/.test(line)) || emptyLines >= acceptedEmptyLines) break; + res += "\n" + line; + } + + return cleanLine(res.trim()); +} + +const EXTRACTED_POSTS_PATH = `${__dirname}/posts.json`; +let postsMap = undefined; +let postsMapLoading = false; + +async function generatePostJSON() { + if (postsMapLoading) return Promise.reject(new Error("Loading")); + if (!!postsMap) return Promise.resolve(postsMap); + + postsMapLoading = true; + + const dirPosts = `${__dirname}/_posts`; + const dirs = await readdir(dirPosts, { withFileTypes: true }); + const mdFiles = dirs.filter( + (e) => e.isFile() && e.name.endsWith(".md") && !e.name.startsWith("_"), + ); + const mdContents = await Promise.all( + mdFiles.map((e) => Promise.all([e, readFile(`${dirPosts}/${e.name}`, "utf8")])), + ); + + const result = mdContents + .map(([e, md]) => { + const tmp = { + name: parse(e.name).name, + }; + + const lines = md.split("\n").filter((l) => l.trim() !== "---"); + EXTRACT.forEach((e) => { + const extracted = extract(lines, e); + if (["long_text", "downloads", "main_changelog"].indexOf(e[0]) !== -1 && !!extracted) + tmp[e[0]] = DOMPurify.sanitize(extracted); + else tmp[e[0]] = extracted; + }); + + return tmp; + }) + .reduce((acc, cur) => { + acc[cur.name] = cur; + return acc; + }, {}); + + postsMap = result; + postsMapLoading = false; + + await writeFile(EXTRACTED_POSTS_PATH, JSON.stringify(result)); + + return result; +} + +app.get("/posts.json", cors(corsOptions), (_, res) => { + generatePostJSON() + .then(() => res.sendFile(EXTRACTED_POSTS_PATH)) + .catch((err) => res.status(403).send(err.message).end()); +}); + +function transformData(obj) { + if (obj === null) return {}; + if (!Array.isArray(obj) || typeof obj[0] === "string") return obj; + + return obj.reduce( + (acc, cur) => ({ + ...acc, + [Object.keys(cur)[0]]: transformData(Object.values(cur)[0]), + }), + {}, + ); +} + +/** + * @param {String} filePath path to the changelog + * @returns {Promise} JS Object returned + */ +async function extractChangelog(filePath) { + const data = await readFile(filePath, "utf8"); + // Split the file contents into an array of lines + const lines = data.trim().split("\n"); + + // Remove the first two and last three lines + lines.splice(0, 2); + lines.splice(-3); + + // Join the remaining lines into a single string + const yamlString = lines.join("\n"); + + // Parse the YAML string into a JavaScript object + const obj = await yaml.load(yamlString); + const root = Object.values(obj)[0]; + return transformData(root); +} + +const CHANGELOGS_DIR = "./changelogs"; +const CHANGELOGS = ["compliance32.html", "dungeons.html"]; +const CHANGELOGS_OBJ = []; +const CHANGELOGS_LOADING = []; + +CHANGELOGS.forEach((changelog, i) => { + CHANGELOGS_LOADING[i] = true; + + const changelogPath = join(__dirname, CHANGELOGS_DIR, changelog); + const stem = parse(changelogPath).name; + + extractChangelog(changelogPath).then((obj) => { + CHANGELOGS_OBJ[i] = obj; + CHANGELOGS_LOADING[i] = false; + }); + + app.get(`/changelogs/${stem}.json`, cors(corsOptions), (_, res) => { + if (CHANGELOGS_LOADING[i]) { + res.status(403).send("loading").end(); + return; + } + + return res.json(CHANGELOGS_OBJ[i]).end(); + }); +}); + +app.use( + express.static(__dirname + "/_site/", { + extensions: ["html", "htm"], + }), +); + +// redirect addon page because it is a "template" page +app.get("/addon", (req, res, next) => { + if (req.url === "/addon") { + req.url = "/addons"; + res.redirect("/addons"); + } + next(); +}); +app.get("/addon.html", (req, res, next) => { + req.url = "/addons"; + res.redirect("/addons"); + next(); +}); + +app.get("/addon/", (req, res, next) => { + if (req.url === "/addon/") { + req.url = "/addons"; + res.redirect("/addons"); + } + next(); +}); + +app.get("/addons/", (req, res, next) => { + if (req.url == "/addons/") { + req.url = "/addons"; + res.redirect("/addons"); + } + next(); +}); + +app.get("/addons/:name/?", async (req, res) => { + const addon = await fetch(`https://api.faithfulpack.net/v2/addons/${req.params.name}/all`) + .then((r) => r.json()) + // invalid slug, not our problem, move on + .catch(() => res.sendFile(NOT_FOUND_PAGE)); + + if (!addon || !addon.approval || addon.approval.status !== "approved") + return res.sendFile(NOT_FOUND_PAGE); + + const users = await fetch( + `https://api.faithfulpack.net/v2/users/${addon.authors.join(",")}`, + ).then((r) => r.json()); + + const authors = Array.isArray(users) ? users : [users]; + const headerURL = + addon.files.find((el) => el.use === "header")?.source || "/image/home/og_logo.png"; + + const authorArray = authors.map((user) => user.username).filter((e) => e); + + const dataReplaced = ADDON_FIELD_REPLACE.reduce((acc, token) => { + acc[token] = addon[token]; + return acc; + }, {}); + + dataReplaced.authors = authorArray.join(", "); + dataReplaced.url = `${req.originalUrl}`; + + // load addon post page + let data = await readFile(ADDON_PAGE, "utf8"); + + // replace header if existing + if (headerURL) dataReplaced.header_img = headerURL; + + // replace all header values + ADDON_FIELD_REPLACE.forEach((token) => { + data = data.replaceAll(ADDON_REPLACE_TOKEN(token), dataReplaced[token]); + }); + + // replace script value + //! please use Node v15+ for support of replaceAll + data = data + .replaceAll("'" + ADDON_REPLACE_TOKEN("data.addon") + "'", JSON.stringify(addon)) + .replaceAll("'" + ADDON_REPLACE_TOKEN("data.authors") + "'", JSON.stringify(authors)) + .replaceAll("'" + ADDON_REPLACE_TOKEN("data.slug") + "'", JSON.stringify(req.params.name)) + .replaceAll("'" + ADDON_REPLACE_TOKEN("data.files") + "'", JSON.stringify(addon.files)); + + res.send(data); + res.end(); +}); + +app.use((_req, res) => res.status(404).sendFile(NOT_FOUND_PAGE)); + +app.listen(process.env.PORT, () => + console.log(`Website listening at http://localhost:${process.env.PORT} in ${__dirname}`), +); diff --git a/js/404.js b/js/404.js index 59f0544f..3101f6aa 100644 --- a/js/404.js +++ b/js/404.js @@ -1,34 +1,34 @@ -const FRAME_TIME = 12; -const tnt = document.getElementById('tnt'); -const diamond = document.getElementById('diamond'); -const explosion = document.getElementById('explosion'); -let exploded = false; - -function sleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -document.body.classList.add('error') - -async function boom() { - if (!exploded) { - for (let i = 0; i < 8; i++) { - await sleep(FRAME_TIME*25); - if (i % 2 === 0) tnt.src = "../image/404/tnt_side_on.png"; - else tnt.src = "../image/404/tnt_side.png"; - } - explosion.classList.remove("hidden"); - tnt.classList.add("hidden"); - for (let i = 0; i <= 15; i++) { - await sleep(FRAME_TIME*1.3); - explosion.src = "../image/404/explosion_" + i + ".png"; - } - diamond.classList.remove("hidden"); - explosion.classList.add("hidden"); - exploded = true; - } else { - tnt.classList.remove("hidden"); - diamond.classList.add("hidden"); - exploded = false; - } -} \ No newline at end of file +const FRAME_TIME = 12; +const tnt = document.getElementById("tnt"); +const diamond = document.getElementById("diamond"); +const explosion = document.getElementById("explosion"); +let exploded = false; + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +document.body.classList.add("error"); + +async function boom() { + if (!exploded) { + for (let i = 0; i < 8; i++) { + await sleep(FRAME_TIME * 25); + if (i % 2 === 0) tnt.src = "../image/404/tnt_side_on.png"; + else tnt.src = "../image/404/tnt_side.png"; + } + explosion.classList.remove("hidden"); + tnt.classList.add("hidden"); + for (let i = 0; i <= 15; i++) { + await sleep(FRAME_TIME * 1.3); + explosion.src = "../image/404/explosion_" + i + ".png"; + } + diamond.classList.remove("hidden"); + explosion.classList.add("hidden"); + exploded = true; + } else { + tnt.classList.remove("hidden"); + diamond.classList.add("hidden"); + exploded = false; + } +} diff --git a/js/addons/addon-grid.js b/js/addons/addon-grid.js index 68fcb816..e89550c6 100644 --- a/js/addons/addon-grid.js +++ b/js/addons/addon-grid.js @@ -1,5 +1,5 @@ export default { - name: 'addon-grid', + name: "addon-grid", template: `
@@ -58,23 +58,23 @@ export default { props: { addons: { type: Object, - required: true + required: true, }, addonsFav: { type: Object, - required: true + required: true, }, action: { type: Function, - required: true + required: true, }, icon: { type: String, - required: true + required: true, }, iconColor: { type: String, - required: true + required: true, }, sort: { type: String, @@ -84,31 +84,31 @@ export default { }, data() { return { - optifine: '/image/icon/optifine.png', - bedrock: '/image/icon/bedrock.png', - java: '/image/icon/java.png', - } + optifine: "/image/icon/optifine.png", + bedrock: "/image/icon/bedrock.png", + java: "/image/icon/java.png", + }; }, computed: { sortedAddons() { const sorted = Object.values(this.addons).sort((a, b) => { - const an = a.name.trim().toLowerCase() - const bn = b.name.trim().toLowerCase() + const an = a.name.trim().toLowerCase(); + const bn = b.name.trim().toLowerCase(); const ad = a.last_updated || 0; const bd = b.last_updated || 0; switch (this.sort) { case "na": - return an === bn ? 0 : (an > bn ? 1 : -1) + return an === bn ? 0 : an > bn ? 1 : -1; case "nd": - return an === bn ? 0 : (an > bn ? -1 : 1) + return an === bn ? 0 : an > bn ? -1 : 1; case "da": - return ad === bd ? 0 : (ad > bd ? 1 : -1) + return ad === bd ? 0 : ad > bd ? 1 : -1; case "dd": default: - return ad === bd ? 0 : (ad < bd ? 1 : -1) + return ad === bd ? 0 : ad < bd ? 1 : -1; } - }) + }); return sorted; }, - } -} \ No newline at end of file + }, +}; diff --git a/js/addons/addon-page.js b/js/addons/addon-page.js index 9d79d3e9..69cdb182 100644 --- a/js/addons/addon-page.js +++ b/js/addons/addon-page.js @@ -1,11 +1,11 @@ /* global fetch */ -const AddonGrid = () => import('./addon-grid.js') +const AddonGrid = () => import("./addon-grid.js"); export default { - name: 'addon-page', + name: "addon-page", components: { - AddonGrid + AddonGrid, }, template: ` @@ -112,53 +112,59 @@ export default { { label: "Date (Newest to Oldest)", value: "dd" }, { label: "Date (Oldest to Newest)", value: "da" }, { label: "Name (A-Z)", value: "na" }, - { label: "Name (Z-A)", value: "nd" } + { label: "Name (Z-A)", value: "nd" }, ]; return { addons: {}, searchedAddons: {}, - search: '', + search: "", loading: true, - optifine: '/image/icon/optifine.png', - bedrock: '/image/icon/bedrock.png', - java: '/image/icon/java.png', - editions: ['Java', 'Bedrock'], - res: ['32x', '64x'], - selectedEditions: ['Java', 'Bedrock'], - selectedRes: ['32x', '64x'], + optifine: "/image/icon/optifine.png", + bedrock: "/image/icon/bedrock.png", + java: "/image/icon/java.png", + editions: ["Java", "Bedrock"], + res: ["32x", "64x"], + selectedEditions: ["Java", "Bedrock"], + selectedRes: ["32x", "64x"], fav: {}, resultCount: 0, sortMethods, currentSort: sortMethods[0].value, - } + }; }, methods: { startSearch() { if ( - this.search === '' && - this.editions.length + this.res.length === this.selectedEditions.length + this.selectedRes.length + this.search === "" && + this.editions.length + this.res.length === + this.selectedEditions.length + this.selectedRes.length ) - this.searchedAddons = this.addons + this.searchedAddons = this.addons; else { - this.searchedAddons = {} + this.searchedAddons = {}; for (const addonID in this.addons) { - if (!this.addons[addonID].name.toLowerCase().includes(this.search.toLowerCase()) && this.search !== '') continue - const localRes = [] - const localEditions = [] + if ( + !this.addons[addonID].name.toLowerCase().includes(this.search.toLowerCase()) && + this.search !== "" + ) + continue; + const localRes = []; + const localEditions = []; // split types of an addon (res + edition : res & edition) - const tags = this.addons[addonID].options.tags + const tags = this.addons[addonID].options.tags; for (let tagIndex = 0; tagIndex < tags.length; tagIndex++) { - if (this.editions.includes(tags[tagIndex])) localEditions.push(tags[tagIndex]) - if (this.res.includes(tags[tagIndex])) localRes.push(tags[tagIndex]) + if (this.editions.includes(tags[tagIndex])) localEditions.push(tags[tagIndex]); + if (this.res.includes(tags[tagIndex])) localRes.push(tags[tagIndex]); } // search if edition then check if res for (let i = 0; localEditions[i]; i++) { if (this.selectedEditions.includes(localEditions[i])) { for (let j = 0; localRes[j]; j++) { - if (this.selectedRes.includes(localRes[j])) this.searchedAddons[addonID] = this.addons[addonID] + if (this.selectedRes.includes(localRes[j])) + this.searchedAddons[addonID] = this.addons[addonID]; } } } @@ -167,42 +173,42 @@ export default { console.log("I made it here!"); this.resultCount = Object.keys(this.searchedAddons).length; - this.$forceUpdate() // force update (because it can be a bit long to process) + this.$forceUpdate(); // force update (because it can be a bit long to process) }, clearSearch() { - this.search = '' - this.startSearch() + this.search = ""; + this.startSearch(); }, checkFav(addon) { if (!this.fav[addon.id]) { - this.fav[addon.id] = addon - window.localStorage.setItem('favAddons', JSON.stringify(this.fav)) + this.fav[addon.id] = addon; + window.localStorage.setItem("favAddons", JSON.stringify(this.fav)); } else { - delete this.fav[addon.id] - window.localStorage.setItem('favAddons', JSON.stringify(this.fav)) + delete this.fav[addon.id]; + window.localStorage.setItem("favAddons", JSON.stringify(this.fav)); } - this.$forceUpdate() - } + this.$forceUpdate(); + }, }, computed: { results() { return this.resultCount === 1 ? "result" : "results"; - } + }, }, created() { - fetch('https://api.faithfulpack.net/v2/addons/approved') + fetch("https://api.faithfulpack.net/v2/addons/approved") .then((res) => res.json()) .then((data) => { - this.addons = data - this.loading = false + this.addons = data; + this.loading = false; this.resultCount = data.length; - for (const addonID in this.addons) this.addons[addonID].id = addonID // fix missing ID (property value) + for (const addonID in this.addons) this.addons[addonID].id = addonID; // fix missing ID (property value) - this.searchedAddons = this.addons - }) + this.searchedAddons = this.addons; + }); - this.fav = JSON.parse(window.localStorage.getItem('favAddons') || '{}') - } -} + this.fav = JSON.parse(window.localStorage.getItem("favAddons") || "{}"); + }, +}; diff --git a/js/addons/addon-post-modal.js b/js/addons/addon-post-modal.js index 49d7d513..51c1fb9b 100644 --- a/js/addons/addon-post-modal.js +++ b/js/addons/addon-post-modal.js @@ -1,7 +1,7 @@ /* global Vuetify */ export default { - name: 'addon-modal', + name: "addon-modal", template: ` import('./addon-post.js') - -document.addEventListener("DOMContentLoaded", () => { - const v = new Vue({ - components: { - AddonPost - }, - el: "#app", - vuetify: new Vuetify() - }) -}) +/* global Vue, VueRouter, Vuetify */ + +Vue.config.devtools = location.hostname === "localhost" || location.hostname === "127.0.0.1"; + +const AddonPost = () => import("./addon-post.js"); + +document.addEventListener("DOMContentLoaded", () => { + const v = new Vue({ + components: { + AddonPost, + }, + el: "#app", + vuetify: new Vuetify(), + }); +}); diff --git a/js/addons/addon-post.js b/js/addons/addon-post.js index 1f281f41..598dd0b4 100644 --- a/js/addons/addon-post.js +++ b/js/addons/addon-post.js @@ -1,11 +1,11 @@ /* global fetch, marked */ -const addonModal = () => import('./addon-post-modal.js') +const addonModal = () => import("./addon-post-modal.js"); export default { - name: 'addon-page', + name: "addon-page", components: { - addonModal + addonModal, }, template: ` el.use === 'header')[0].source + return this.files.filter((el) => el.use === "header")[0].source; }, getCarousel() { - return this.files.filter((el) => el.use === 'carousel' || el.use === 'screenshot').map((el) => el.source) + return this.files + .filter((el) => el.use === "carousel" || el.use === "screenshot") + .map((el) => el.source); }, getDownloads() { - return this.files.filter((el) => el.use === 'download') + return this.files.filter((el) => el.use === "download"); }, search_authors() { this.addon.authors.forEach((authorID) => { fetch(`https://api.faithfulpack.net/v2/users/${authorID}`) .then((response) => response.json()) .then((author) => { - this.authors.push(author) - }) - }) - } + this.authors.push(author); + }); + }); + }, }, beforeMount() { if (!window.slug && this.$route) { fetch(`https://api.faithfulpack.net/v2/addons/${window.slug}`) - .then((response) => response.json()) - .then((data) => this.addon = data[0]) - .then(() => { - this.search_authors() - }) - .then(() => { - fetch(`https://api.faithfulpack.net/v2/addons/${this.addon.id}`) - .then((response) => response.json()) - .then((data) => this.files = data) - }) - .finally(() => { - this.loading = false - window.scrollTo(0, 0) - }) - .catch((err) => { - console.error(err) - this.addon = {} - this.loading = false - window.scrollTo(0, 0) - }) + .then((response) => response.json()) + .then((data) => (this.addon = data[0])) + .then(() => { + this.search_authors(); + }) + .then(() => { + fetch(`https://api.faithfulpack.net/v2/addons/${this.addon.id}`) + .then((response) => response.json()) + .then((data) => (this.files = data)); + }) + .finally(() => { + this.loading = false; + window.scrollTo(0, 0); + }) + .catch((err) => { + console.error(err); + this.addon = {}; + this.loading = false; + window.scrollTo(0, 0); + }); } else { - this.addon = window.addon - this.search_authors() - this.files = window.files + this.addon = window.addon; + this.search_authors(); + this.files = window.files; - this.loading = false - window.scrollTo(0, 0) + this.loading = false; + window.scrollTo(0, 0); } - } -} + }, +}; diff --git a/js/addons/index.js b/js/addons/index.js index 276e48af..916e7a60 100644 --- a/js/addons/index.js +++ b/js/addons/index.js @@ -1,18 +1,18 @@ /* global Vue, VueRouter, Vuetify */ document.addEventListener("DOMContentLoaded", () => { - Vue.config.devtools = location.hostname === 'localhost' || location.hostname === '127.0.0.1' + Vue.config.devtools = location.hostname === "localhost" || location.hostname === "127.0.0.1"; - const AddonPage = () => import('./addon-page.js') + const AddonPage = () => import("./addon-page.js"); const routes = [ - { path: '/', component: AddonPage, name: 'addon-page' }, - { path: '*', redirect: '/' } - ] + { path: "/", component: AddonPage, name: "addon-page" }, + { path: "*", redirect: "/" }, + ]; const router = new VueRouter({ routes, - }) + }); const v = new Vue({ router, @@ -21,13 +21,13 @@ document.addEventListener("DOMContentLoaded", () => { theme: { themes: { light: { - primary: '#FFFFFF', + primary: "#FFFFFF", }, dark: { - primary: '#FFFFFF', - } - } - } - }) - }) -}) \ No newline at end of file + primary: "#FFFFFF", + }, + }, + }, + }), + }); +}); diff --git a/js/defaultFunctionality.js b/js/defaultFunctionality.js index a7dc6ae4..01ea8e74 100644 --- a/js/defaultFunctionality.js +++ b/js/defaultFunctionality.js @@ -1,145 +1,149 @@ /* global Element, Event */ Element.prototype.siblingElements = function () { - if (this.parentNode === null) return [] + if (this.parentNode === null) return []; - return [...this.parentNode.children].filter((el) => el !== this) -} + return [...this.parentNode.children].filter((el) => el !== this); +}; -const DROPDOWN_SHOW_CLASS = 'show' +const DROPDOWN_SHOW_CLASS = "show"; // at initialization document.querySelectorAll('[data-toggle="dropdown"]').forEach((item) => { // add click listener to toggle dropdowns - item.addEventListener('click', () => { - toggleDropdown(item) - }) -}) + item.addEventListener("click", () => { + toggleDropdown(item); + }); +}); // function made to toggle my item and untoggle all others -function toggleDropdown (item) { - const itemExpanded = item.parentNode.classList.contains(DROPDOWN_SHOW_CLASS) - - if (!itemExpanded) { // if I am not expanded, go untoggle all other siblings - item.parentNode.siblingElements().filter((el) => el.classList.contains(DROPDOWN_SHOW_CLASS)).forEach((otherParent) => { - otherParent.classList.remove(DROPDOWN_SHOW_CLASS) - }) +function toggleDropdown(item) { + const itemExpanded = item.parentNode.classList.contains(DROPDOWN_SHOW_CLASS); + + if (!itemExpanded) { + // if I am not expanded, go untoggle all other siblings + item.parentNode + .siblingElements() + .filter((el) => el.classList.contains(DROPDOWN_SHOW_CLASS)) + .forEach((otherParent) => { + otherParent.classList.remove(DROPDOWN_SHOW_CLASS); + }); } // then toggle me - item.parentNode.classList.toggle(DROPDOWN_SHOW_CLASS) + item.parentNode.classList.toggle(DROPDOWN_SHOW_CLASS); } document.querySelectorAll('[data-toggle="collapse"]').forEach((item) => { - item.dataset.expanded = false - item.addEventListener('click', () => { - toggleMenu(item) - }) -}) - -function toggleMenu (item) { - let expandNow = true - if (item.dataset.expanded === 'true') expandNow = false - - item.classList.toggle('collapsed', expandNow) - getNextElement(item, item.dataset.target).classList.toggle('show', expandNow) - item.dataset.expanded = expandNow + item.dataset.expanded = false; + item.addEventListener("click", () => { + toggleMenu(item); + }); +}); + +function toggleMenu(item) { + let expandNow = true; + if (item.dataset.expanded === "true") expandNow = false; + + item.classList.toggle("collapsed", expandNow); + getNextElement(item, item.dataset.target).classList.toggle("show", expandNow); + item.dataset.expanded = expandNow; } -function getNextElement (element, selector) { - let next = element.nextElementSibling +function getNextElement(element, selector) { + let next = element.nextElementSibling; while (next) { - if (next.matches(selector)) return next - next = next.nextElementSibling + if (next.matches(selector)) return next; + next = next.nextElementSibling; } } document.querySelectorAll('[data-ride="carousel"]').forEach((item) => { - const indicators = item.querySelector('.carousel-indicators').children - const itemCount = indicators.length - let currentItem = 0 - let blocking = false - - item.querySelector('[data-slide="prev"]').addEventListener('click', (e) => { - e.preventDefault() - if (currentItem === 0) goToSlide(item, itemCount - 1) - else goToSlide(item, currentItem - 1) - }) - - item.querySelector('[data-slide="next"]').addEventListener('click', (e) => { - e.preventDefault() - if (currentItem === itemCount - 1) goToSlide(item, 0) - else goToSlide(item, currentItem + 1) - }) - - setTimeout(function loop () { - if (currentItem === itemCount - 1) goToSlide(item, 0) - else goToSlide(item, currentItem + 1) - setTimeout(loop, 5000) - }, 5000) + const indicators = item.querySelector(".carousel-indicators").children; + const itemCount = indicators.length; + let currentItem = 0; + let blocking = false; + + item.querySelector('[data-slide="prev"]').addEventListener("click", (e) => { + e.preventDefault(); + if (currentItem === 0) goToSlide(item, itemCount - 1); + else goToSlide(item, currentItem - 1); + }); + + item.querySelector('[data-slide="next"]').addEventListener("click", (e) => { + e.preventDefault(); + if (currentItem === itemCount - 1) goToSlide(item, 0); + else goToSlide(item, currentItem + 1); + }); + + setTimeout(function loop() { + if (currentItem === itemCount - 1) goToSlide(item, 0); + else goToSlide(item, currentItem + 1); + setTimeout(loop, 5000); + }, 5000); for (const child of indicators) { - child.addEventListener('click', () => { - goToSlide(item, parseInt(child.dataset.slideTo, 10)) - }) + child.addEventListener("click", () => { + goToSlide(item, parseInt(child.dataset.slideTo, 10)); + }); } - function goToSlide (carousel, index) { + function goToSlide(carousel, index) { if (!blocking && index !== currentItem) { - blocking = true + blocking = true; - const carouselIIndicators = carousel.querySelector('.carousel-indicators').children - const carouselItems = carousel.querySelector('.carousel-inner').children + const carouselIIndicators = carousel.querySelector(".carousel-indicators").children; + const carouselItems = carousel.querySelector(".carousel-inner").children; - carouselIIndicators.item(currentItem).classList.remove('active') - carouselIIndicators.item(index).classList.add('active') + carouselIIndicators.item(currentItem).classList.remove("active"); + carouselIIndicators.item(index).classList.add("active"); - let itemKeyLeftRight = '' - let itemKeyPrevNext = '' + let itemKeyLeftRight = ""; + let itemKeyPrevNext = ""; if (index > currentItem) { - itemKeyLeftRight = 'carousel-item-left' - itemKeyPrevNext = 'carousel-item-next' + itemKeyLeftRight = "carousel-item-left"; + itemKeyPrevNext = "carousel-item-next"; } else { - itemKeyLeftRight = 'carousel-item-right' - itemKeyPrevNext = 'carousel-item-prev' + itemKeyLeftRight = "carousel-item-right"; + itemKeyPrevNext = "carousel-item-prev"; } - carouselItems.item(index).classList.add(itemKeyPrevNext) - carouselItems.item(currentItem).classList.add(itemKeyLeftRight) + carouselItems.item(index).classList.add(itemKeyPrevNext); + carouselItems.item(currentItem).classList.add(itemKeyLeftRight); setTimeout(() => { - carouselItems.item(index).classList.remove(itemKeyPrevNext) - carouselItems.item(currentItem).classList.remove(itemKeyLeftRight) - carouselItems.item(index).classList.add('active') - carouselItems.item(currentItem).classList.remove('active') - currentItem = index - - blocking = false - }, 600) + carouselItems.item(index).classList.remove(itemKeyPrevNext); + carouselItems.item(currentItem).classList.remove(itemKeyLeftRight); + carouselItems.item(index).classList.add("active"); + carouselItems.item(currentItem).classList.remove("active"); + currentItem = index; + + blocking = false; + }, 600); } } -}) +}); // fix non centered icons -document.addEventListener('DOMContentLoaded', () => { - window.dispatchEvent(new Event('resize')) +document.addEventListener("DOMContentLoaded", () => { + window.dispatchEvent(new Event("resize")); // set sticky menu - const topNavbar = document.getElementById('topNavbar') - const topNavbarParent = topNavbar.parentElement + const topNavbar = document.getElementById("topNavbar"); + const topNavbarParent = topNavbar.parentElement; function changeTopNavbar() { - const topNavbarHeight = topNavbar.offsetHeight - const isScrolling = window.scrollY > (topNavbar.offsetTop + topNavbarHeight) - topNavbar.classList.toggle('fixed', isScrolling) + const topNavbarHeight = topNavbar.offsetHeight; + const isScrolling = window.scrollY > topNavbar.offsetTop + topNavbarHeight; + topNavbar.classList.toggle("fixed", isScrolling); if (isScrolling) { - topNavbarParent.style.paddingTop = topNavbarHeight + 'px' + topNavbarParent.style.paddingTop = topNavbarHeight + "px"; } else { - topNavbarParent.style.paddingTop = '0px' + topNavbarParent.style.paddingTop = "0px"; } } - changeTopNavbar() // Fix when reloading page already scrolled down, for example home page + changeTopNavbar(); // Fix when reloading page already scrolled down, for example home page - window.addEventListener('scroll', () => changeTopNavbar(), true) -}) + window.addEventListener("scroll", () => changeTopNavbar(), true); +}); diff --git a/js/download/download-line.js b/js/download/download-line.js index 1efe2123..9da6580e 100644 --- a/js/download/download-line.js +++ b/js/download/download-line.js @@ -79,7 +79,7 @@ export default { data() { return { showIcon: "➕", - } + }; }, methods: { getLocalizedDate(dateObj) { @@ -93,41 +93,46 @@ export default { }, handleOpen() { // change icon then pass back to download-table to unhide child - this.showIcon = this.showIcon === "➕" ? "➖" : "➕" - this.$emit('click') - } + this.showIcon = this.showIcon === "➕" ? "➖" : "➕"; + this.$emit("click"); + }, }, computed: { labelColor() { switch (this.item.file_type) { - case "Download": return "github" - case "R": return "green" - case "B": return "blue" - case "A": return "yellow" - case "Snapshot": return "black" - default: return "green" + case "Download": + return "github"; + case "R": + return "green"; + case "B": + return "blue"; + case "A": + return "yellow"; + case "Snapshot": + return "black"; + default: + return "green"; } }, labelText() { - if (this.item.file_type == "Download") return 'Download' - if (!this.item.file_version) return this.item.file_type - return this.item.file_type + this.item.file_version + if (this.item.file_type == "Download") return "Download"; + if (!this.item.file_version) return this.item.file_type; + return this.item.file_type + this.item.file_version; }, date() { - if (this.item.file_type === "GitHub") return - if (this.item.date) - return this.getLocalizedDate(new Date(this.item.date)); + if (this.item.file_type === "GitHub") return; + if (this.item.date) return this.getLocalizedDate(new Date(this.item.date)); // no other way to get dates - if (!this.curse || !this.curse.uploaded_at) return "Unknown" + if (!this.curse || !this.curse.uploaded_at) return "Unknown"; return this.getLocalizedDate(new Date(this.curse.uploaded_at.split("T")[0])); }, size() { - if (this.item.file_type === "GitHub") return + if (this.item.file_type === "GitHub") return; // some very old downloads have manual sizes - if (this.item.size) return this.item.size - if (!this.curse || !this.curse.filesize) return "Unknown" - return `${(this.curse.filesize / 1000000).toFixed(2)} MB` + if (this.item.size) return this.item.size; + if (!this.curse || !this.curse.filesize) return "Unknown"; + return `${(this.curse.filesize / 1000000).toFixed(2)} MB`; }, }, -} \ No newline at end of file +}; diff --git a/js/download/download-table.js b/js/download/download-table.js index 30f6beb8..058fbd6b 100644 --- a/js/download/download-table.js +++ b/js/download/download-table.js @@ -1,7 +1,7 @@ -const DownloadLine = () => import("./download-line.js") +const DownloadLine = () => import("./download-line.js"); export default { - name: "download-table", + name: "download-table", components: { DownloadLine, }, @@ -13,9 +13,9 @@ export default { files: { type: Object, required: true, - } + }, }, - template: ` + template: `
@@ -57,19 +57,19 @@ export default { data() { return { openStates: {}, - } + }; }, methods: { handleOpen(version) { - this.openStates[version] = !this.openStates[version] + this.openStates[version] = !this.openStates[version]; // doesn't trigger rerender of subelements - this.$forceUpdate() + this.$forceUpdate(); }, getCurseFile(item) { if (item.links.curse) { - const id = parseInt(item.links.curse.split('/').pop()) - return this.files.find((el) => el.id === id) + const id = parseInt(item.links.curse.split("/").pop()); + return this.files.find((el) => el.id === id); } }, }, -} +}; diff --git a/js/download/index.js b/js/download/index.js index 54340f0c..e0c12df3 100644 --- a/js/download/index.js +++ b/js/download/index.js @@ -1,12 +1,12 @@ /* global location, Vue, axios, getHTML */ -let cache = {} -const DownloadTable = () => import('./download-table.js') +let cache = {}; +const DownloadTable = () => import("./download-table.js"); document.addEventListener("DOMContentLoaded", () => { - Vue.config.devtools = location.hostname === 'localhost' || location.hostname === '127.0.0.1' + Vue.config.devtools = location.hostname === "localhost" || location.hostname === "127.0.0.1"; const v = new Vue({ - el: '#app', + el: "#app", components: { DownloadTable, }, @@ -74,49 +74,49 @@ document.addEventListener("DOMContentLoaded", () => { if (discontinued) this.discontinued[name].downloads = downloads; else this.alive[name][edition].downloads = downloads; }) - .catch(console.error) + .catch(console.error); fetch(`https://api.cfwidget.com/${curse}`) .then((res) => res.json()) .then(({ files }) => { if (discontinued) this.discontinued[name].files = files; else this.alive[name][edition].files = files; }) - .catch(console.error) + .catch(console.error); }, }, created() { Promise.all([ this.fetchData({ - json: 'faithful_java_32x', + json: "faithful_java_32x", curse: "436482", name: "Faithful 32x", - edition: "Java" + edition: "Java", }), this.fetchData({ - json: 'faithful_java_64x', + json: "faithful_java_64x", curse: "419139", name: "Faithful 64x", - edition: "Java" + edition: "Java", }), this.fetchData({ - json: 'faithful_bedrock_32x', + json: "faithful_bedrock_32x", curse: "507188", name: "Faithful 32x", edition: "Bedrock", }), this.fetchData({ - json: 'faithful_bedrock_64x', + json: "faithful_bedrock_64x", curse: "694024", name: "Faithful 64x", edition: "Bedrock", }), this.fetchData({ - json: 'faithful_dungeons_32x', + json: "faithful_dungeons_32x", curse: "501546", name: "Faithful 32x for Minecraft Dungeons", discontinued: true, }), - ]) - } - }) -}) + ]); + }, + }); +}); diff --git a/js/faq.js b/js/faq.js index d8d68f0b..00675838 100644 --- a/js/faq.js +++ b/js/faq.js @@ -7,7 +7,7 @@ document.addEventListener("DOMContentLoaded", () => { allFaqs: [], faqs: [], search: null, - } + }; }, template: `
@@ -40,27 +40,29 @@ document.addEventListener("DOMContentLoaded", () => { .replace(/in <#[^]+>/, "on our [Discord](https://discord.gg/sN9YRQbBv7)") // removes channel links .replace(/<[^]+>/, "") // removes pings .replace("()", ""), // removes stray parentheses left by removing pings) - ) + ); }, startSearch() { if (!this.search || this.search.length < 3) { - this.faqs = this.allFaqs - return + this.faqs = this.allFaqs; + return; } // partial searches count - this.faqs = this.allFaqs.filter((faq) => faq.question.toLowerCase().includes(this.search.toLowerCase())) - } + this.faqs = this.allFaqs.filter((faq) => + faq.question.toLowerCase().includes(this.search.toLowerCase()), + ); + }, }, computed: { filteredFaqs() { - return this.faqs.filter((v) => !v.discord) + return this.faqs.filter((v) => !v.discord); }, isDarkMode() { return ( - theme.currentTheme === 'dark' || - (theme.currentTheme === 'auto' && matchMedia('(prefers-color-scheme: dark)').matches) + theme.currentTheme === "dark" || + (theme.currentTheme === "auto" && matchMedia("(prefers-color-scheme: dark)").matches) ); - } + }, }, created() { axios @@ -68,9 +70,9 @@ document.addEventListener("DOMContentLoaded", () => { "https://raw.githubusercontent.com/Faithful-Resource-Pack/CompliBot/main/json/faq.json", ) .then((res) => { - this.allFaqs = res.data - this.startSearch() - }) + this.allFaqs = res.data; + this.startSearch(); + }); }, - }) -}) + }); +}); diff --git a/js/favorite-addons.js b/js/favorite-addons.js index 48fe3a97..7b15187a 100644 --- a/js/favorite-addons.js +++ b/js/favorite-addons.js @@ -1,59 +1,65 @@ -const favContainer = document.getElementById('favorites') -const template = document.getElementById('template') +const favContainer = document.getElementById("favorites"); +const template = document.getElementById("template"); -const KEY = 'favs' + window.location.pathname +const KEY = "favs" + window.location.pathname; -Object.defineProperty(window, 'favorites', { +Object.defineProperty(window, "favorites", { get() { - return JSON.parse(localStorage.getItem(KEY)) || [] + return JSON.parse(localStorage.getItem(KEY)) || []; }, set(value) { - localStorage.setItem(KEY, JSON.stringify(value)) - } -}) + localStorage.setItem(KEY, JSON.stringify(value)); + }, +}); function updateView() { if (favorites.length) { - favContainer.style.display = 'grid' - favContainer.innerHTML = '' - let locFavs = favorites + favContainer.style.display = "grid"; + favContainer.innerHTML = ""; + let locFavs = favorites; locFavs.sort((a, b) => { - if (a.title < b.title) { return -1; } - if (a.title > b.title) { return 1; } + if (a.title < b.title) { + return -1; + } + if (a.title > b.title) { + return 1; + } return 0; - }) + }); locFavs.forEach((item, i) => { - favContainer.append(template.content.cloneNode(true)) - document.getElementsByClassName('fav_img')[i].src = item.imgURL - document.getElementsByClassName('img-card')[i].href = item.link - document.getElementsByClassName('fav_title')[i].innerHTML = item.title - document.getElementsByClassName('rem-button')[i].onclick = () => { removeFromFavs(item.link) } - }) + favContainer.append(template.content.cloneNode(true)); + document.getElementsByClassName("fav_img")[i].src = item.imgURL; + document.getElementsByClassName("img-card")[i].href = item.link; + document.getElementsByClassName("fav_title")[i].innerHTML = item.title; + document.getElementsByClassName("rem-button")[i].onclick = () => { + removeFromFavs(item.link); + }; + }); } else { - favContainer.style.display = 'none' + favContainer.style.display = "none"; } } window.addToFavs = function (imgURL, title, link) { - let newFavs = favorites + let newFavs = favorites; if (!newFavs.some((e) => e.link == link)) { newFavs.push({ imgURL: imgURL, link: link, - title: title - }) - favorites = newFavs - updateView() + title: title, + }); + favorites = newFavs; + updateView(); } -} +}; window.removeFromFavs = function (link) { - let newFavs = favorites + let newFavs = favorites; newFavs.forEach((item, i) => { - if (item.link == link) newFavs.splice(i, 1) - }) - favorites = newFavs - updateView() -} + if (item.link == link) newFavs.splice(i, 1); + }); + favorites = newFavs; + updateView(); +}; -updateView() +updateView(); diff --git a/js/mods/components/clearDatabase.js b/js/mods/components/clearDatabase.js index df081126..c2fae4ea 100644 --- a/js/mods/components/clearDatabase.js +++ b/js/mods/components/clearDatabase.js @@ -1,7 +1,7 @@ /* global Vue, indexedDB */ /* eslint no-multi-str: 0 */ -Vue.component('clear-database', { +Vue.component("clear-database", { template: `
@@ -10,29 +10,29 @@ Vue.component('clear-database', { `, methods: { clearDB() { - const dbName = this.$root.$refs.localDownload.dbName + const dbName = this.$root.$refs.localDownload.dbName; // try to close db try { - this.$root.$refs.localDownload.database.close() + this.$root.$refs.localDownload.database.close(); } catch (_err) {} - const request = indexedDB.deleteDatabase(dbName) - console.log('Clearing ' + dbName + ' database...') + const request = indexedDB.deleteDatabase(dbName); + console.log("Clearing " + dbName + " database..."); request.onsuccess = function (_event) { - console.info(dbName + 'database cleared.') + console.info(dbName + "database cleared."); - document.location.reload() - } + document.location.reload(); + }; request.onerror = function (event) { - console.error('Error when clearing database', event) - } + console.error("Error when clearing database", event); + }; request.onblocked = function (_event) { - console.error("Couldn't delete database due to the operation being blocked") - } - } - } -}) + console.error("Couldn't delete database due to the operation being blocked"); + }; + }, + }, +}); diff --git a/js/mods/components/customModal.js b/js/mods/components/customModal.js index 11299862..91856f97 100644 --- a/js/mods/components/customModal.js +++ b/js/mods/components/customModal.js @@ -1,20 +1,20 @@ /* global Vue */ /* eslint no-multi-str: 0 */ -Vue.component('custom-modal', { +Vue.component("custom-modal", { props: { modalOpened: { type: Boolean, - required: true + required: true, }, contentId: { type: String, - default: undefined + default: undefined, }, closeOnClick: { type: Function, - required: true - } + required: true, + }, }, template: `
@@ -23,4 +23,4 @@ Vue.component('custom-modal', {
`, -}) +}); diff --git a/js/mods/components/localDownload.js b/js/mods/components/localDownload.js index bd94348c..0620085c 100644 --- a/js/mods/components/localDownload.js +++ b/js/mods/components/localDownload.js @@ -2,12 +2,12 @@ /* eslint no-multi-str: 0 */ try { - let NAME // eslint-disable-line + let NAME; // eslint-disable-line } catch (_e) {} -NAME = 'Faithful Mods' // eslint-disable-line +NAME = "Faithful Mods"; // eslint-disable-line -Vue.component('local-download', { - props: ['canpack', 'versions'], +Vue.component("local-download", { + props: ["canpack", "versions"], template: `
`, - data () { + data() { return { - dbName: 'mods', + dbName: "mods", dbVersion: 4, database: null, isDownloading: false, stores: [ { - name: 'files', - options: { autoIncrement: true } - } + name: "files", + options: { autoIncrement: true }, + }, ], steps: [ { - name: 'Downloading mods', - content: 'Downloading ' + name: "Downloading mods", + content: "Downloading ", }, { - name: 'Unzipping mods', - content: 'Extracting ' + name: "Unzipping mods", + content: "Extracting ", }, { - name: 'Creating archive', - content: 'Zipping time left: ' - } + name: "Creating archive", + content: "Zipping time left: ", + }, ], currentStep: 0, - currentMod: '', + currentMod: "", modalOpened: false, confirmOpened: false, modSelection: undefined, @@ -108,128 +108,129 @@ Vue.component('local-download', { startTime: new moment(), // eslint-disable-line new-cap currentTime: new moment(), // eslint-disable-line new-cap currentWorker: undefined, - finalZip: undefined - } + finalZip: undefined, + }; }, methods: { closeModal() { - this.modalOpened = false + this.modalOpened = false; if (this.navigatorSupportsWorkers && this.currentWorker !== undefined) { - this.currentWorker.terminate() + this.currentWorker.terminate(); } }, downloadLocally(forceDownload = false) { // hide confirm modal - this.confirmOpened = false - this.logs = [] - this.generatedPercent = -1 + this.confirmOpened = false; + this.logs = []; + this.generatedPercent = -1; - this.finalZip = undefined + this.finalZip = undefined; - this.isDownloading = true - this.modalOpened = true + this.isDownloading = true; + this.modalOpened = true; - this.currentStep = 0 + this.currentStep = 0; if (this.navigatorSupportsWorkers) { - this.downloadWithWorker(this.modSelection, forceDownload, this.logHandler) + this.downloadWithWorker(this.modSelection, forceDownload, this.logHandler); - return + return; } - ResourcePackCreator.openDatabase(this.dbName, this.dbVersion, this.stores[0].name) - ResourcePackCreator.packVersions = this.$root.versions - ResourcePackCreator.zipOptions = this.$root.$refs.zipOptions.zipOptions - ResourcePackCreator.downloadLocally(this.modSelection, forceDownload, this.logHandler) - .catch((err) => { - this.logHandler({ - step: 0, - message: err - }) - }) + ResourcePackCreator.openDatabase(this.dbName, this.dbVersion, this.stores[0].name); + ResourcePackCreator.packVersions = this.$root.versions; + ResourcePackCreator.zipOptions = this.$root.$refs.zipOptions.zipOptions; + ResourcePackCreator.downloadLocally(this.modSelection, forceDownload, this.logHandler).catch( + (err) => { + this.logHandler({ + step: 0, + message: err, + }); + }, + ); }, downloadWithWorker(modSelection, forceDownload, logListener) { // terminate (or re-terminate old worker) - if (this.currentWorker) this.currentWorker.terminate() + if (this.currentWorker) this.currentWorker.terminate(); - this.currentWorker = new Worker('/js/mods/worker/downloadWorker.js') + this.currentWorker = new Worker("/js/mods/worker/downloadWorker.js"); // listen to logs this.currentWorker.onmessage = function (e) { - if (e.data && e.data.type === 'log') logListener(e.data.content) - } + if (e.data && e.data.type === "log") logListener(e.data.content); + }; // open database this.currentWorker.postMessage({ - channel: 'openDatabase', + channel: "openDatabase", data: { dbName: this.dbName, dbVersion: this.dbVersion, - storeName: this.stores[0].name - } - }) + storeName: this.stores[0].name, + }, + }); // set zip options this.currentWorker.postMessage({ - channel: 'fillZipOptions', - data: this.$root.$refs.zipOptions.zipOptions - }) + channel: "fillZipOptions", + data: this.$root.$refs.zipOptions.zipOptions, + }); // open database this.currentWorker.postMessage({ - channel: 'fillPackVersions', - data: this.$root.versions || this.$props.versions - }) + channel: "fillPackVersions", + data: this.$root.versions || this.$props.versions, + }); // finally create pack this.currentWorker.postMessage({ - channel: 'createPack', + channel: "createPack", data: { modSelection: modSelection, - forceDownload: forceDownload - } - }) + forceDownload: forceDownload, + }, + }); }, logHandler(log) { if (log.step < 3) { - this.currentStep = log.step + this.currentStep = log.step; if (log.step !== 2) { - this.addLog(log.message) + this.addLog(log.message); } else { if (!isNaN(parseFloat(log.message))) { - this.generatedPercent = log.message + this.generatedPercent = log.message; - this.currentTime = new moment() // eslint-disable-line - } else if (typeof log.message === 'string') this.addLog(log.message) + this.currentTime = new moment(); // eslint-disable-line + } else if (typeof log.message === "string") this.addLog(log.message); } } else { - this.finalZip = log.message + this.finalZip = log.message; - this.downloadZip() + this.downloadZip(); - this.isDownloading = false + this.isDownloading = false; } }, addLog(value, isError = false) { this.logs.push({ - type: isError ? 'error' : 'log', - value: '' + value - }) + type: isError ? "error" : "log", + value: "" + value, + }); }, modToDisplayName(mod) { - return mod.name.displayName + return mod.name.displayName; }, modToRepoName(mod) { - if (mod.extRepo) return mod.extRepo.split('/').pop() - else return mod.orgRepo + if (mod.extRepo) return mod.extRepo.split("/").pop(); + else return mod.orgRepo; }, modToRepoURL(mod) { if (mod.orgRepo) { - return 'https://github.com/Faithful-Mods/' + this.modToRepoName(mod) + return "https://github.com/Faithful-Mods/" + this.modToRepoName(mod); } else { - return mod.extRepo + return mod.extRepo; } }, modToSelection(mod, version = undefined) { @@ -237,86 +238,86 @@ Vue.component('local-download', { name: this.modToRepoName(mod), displayName: this.modToDisplayName(mod), repositoryURL: this.modToRepoURL(mod, version), - version: mod.versionSelected || version - } + version: mod.versionSelected || version, + }; }, openConfirmModal(modSelection = undefined) { - this.modSelection = (!modSelection) ? this.$root.modSelection : modSelection + this.modSelection = !modSelection ? this.$root.modSelection : modSelection; - this.confirmOpened = true + this.confirmOpened = true; }, downloadZip() { if (this.finalZip !== undefined) { - const customName = this.$root.$refs.zipOptions.customArchiveName - const archiveName = customName || NAME + ' Resource Pack ' + ((new Date()).getTime()) - saveAs(this.finalZip, archiveName + '.zip') // 2) trigger the download + const customName = this.$root.$refs.zipOptions.customArchiveName; + const archiveName = customName || NAME + " Resource Pack " + new Date().getTime(); + saveAs(this.finalZip, archiveName + ".zip"); // 2) trigger the download } - } + }, }, watch: { logs: { currentStep(newValue, oldValue) { if (oldValue === 1 && newValue === 2) { - this.startTime.set(new Date()) + this.startTime.set(new Date()); } }, handler() { // scroll to bottom Vue.nextTick(() => { - const objDiv = this.$refs.log - objDiv.scrollTop = objDiv.scrollHeight + 100 - }) + const objDiv = this.$refs.log; + objDiv.scrollTop = objDiv.scrollHeight + 100; + }); }, - deep: true - } + deep: true, + }, }, computed: { canCloseModal() { - return this.navigatorSupportsWorkers || (this.modalOpened && !this.isDownloading) + return this.navigatorSupportsWorkers || (this.modalOpened && !this.isDownloading); }, canDownloadLocally() { - return !this.$props.canpack + return !this.$props.canpack; }, isGenerating() { - return this.generatedPercent > 0 + return this.generatedPercent > 0; }, latestLog() { - return (this.logs.length > 0) ? this.logs[this.logs.length - 1].value || '' : '' + return this.logs.length > 0 ? this.logs[this.logs.length - 1].value || "" : ""; }, navigatorSupportsWorkers() { - return typeof (Worker) === 'function' + return typeof Worker === "function"; }, reasonCantDownload() { - return 'This selection cannot be packed (Pack versions not compatible)' + return "This selection cannot be packed (Pack versions not compatible)"; }, timeLeft() { // we need to multiply duration by percent /* - * durationInMs = diff from start to now as ms - * - * durationInMs | percent - * totalDurInMs | 100 - * - * timeLeftInMs = totalDurInMs - durationMs - */ + * durationInMs = diff from start to now as ms + * + * durationInMs | percent + * totalDurInMs | 100 + * + * timeLeftInMs = totalDurInMs - durationMs + */ - const durationInMs = moment.duration(this.currentTime.diff(this.startTime)).asMilliseconds() - const totalDurInMs = durationInMs * 100 / this.generatedPercent - const timeLeftInMs = totalDurInMs - durationInMs + const durationInMs = moment.duration(this.currentTime.diff(this.startTime)).asMilliseconds(); + const totalDurInMs = (durationInMs * 100) / this.generatedPercent; + const timeLeftInMs = totalDurInMs - durationInMs; - const durLeft = moment.duration(timeLeftInMs) + const durLeft = moment.duration(timeLeftInMs); - const h = durLeft.hours() - const m = durLeft.minutes() - const s = durLeft.seconds() + const h = durLeft.hours(); + const m = durLeft.minutes(); + const s = durLeft.seconds(); - return (h > 0 ? h + 'h ' : '') + (m > 0 ? m + 'min ' : '') + s + 's' + return (h > 0 ? h + "h " : "") + (m > 0 ? m + "min " : "") + s + "s"; }, cancelTitle() { return this.navigatorSupportsWorkers - ? 'Your browser supports Web Workers :). You can cancel this script immediatly.' - : "Your navigator doesn't supports Web Workers :(. You can't cancel this script." - } - } -}) + ? "Your browser supports Web Workers :). You can cancel this script immediatly." + : "Your navigator doesn't supports Web Workers :(. You can't cancel this script."; + }, + }, +}); diff --git a/js/mods/components/modpackCard.js b/js/mods/components/modpackCard.js index 7300f306..fdcc650f 100644 --- a/js/mods/components/modpackCard.js +++ b/js/mods/components/modpackCard.js @@ -1,8 +1,8 @@ /* global Vue */ /* eslint no-multi-str: 0 */ -Vue.component('modpack-card', { - props: ['modpack', 'cantDownload', 'onbuttonclick'], +Vue.component("modpack-card", { + props: ["modpack", "cantDownload", "onbuttonclick"], template: `
@@ -38,5 +38,5 @@ Vue.component('modpack-card', {
-
` -}) + `, +}); diff --git a/js/mods/components/modpackModal.js b/js/mods/components/modpackModal.js index 1a07e71e..eac18138 100644 --- a/js/mods/components/modpackModal.js +++ b/js/mods/components/modpackModal.js @@ -1,10 +1,10 @@ /* global Vue */ /* eslint no-multi-str: 0 */ -const _TEXT_LOADING = 'Loading...' +const _TEXT_LOADING = "Loading..."; -Vue.component('modpack-modal', { - props: ['modpackmodalopened', 'modpack', 'onclose', 'mods'], +Vue.component("modpack-modal", { + props: ["modpackmodalopened", "modpack", "onclose", "mods"], template: `

{{ modpack.modpackName }}

@@ -30,107 +30,123 @@ Vue.component('modpack-modal', { return { modsFound: 0, modsIgnored: 0, - modsNames: {} - } + modsNames: {}, + }; }, computed: { modSelection() { - const result = [] + const result = []; // build mod selections following mods found this.findMods().forEach((mod) => { result.push({ - name: mod.resource_pack.git_repository.split('/').pop(), + name: mod.resource_pack.git_repository.split("/").pop(), displayName: mod.name, repositoryURL: mod.resource_pack.git_repository, - version: this.modpack.minecraftVersion - }) - }) + version: this.modpack.minecraftVersion, + }); + }); - return result + return result; }, numberOfModsFound() { - return this.modsFound + return this.modsFound; }, numberOfModsIgnored() { - return this.modsIgnored + return this.modsIgnored; }, coveragePercentage() { - this.findMods() - return (((this.numberOfModsIgnored + this.numberOfModsFound) * 100) / this.$props.modpack.modList.length).toFixed(2) - } + this.findMods(); + return ( + ((this.numberOfModsIgnored + this.numberOfModsFound) * 100) / + this.$props.modpack.modList.length + ).toFixed(2); + }, }, watch: { modpackmodalopened(value) { - if (!value) return + if (!value) return; this.modpack.modList.forEach((id) => { - this.searchModName(id) - }) - } + this.searchModName(id); + }); + }, }, methods: { searchModName(id) { - if (this.modsNames[id] && this.modsNames[id] != _TEXT_LOADING) return + if (this.modsNames[id] && this.modsNames[id] != _TEXT_LOADING) return; if (this.mods[id]) { - this.modsNames[id] = this.mods[id].name - return + this.modsNames[id] = this.mods[id].name; + return; } - this.modsNames[id] = _TEXT_LOADING + this.modsNames[id] = _TEXT_LOADING; this.getName(id).then(() => this.$forceUpdate()); }, getName(id) { if (this.mods[id]) this.modsNames[id] = this.mods[id].name; - return axios.get(`${this.$root.apiURL}/v2/mods/${id}/curseforge/name`) - .then((res) => { this.modsNames[id] = res.data }) - .catch(() => { this.modsNames[id] = 'Not Found on CurseForge API: ' + id }); + return axios + .get(`${this.$root.apiURL}/v2/mods/${id}/curseforge/name`) + .then((res) => { + this.modsNames[id] = res.data; + }) + .catch(() => { + this.modsNames[id] = "Not Found on CurseForge API: " + id; + }); }, findMods() { - const results = [] - this.modsFound = 0 - this.modsIgnored = 0 + const results = []; + this.modsFound = 0; + this.modsIgnored = 0; this.modpack.modList.forEach((modId) => { switch (this.findMod(modId)) { case 'Found': - this.modsFound++ - results.push(this.mods[modId]) + this.modsFound++; + results.push(this.mods[modId]); break; case `No textures`: case `No textures in ${this.modpack.minecraftVersion}`: - this.modsIgnored++ + this.modsIgnored++; break; default: // not found or not available in current version or blacklisted break; } - }) + }); - return results + return results; }, findMod(id) { if (this.mods[id] && this.mods[id].blacklisted) - return `No textures` + return `No textures`; - if (this.mods[id] && this.mods[id].resource_pack.blacklist && this.mods[id].resource_pack.blacklist.includes(this.modpack.minecraftVersion)) - return `No textures in ${this.modpack.minecraftVersion}` + if ( + this.mods[id] && + this.mods[id].resource_pack.blacklist && + this.mods[id].resource_pack.blacklist.includes(this.modpack.minecraftVersion) + ) + return `No textures in ${this.modpack.minecraftVersion}`; - if (this.mods[id] && this.mods[id].resource_pack.versions.includes(this.modpack.minecraftVersion)) - return `Found` + if ( + this.mods[id] && + this.mods[id].resource_pack.versions.includes(this.modpack.minecraftVersion) + ) + return `Found`; if (this.mods[id] && this.mods[id].resource_pack.versions.length !== 0) - return `Not in ${this.modpack.minecraftVersion}` + return `Not in ${this.modpack.minecraftVersion}`; - return `Not found` + return `Not found`; }, download() { - if (!this.modSelection || !Array.isArray(this.modSelection) || this.modSelection.length === 0) return - this.$props.onclose() - this.$root.$refs.localDownload.openConfirmModal(this.modSelection) - } - } -}) + if (!this.modSelection || !Array.isArray(this.modSelection) || this.modSelection.length === 0) + return; + this.$props.onclose(); + this.$root.$refs.localDownload.openConfirmModal(this.modSelection); + }, + }, +}); diff --git a/js/mods/components/mods/downloadMinecraftVersion.js b/js/mods/components/mods/downloadMinecraftVersion.js index 090df0cb..4fbdb64c 100644 --- a/js/mods/components/mods/downloadMinecraftVersion.js +++ b/js/mods/components/mods/downloadMinecraftVersion.js @@ -1,13 +1,13 @@ /* global Vue */ /* eslint no-multi-str: 0 */ -Vue.component('download-minecraft-version', { +Vue.component("download-minecraft-version", { props: { value: { version: String, - count: Number + count: Number, }, - block: Boolean + block: Boolean, }, template: ` `, data() { - return {} + return {}; }, methods: { dv() { if (this.$root.$refs.localDownload && !!this.$root.$refs.localDownload.openConfirmModal) { - this.$root.$refs.localDownload.openConfirmModal(this.$root.mods.filter((mod) => mod.resource_pack.versions.includes(this.$props.value.version)).map((mod) => { - return this.$root.modToSelection(mod, this.$props.value.version) - })) + this.$root.$refs.localDownload.openConfirmModal( + this.$root.mods + .filter((mod) => mod.resource_pack.versions.includes(this.$props.value.version)) + .map((mod) => { + return this.$root.modToSelection(mod, this.$props.value.version); + }), + ); } - } - } -}) + }, + }, +}); diff --git a/js/mods/components/mods/minecraftMod.js b/js/mods/components/mods/minecraftMod.js index 133c22b5..5575d872 100644 --- a/js/mods/components/mods/minecraftMod.js +++ b/js/mods/components/mods/minecraftMod.js @@ -1,14 +1,15 @@ /* global Vue, axios */ /* eslint no-multi-str: 0 */ -const _MOD_NOT_FOUND_MESSAGE = 'Found no thumbnail for this mod' -const _NO_LINK = null -const _NO_ICON = 'https://database.faithfulpack.net/images/branding/logos/transparent/512/mods_logo.png' -const _NO_ATTACHMENTS = -1 +const _MOD_NOT_FOUND_MESSAGE = "Found no thumbnail for this mod"; +const _NO_LINK = null; +const _NO_ICON = + "https://database.faithfulpack.net/images/branding/logos/transparent/512/mods_logo.png"; +const _NO_ATTACHMENTS = -1; -Vue.component('minecraft-mod', { +Vue.component("minecraft-mod", { props: { - mod: Object + mod: Object, }, template: `
  • @@ -41,50 +42,60 @@ Vue.component('minecraft-mod', { return { searchPages: 3, imageSource: _NO_ICON, - link: _NO_LINK - } + link: _NO_LINK, + }; }, computed: { /** @returns {String} of joined aliases in */ aliases() { - return this.$props.mod.aliases.length > 0 ? ' ‐ 
    ' + this.$props.mod.aliases.join(', ') + '
    ' : '' + return this.$props.mod.aliases.length > 0 + ? ' ‐ 
    ' + + this.$props.mod.aliases.join(", ") + + "
    " + : ""; }, /** @returns {String} complete curseforge mod url*/ curseURL() { - return this.$props.mod.curseURL || _NO_LINK + return this.$props.mod.curseURL || _NO_LINK; }, /** @returns {String} info link to curseforge's mod page*/ info() { - const link = this.$props.mod.curse_url || _NO_LINK + const link = this.$props.mod.curse_url || _NO_LINK; - if (link === _NO_LINK) return '' - return '' + if (link === _NO_LINK) return ""; + return ( + '' + ); }, /** @returns {String} main mod name s*/ name() { - return this.$props.mod.name + return this.$props.mod.name; }, /** @returns {String} background-img OR set opacity to 1*/ imageStyle() { - if (this.imageSource !== _NO_ICON) return '' - return 'opacity: 1' + if (this.imageSource !== _NO_ICON) return ""; + return "opacity: 1"; }, /** @returns {Array} of available versions */ minecraftVersions() { - return this.$props.mod.resource_pack.versions + return this.$props.mod.resource_pack.versions; }, /** @return {String} git repository full url */ repoURL() { - return this.$props.mod.resource_pack.git_repository + return this.$props.mod.resource_pack.git_repository; }, modId() { - return this.mod.id + return this.mod.id; }, modIds() { - return this.minecraftVersions.map((v) => this.modId) + return this.minecraftVersions.map((v) => this.modId); }, title() { - return `

    ${this.name}

    ${this.aliases}
    ${this.info}` - } + return `

    ${this.name}

    ${this.aliases}
    ${this.info}`; + }, }, -}) +}); diff --git a/js/mods/components/mods/minecraftModsList.js b/js/mods/components/mods/minecraftModsList.js index 12842a3a..bc2fdbe9 100644 --- a/js/mods/components/mods/minecraftModsList.js +++ b/js/mods/components/mods/minecraftModsList.js @@ -1,26 +1,28 @@ /* global Vue */ /* eslint no-multi-str: 0 */ -Vue.component('minecraft-mod-list', { +Vue.component("minecraft-mod-list", { template: `
    `, props: { - mods: Object + mods: Object, }, data() { return { - thumbnailCache: [] - } + thumbnailCache: [], + }; }, methods: { searchCache(modName) { - return this.thumbnailCache.filter((mod) => modName === mod.modName)[0] + return this.thumbnailCache.filter((mod) => modName === mod.modName)[0]; }, modToRepoName(mod) { - return mod.resource_pack.git_repository ? mod.resource_pack.git_repository.split('/').pop() : null - } + return mod.resource_pack.git_repository + ? mod.resource_pack.git_repository.split("/").pop() + : null; + }, }, -}) +}); diff --git a/js/mods/components/mods/minecraftVersions.js b/js/mods/components/mods/minecraftVersions.js index a7924f5c..27fcac08 100644 --- a/js/mods/components/mods/minecraftVersions.js +++ b/js/mods/components/mods/minecraftVersions.js @@ -1,10 +1,10 @@ /* global Vue, MinecraftUtils */ /* eslint no-multi-str: 0 */ -Vue.component('minecraft-versions', { +Vue.component("minecraft-versions", { props: { versions: Array, - breakpoints: Object + breakpoints: Object, }, template: `
    @@ -20,45 +20,46 @@ Vue.component('minecraft-versions', {
    `, - data () { - return {} + data() { + return {}; }, computed: { orderedVersions() { return this.$props.versions.sort(function (a, b) { - const numbers = MinecraftUtils.minecraftVersionsToNumbers([a.version, b.version]) + const numbers = MinecraftUtils.minecraftVersionsToNumbers([a.version, b.version]); - return (numbers[0] > numbers[1] ? -1 : 1) - }) + return numbers[0] > numbers[1] ? -1 : 1; + }); }, elementsPerLine() { - if (!!this.$props.breakpoints.lg && !this.$props.breakpoints.md) return this.$props.versions.length - if (!!this.$props.breakpoints.md && !this.$props.breakpoints.sm) return 6 - if (!!this.$props.breakpoints.sm && !this.$props.breakpoints.xs) return 3 + if (!!this.$props.breakpoints.lg && !this.$props.breakpoints.md) + return this.$props.versions.length; + if (!!this.$props.breakpoints.md && !this.$props.breakpoints.sm) return 6; + if (!!this.$props.breakpoints.sm && !this.$props.breakpoints.xs) return 3; - return 1 + return 1; }, versionsOrganized() { - const result = [] + const result = []; for (let i = 0; i < this.orderedVersions.length; ++i) { if (i % this.elementsPerLine === 0) { - result.push([]) + result.push([]); } - result[result.length - 1].push(this.orderedVersions[i]) + result[result.length - 1].push(this.orderedVersions[i]); } - return result - } + return result; + }, }, methods: { downloadVersion(version) { if (this.$root.handleDownload) { - this.$root.handleDownload('version', { - version: version - }) + this.$root.handleDownload("version", { + version: version, + }); } - } - } -}) + }, + }, +}); diff --git a/js/mods/components/zipOptions.js b/js/mods/components/zipOptions.js index 1e05c0b4..ab3da0e5 100644 --- a/js/mods/components/zipOptions.js +++ b/js/mods/components/zipOptions.js @@ -2,11 +2,11 @@ /* eslint no-multi-str: 0 */ try { - let NAME // eslint-disable-line + let NAME; // eslint-disable-line } catch (_e) {} -NAME = 'Faithful Mods' // eslint-disable-line +NAME = "Faithful Mods"; // eslint-disable-line -Vue.component('zip-options', { +Vue.component("zip-options", { template: `

    @@ -53,67 +53,71 @@ Vue.component('zip-options', { compressionDefault: 7, compressionChosen: 7, // 7 is default compression for ZIP archives compressionLevelsAvailable: 10, - compressionTypes: ['STORE', 'DEFLATE'], + compressionTypes: ["STORE", "DEFLATE"], specialCompressionLabels: { - 0: 'No compression', - 1: 'Best speed', - 7: 'Recommended', - 9: 'Best compression' + 0: "No compression", + 1: "Best speed", + 7: "Recommended", + 9: "Best compression", }, - archiveName: '' - } + archiveName: "", + }; }, computed: { chevron() { - return 'fa-caret-' + (this.advancedOptionsEnabled ? 'up' : 'down') + return "fa-caret-" + (this.advancedOptionsEnabled ? "up" : "down"); }, compressionLevels() { - const result = [] + const result = []; for (let i = 0; i < this.compressionLevelsAvailable; ++i) { result.push({ value: i, - label: (i) in this.specialCompressionLabels ? i + ` (${this.specialCompressionLabels[i]})` : String(i) - }) + label: + i in this.specialCompressionLabels + ? i + ` (${this.specialCompressionLabels[i]})` + : String(i), + }); } - return result + return result; }, compressionTypeChosen() { - return this.compressionTypes[(this.compressionLevelChosen > 0) * 1] + return this.compressionTypes[(this.compressionLevelChosen > 0) * 1]; }, compressionLevelChosen() { - return this.advancedOptionsEnabled ? this.compressionChosen : this.compressionDefault + return this.advancedOptionsEnabled ? this.compressionChosen : this.compressionDefault; }, zipOptions() { const result = { - type: 'blob', - comment: 'Resource pack generated by ' + NAME, - compression: this.compressionTypeChosen - } + type: "blob", + comment: "Resource pack generated by " + NAME, + compression: this.compressionTypeChosen, + }; - if (this.compressionTypeChosen === this.compressionTypes[1]) { // if DEFlATE compression chosen + if (this.compressionTypeChosen === this.compressionTypes[1]) { + // if DEFlATE compression chosen result.compressionOptions = { - level: this.compressionLevelChosen - } + level: this.compressionLevelChosen, + }; } - return result + return result; }, customArchiveName() { - return (this.advancedOptionsEnabled && this.archiveName !== '') ? this.archiveName : undefined - } + return this.advancedOptionsEnabled && this.archiveName !== "" ? this.archiveName : undefined; + }, }, watch: { archiveName(newValue, oldValue) { if (oldValue !== newValue) { - const changed = newValue.trim() + const changed = newValue.trim(); if (changed !== newValue) { - this.archiveName = changed + this.archiveName = changed; } } - } + }, }, mounted() { - this.$root.$refs.zipOptions = this - } -}) + this.$root.$refs.zipOptions = this; + }, +}); diff --git a/js/mods/core/MinecraftUtils.js b/js/mods/core/MinecraftUtils.js index 02791bc4..221e0c9c 100644 --- a/js/mods/core/MinecraftUtils.js +++ b/js/mods/core/MinecraftUtils.js @@ -1,69 +1,72 @@ -const MinecraftUtils = { // eslint-disable-line no-unused-vars +const MinecraftUtils = { + // eslint-disable-line no-unused-vars minecraftVersionToNumberArray(version) { - const numbers = version.split('.') + const numbers = version.split("."); if (numbers.length < 3) { for (let i = 0; i < 3 - numbers.length; ++i) { - numbers.push(0) + numbers.push(0); } } - return numbers.map((number) => parseInt(number)) + return numbers.map((number) => parseInt(number)); }, minecraftVersionsToNumbers(numbers) { // initial numbers : 1.10, 1.7.9, 1.11.2 ( 1.7.9 < 1.10 < 1.11.2 ) // result : 1100, 1079, 1112 ( 1079 < 1100 < 1112 ) // handle string arrays - if (Array.isArray(numbers) && numbers.length > 0 && typeof (numbers[0]) === 'string') { - const tmp = [] + if (Array.isArray(numbers) && numbers.length > 0 && typeof numbers[0] === "string") { + const tmp = []; for (let i = 0; i < numbers.length; ++i) { - tmp.push(this.minecraftVersionToNumberArray(numbers[i])) + tmp.push(this.minecraftVersionToNumberArray(numbers[i])); } - numbers = tmp + numbers = tmp; } - const result = [] + const result = []; // looking for max numbers count - let maxNumbersCount = -1 + let maxNumbersCount = -1; for (let i = 0; i < numbers.length; ++i) { - if (numbers[i].length > maxNumbersCount) { maxNumbersCount = numbers[i].length } + if (numbers[i].length > maxNumbersCount) { + maxNumbersCount = numbers[i].length; + } - result.push('0') // we need this number to have a number to parse at the end + result.push("0"); // we need this number to have a number to parse at the end } for (let a = 0; a < maxNumbersCount; ++a) { // if it' the first number, we just add it to the end if (a === 0) { for (let i = 0; i < numbers.length; ++i) { - result[i] += String(numbers[i][a]) + result[i] += String(numbers[i][a]); } } else { // else we need to add additional zeros equals to the difference of letters with max number // 0, 20, 600 -> 000, 020, 600 // first we find the maxDigits for this number - let maxDigits = -1 + let maxDigits = -1; for (let i = 0; i < numbers.length; ++i) { - if (String(numbers[i][a] || '').length > maxDigits) { - maxDigits = String(numbers[i][a] || '').length + if (String(numbers[i][a] || "").length > maxDigits) { + maxDigits = String(numbers[i][a] || "").length; } } // then for each nuber we add the difference of zeros for (let i = 0; i < numbers.length; ++i) { - for (let b = 0; b < maxDigits - String(numbers[i][a] || '').length; ++b) { - result[i] += '0' + for (let b = 0; b < maxDigits - String(numbers[i][a] || "").length; ++b) { + result[i] += "0"; } // finally we push the number - result[i] += String(numbers[i][a] || '') + result[i] += String(numbers[i][a] || ""); } } } - return result.map((number) => parseInt(number)) - } -} + return result.map((number) => parseInt(number)); + }, +}; diff --git a/js/mods/core/ResourcePackCreator.js b/js/mods/core/ResourcePackCreator.js index 114a082b..f686734f 100644 --- a/js/mods/core/ResourcePackCreator.js +++ b/js/mods/core/ResourcePackCreator.js @@ -1,8 +1,9 @@ /* eslint new-cap: 0 */ /* global MinecraftUtils, axios, idb, JSZip, axiosRetry, fetch */ -const PATH_PACK_PNG = 'https://database.faithfulpack.net/images/branding/logos/transparent/512/mods_logo.png' -const MCMETA_DESCRIPTION = 'Faithful Mods' +const PATH_PACK_PNG = + "https://database.faithfulpack.net/images/branding/logos/transparent/512/mods_logo.png"; +const MCMETA_DESCRIPTION = "Faithful Mods"; /** * Resolves after delay @@ -13,8 +14,8 @@ const MCMETA_DESCRIPTION = 'Faithful Mods' */ Promise.sleep = (delay, value = undefined) => new Promise((resolve) => { - setTimeout(() => resolve(value), delay) - }) + setTimeout(() => resolve(value), delay); + }); /** * @callback PromiseCallback @@ -29,9 +30,8 @@ Promise.sleep = (delay, value = undefined) => * @param {any[]} results Promise results * @returns {Promise} all results if successful */ -Promise.throttle = function(arr, throttle, delay, results = []) { - if (arr.length === 0) - return results; +Promise.throttle = function (arr, throttle, delay, results = []) { + if (arr.length === 0) return results; const start = new Date().getTime(); const one = arr.shift(); @@ -40,13 +40,13 @@ Promise.throttle = function(arr, throttle, delay, results = []) { .then((res) => { let end = new Date().getTime(); let duration = end - start; - return Promise.sleep(duration < throttle ? Math.min(throttle - duration, delay) : delay, res) + return Promise.sleep(duration < throttle ? Math.min(throttle - duration, delay) : delay, res); }) .then((res) => { - results.push(res) - return Promise.throttle(arr, throttle, delay, results) - }) -} + results.push(res); + return Promise.throttle(arr, throttle, delay, results); + }); +}; /** * This callback is displayed as part of the Requester class. @@ -78,7 +78,8 @@ Promise.throttle = function(arr, throttle, delay, results = []) { * @property {string} version mod minecraft version */ -const ResourcePackCreator = { // eslint-disable-line no-unused-vars +const ResourcePackCreator = { + // eslint-disable-line no-unused-vars packVersions: Array[String], database: undefined, databasePromise: undefined, @@ -96,25 +97,29 @@ const ResourcePackCreator = { // eslint-disable-line no-unused-vars // (list of package number must not change) // we need mods and versions to be loaded - if (modSelection.length === 0) { return undefined } + if (modSelection.length === 0) { + return undefined; + } - let currentPackageVersion - let versionChanged = false + let currentPackageVersion; + let versionChanged = false; - let i = 0 + let i = 0; while (i < modSelection.length && !versionChanged) { - const tmpPackageVersion = this.packageVersion(modSelection[i].version) + const tmpPackageVersion = this.packageVersion(modSelection[i].version); if (currentPackageVersion === undefined) { - currentPackageVersion = tmpPackageVersion + currentPackageVersion = tmpPackageVersion; } else { - if (currentPackageVersion !== tmpPackageVersion) { versionChanged = true } + if (currentPackageVersion !== tmpPackageVersion) { + versionChanged = true; + } } - ++i + ++i; } - return versionChanged ? undefined : currentPackageVersion + return versionChanged ? undefined : currentPackageVersion; }, /** @@ -123,49 +128,60 @@ const ResourcePackCreator = { // eslint-disable-line no-unused-vars * @returns {number} mod package version */ packageVersion(modVersion) { - const numbers = MinecraftUtils.minecraftVersionToNumberArray(modVersion) + const numbers = MinecraftUtils.minecraftVersionToNumberArray(modVersion); - const packageVersionKeys = Object.keys(this.packVersions) + const packageVersionKeys = Object.keys(this.packVersions); - let i = 0 - let result = -1 + let i = 0; + let result = -1; while (i < packageVersionKeys.length && result === -1) { - const otherNumbersMin = MinecraftUtils.minecraftVersionToNumberArray(this.packVersions[packageVersionKeys[i]].min) - const otherNumbersMax = MinecraftUtils.minecraftVersionToNumberArray(this.packVersions[packageVersionKeys[i]].max) + const otherNumbersMin = MinecraftUtils.minecraftVersionToNumberArray( + this.packVersions[packageVersionKeys[i]].min, + ); + const otherNumbersMax = MinecraftUtils.minecraftVersionToNumberArray( + this.packVersions[packageVersionKeys[i]].max, + ); // we compute the corresponding numbers - const correspondingNumbers = MinecraftUtils.minecraftVersionsToNumbers([numbers, otherNumbersMin, otherNumbersMax]) - - if (correspondingNumbers[0] >= correspondingNumbers[1] && correspondingNumbers[0] <= correspondingNumbers[2]) { - result = packageVersionKeys[i] + const correspondingNumbers = MinecraftUtils.minecraftVersionsToNumbers([ + numbers, + otherNumbersMin, + otherNumbersMax, + ]); + + if ( + correspondingNumbers[0] >= correspondingNumbers[1] && + correspondingNumbers[0] <= correspondingNumbers[2] + ) { + result = packageVersionKeys[i]; } - ++i + ++i; } if (result === -1) { - throw new Error('No package versions file') + throw new Error("No package versions file"); } - this.fullPackageVersion = result + this.fullPackageVersion = result; - return result + return result; }, modToDisplayName(mod) { - return mod.name.displayName + return mod.name.displayName; }, modToRepoName(mod) { - if (mod.name.extRepo) return mod.name.extRepo.split('/').pop() - else return mod.name.orgRepo + if (mod.name.extRepo) return mod.name.extRepo.split("/").pop(); + else return mod.name.orgRepo; }, modToRepoURL(mod) { if (mod.orgRepo) { - return 'https://github.com/Faithful-Mods/' + this.modToRepoName(mod) + return "https://github.com/Faithful-Mods/" + this.modToRepoName(mod); } else { - return mod.extRepo + return mod.extRepo; } }, @@ -174,8 +190,8 @@ const ResourcePackCreator = { // eslint-disable-line no-unused-vars name: this.modToRepoName(mod), displayName: this.modToDisplayName(mod), repositoryURL: this.modToRepoURL(mod, version), - version: mod.versionSelected || version - } + version: mod.versionSelected || version, + }; }, /** @@ -186,10 +202,10 @@ const ResourcePackCreator = { // eslint-disable-line no-unused-vars */ canPackMods(modSelection, modPackageVersion = undefined) { if (modSelection) { - return this.modPackageVersion(modSelection) !== undefined + return this.modPackageVersion(modSelection) !== undefined; } - return modPackageVersion !== undefined + return modPackageVersion !== undefined; }, /** @@ -200,23 +216,26 @@ const ResourcePackCreator = { // eslint-disable-line no-unused-vars requestDownloadMod(mod) { return axios({ url: - 'https://api.allorigins.win/raw?url=' + mod.repositoryURL + '/archive/' + mod.version + '.zip', - method: 'GET', - responseType: 'blob' // important - }) - .then((res) => { - const fileKey = this.fileKey(mod) - - this.database.delete(this.storeName, fileKey).then(() => { - this.database.put(this.storeName, res.data, fileKey) - }) - - return res - }) + "https://api.allorigins.win/raw?url=" + + mod.repositoryURL + + "/archive/" + + mod.version + + ".zip", + method: "GET", + responseType: "blob", // important + }).then((res) => { + const fileKey = this.fileKey(mod); + + this.database.delete(this.storeName, fileKey).then(() => { + this.database.put(this.storeName, res.data, fileKey); + }); + + return res; + }); }, fileKey(mod) { - return mod.name + '-' + mod.version + return mod.name + "-" + mod.version; }, /** @@ -227,29 +246,34 @@ const ResourcePackCreator = { // eslint-disable-line no-unused-vars * @returns {Promise} Mod downloaded or loaded */ getMod(mod, forceDownload = false, logListener = function () {}) { - if (forceDownload) { return this.requestDownloadMod(mod) } + if (forceDownload) { + return this.requestDownloadMod(mod); + } // only proceed if database loaded - if (typeof this.database === 'object' && 'get' in this.database) { - const fileKey = this.fileKey(mod) + if (typeof this.database === "object" && "get" in this.database) { + const fileKey = this.fileKey(mod); - return this.database.get(this.storeName, fileKey).then((res) => { - logListener({ - step: 0, - message: 'Already downloaded ' + mod.displayName + ' v' + mod.version + ' in cache' - }) + return this.database + .get(this.storeName, fileKey) + .then((res) => { + logListener({ + step: 0, + message: "Already downloaded " + mod.displayName + " v" + mod.version + " in cache", + }); - if (res) { - return Promise.resolve({ data: res }) - } + if (res) { + return Promise.resolve({ data: res }); + } - // fallback on catch - return Promise.reject('Download required') - }).catch(() => { - return this.requestDownloadMod(mod) - }) + // fallback on catch + return Promise.reject("Download required"); + }) + .catch(() => { + return this.requestDownloadMod(mod); + }); } else { - return this.requestDownloadMod(mod) + return this.requestDownloadMod(mod); } }, @@ -264,144 +288,156 @@ const ResourcePackCreator = { // eslint-disable-line no-unused-vars // database not loaded yet if (!this.database) { return this.databasePromise.then(() => { - return this.downloadLocally(modSelection, forceDownload, logListener) - }) + return this.downloadLocally(modSelection, forceDownload, logListener); + }); } - if (!this.storeName || !this.zipOptions) return Promise.reject('Elements missing') - if (modSelection.length === 0) return Promise.resolve() // successfully finished doing nothing + if (!this.storeName || !this.zipOptions) return Promise.reject("Elements missing"); + if (modSelection.length === 0) return Promise.resolve(); // successfully finished doing nothing // create final zip - const finalZip = new JSZip() + const finalZip = new JSZip(); - const promises = [] + const promises = []; modSelection.forEach((mod) => { - promises.push(() => { logListener({ step: 0, - message: 'Downloading ' + mod.displayName + ' v' + mod.version + '...' - }) - return this.getMod(mod, forceDownload, logListener) - }) - }) - - let success = 0 - return Promise.throttle(promises, 3000, 20).then((values) => { - return new Promise((resolve, reject) => { - this.currentStep = 1 - values.forEach((res, index) => { - logListener({ - step: 1, - message: 'Extracting ' + modSelection[index].displayName + ' into final zip' - }) - if (res.data.type === 'text/xml') { - console.warn(modSelection[index]) - } - - const fileKey = this.fileKey(modSelection[index]) - - // load this pack - const zip = new JSZip() - - zip.loadAsync(res.data) - .then((zip) => { - const keys = Object.keys(zip.files) - - let newName - for (let i = 0; i < keys.length; ++i) { - newName = keys[i].replace(fileKey + '/', '') - - if (newName.trim() !== '') { - finalZip.files[newName] = zip.files[keys[i]] - finalZip.files[newName].name = newName + message: "Downloading " + mod.displayName + " v" + mod.version + "...", + }); + return this.getMod(mod, forceDownload, logListener); + }); + }); + + let success = 0; + return Promise.throttle(promises, 3000, 20) + .then((values) => { + return new Promise((resolve, reject) => { + this.currentStep = 1; + values.forEach((res, index) => { + logListener({ + step: 1, + message: "Extracting " + modSelection[index].displayName + " into final zip", + }); + if (res.data.type === "text/xml") { + console.warn(modSelection[index]); + } + + const fileKey = this.fileKey(modSelection[index]); + + // load this pack + const zip = new JSZip(); + + zip + .loadAsync(res.data) + .then((zip) => { + const keys = Object.keys(zip.files); + + let newName; + for (let i = 0; i < keys.length; ++i) { + newName = keys[i].replace(fileKey + "/", ""); + + if (newName.trim() !== "") { + finalZip.files[newName] = zip.files[keys[i]]; + finalZip.files[newName].name = newName; + } } - } - - ++success - // if all archives have been successfully added - if (success === modSelection.length) { - logListener({ - step: 2, - message: 'Inserting pack.png and pack.mcmeta into final zip' - }) - - fetch(PATH_PACK_PNG).then((packImage) => { - return packImage.blob() - }).then((packImageBlob) => { - finalZip.file('pack.png', packImageBlob, { blob: true }) - finalZip.file('pack.mcmeta', `{"pack": {"pack_format": ${this.fullPackageVersion}, "description": "${MCMETA_DESCRIPTION}"}}`) + ++success; + // if all archives have been successfully added + if (success === modSelection.length) { logListener({ step: 2, - message: 'Zipping...' - }) + message: "Inserting pack.png and pack.mcmeta into final zip", + }); - finalZip.generateAsync(this.zipOptions, (metadata) => { - logListener({ - step: 2, - message: metadata.percent.toFixed(2) + fetch(PATH_PACK_PNG) + .then((packImage) => { + return packImage.blob(); }) - }).then((blob) => { - logListener({ - step: 3, - message: blob + .then((packImageBlob) => { + finalZip.file("pack.png", packImageBlob, { blob: true }); + finalZip.file( + "pack.mcmeta", + `{"pack": {"pack_format": ${this.fullPackageVersion}, "description": "${MCMETA_DESCRIPTION}"}}`, + ); + + logListener({ + step: 2, + message: "Zipping...", + }); + + finalZip + .generateAsync(this.zipOptions, (metadata) => { + logListener({ + step: 2, + message: metadata.percent.toFixed(2), + }); + }) + .then((blob) => { + logListener({ + step: 3, + message: blob, + }); + + resolve(); // * SUCCESS + }) + .catch((err) => { + console.error(err); + reject(err); + }); }) - - resolve() // * SUCCESS - }).catch((err) => { - console.error(err) - reject(err) - }) - }) - .catch(reject) - return - } - }).catch(reject) - }) + .catch(reject); + return; + } + }) + .catch(reject); + }); + }); }) - }).catch((...args) => { - console.error(...args) - const error = args[0] - if (error.response) { - // The request was made and the server responded with a status code - // that falls out of the range of 2xx - console.log(error.response.data); - console.log(error.response.status); - console.log(error.response.headers); - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - console.log(error.request); - } else { - // Something happened in setting up the request that triggered an Error - console.log('Error', error.message); - } - console.log(error.config); - return Promise.reject(...args) - }) + .catch((...args) => { + console.error(...args); + const error = args[0]; + if (error.response) { + // The request was made and the server responded with a status code + // that falls out of the range of 2xx + console.log(error.response.data); + console.log(error.response.status); + console.log(error.response.headers); + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of + // http.ClientRequest in node.js + console.log(error.request); + } else { + // Something happened in setting up the request that triggered an Error + console.log("Error", error.message); + } + console.log(error.config); + return Promise.reject(...args); + }); }, openDatabase(dataBaseName, databaseVersion, storeName) { - this.storeName = storeName + this.storeName = storeName; this.databasePromise = new Promise((resolve, reject) => { - idb.openDB(dataBaseName, databaseVersion, { - upgrade(db, _oldVersion, _newVersion, _transaction) { - db.createObjectStore(storeName) - } - }) + idb + .openDB(dataBaseName, databaseVersion, { + upgrade(db, _oldVersion, _newVersion, _transaction) { + db.createObjectStore(storeName); + }, + }) .then((db) => { - this.database = db - resolve() + this.database = db; + resolve(); }) .catch((err) => { - this.database = 1 - console.error(err) - reject(new Error(err)) - }) - }) - } -} + this.database = 1; + console.error(err); + reject(new Error(err)); + }); + }); + }, +}; diff --git a/js/mods/downloadFile.js b/js/mods/downloadFile.js index 8fcc1e79..6bc714a3 100644 --- a/js/mods/downloadFile.js +++ b/js/mods/downloadFile.js @@ -1,43 +1,44 @@ /* global XMLHttpRequest, Blob, NAME */ try { - let NAME // eslint-disable-line + let NAME; // eslint-disable-line } catch (_e) {} -NAME = 'Faithful Mods' // eslint-disable-line +NAME = "Faithful Mods"; // eslint-disable-line -function downloadFile (url) { // eslint-disable-line no-unused-vars +function downloadFile(url) { + // eslint-disable-line no-unused-vars return new Promise((resolve, reject) => { - const req = new XMLHttpRequest() - req.open('GET', url, true) - req.responseType = 'blob' + const req = new XMLHttpRequest(); + req.open("GET", url, true); + req.responseType = "blob"; - const FINAL_NAME = NAME + ' Resource Pack' + const FINAL_NAME = NAME + " Resource Pack"; req.onload = function (_event) { if (req.status !== 200) { - reject(req) - return + reject(req); + return; } - const blob = req.response - const fileName = FINAL_NAME + ' ' + new Date().getTime() + '.zip' - const contentType = 'application/zip' + const blob = req.response; + const fileName = FINAL_NAME + " " + new Date().getTime() + ".zip"; + const contentType = "application/zip"; if (window.navigator.msSaveOrOpenBlob) { // Internet Explorer - window.navigator.msSaveOrOpenBlob(new Blob([blob], { type: contentType }), fileName) + window.navigator.msSaveOrOpenBlob(new Blob([blob], { type: contentType }), fileName); } else { - const el = document.getElementById('target') - el.href = window.URL.createObjectURL(blob) - el.download = fileName - el.click() + const el = document.getElementById("target"); + el.href = window.URL.createObjectURL(blob); + el.download = fileName; + el.click(); } - resolve() - } + resolve(); + }; req.onerror = function () { - reject(req) - } + reject(req); + }; - req.send() - }) + req.send(); + }); } diff --git a/js/mods/extensionjs.js b/js/mods/extensionjs.js index 0132c9bf..5da05882 100644 --- a/js/mods/extensionjs.js +++ b/js/mods/extensionjs.js @@ -1,27 +1,27 @@ -Element.prototype.remove = function() { - this.parentElement.removeChild(this); +Element.prototype.remove = function () { + this.parentElement.removeChild(this); }; -Element.prototype.appendHTML = function(str) { - var div = document.createElement('div'); +Element.prototype.appendHTML = function (str) { + var div = document.createElement("div"); div.innerHTML = str; while (div.children.length > 0) { this.appendChild(div.children[0]); } -} -NodeList.prototype.remove = HTMLCollection.prototype.remove = function() { - for (var i = this.length - 1; i >= 0; i--) { - if (this[i] && this[i].parentElement) { - this[i].parentElement.removeChild(this[i]); - } +}; +NodeList.prototype.remove = HTMLCollection.prototype.remove = function () { + for (var i = this.length - 1; i >= 0; i--) { + if (this[i] && this[i].parentElement) { + this[i].parentElement.removeChild(this[i]); } + } }; -const isEmptyObject = function(object) { - if (typeof(object) == "object" && !Array.isArray(object)) { - let count = 0; - for (let key in object) { - count++; - } - return (count === 0) ? true : false; +const isEmptyObject = function (object) { + if (typeof object == "object" && !Array.isArray(object)) { + let count = 0; + for (let key in object) { + count++; } - return undefined; -}; \ No newline at end of file + return count === 0 ? true : false; + } + return undefined; +}; diff --git a/js/mods/modpacks.js b/js/mods/modpacks.js index 468ed843..063cc286 100644 --- a/js/mods/modpacks.js +++ b/js/mods/modpacks.js @@ -1,14 +1,16 @@ /* global Vue, axios, MinecraftUtils, location */ -const _MODPACK_NOT_FOUND_MESSAGE = 'Found no thumbnail for this modpack' -const _NO_LINK = null -const _NO_ICON = 'https://database.faithfulpack.net/images/branding/logos/transparent/512/mods_logo.png' -const _NO_ATTACHMENTS = -1 +const _MODPACK_NOT_FOUND_MESSAGE = "Found no thumbnail for this modpack"; +const _NO_LINK = null; +const _NO_ICON = + "https://database.faithfulpack.net/images/branding/logos/transparent/512/mods_logo.png"; +const _NO_ATTACHMENTS = -1; document.addEventListener("DOMContentLoaded", () => { - Vue.config.devtools = location.hostname === 'localhost' || location.hostname === '127.0.0.1' - const v = new Vue({ // eslint-disable-line no-unused-vars - el: '#modpacks', + Vue.config.devtools = location.hostname === "localhost" || location.hostname === "127.0.0.1"; + const v = new Vue({ + // eslint-disable-line no-unused-vars + el: "#modpacks", data() { return { modpackModalOpened: false, @@ -18,59 +20,65 @@ document.addEventListener("DOMContentLoaded", () => { globalBlackList: [], loading: true, form: { - search: '', - minSearchLetters: 3 + search: "", + minSearchLetters: 3, }, sentences: { - searchAdvice: 'You can search by name or by version', - lettersLeft: 'letters to start search...', + searchAdvice: "You can search by name or by version", + lettersLeft: "letters to start search...", loading: ' Loading mods...', - failed: 'Failed to load mods. Check console for more informations', - noresults: 'No results found for your search: ', - noResultsVersion: 'No results found for version', - typeAnotherVersion: 'Try to type another version than' + failed: "Failed to load mods. Check console for more informations", + noresults: "No results found for your search: ", + noResultsVersion: "No results found for version", + typeAnotherVersion: "Try to type another version than", }, }; }, methods: { openModpackModal(index) { - this.currentModpackIndex = index - this.modpackModalOpened = true + this.currentModpackIndex = index; + this.modpackModalOpened = true; }, - downloadModpackFromModList(modpackId, modpackName, modpackVersion, minecraftVersion, modsId = []) { + downloadModpackFromModList( + modpackId, + modpackName, + modpackVersion, + minecraftVersion, + modsId = [], + ) { this.modpacks.push({ modpackName: modpackName, modpackVersion: modpackVersion, minecraftVersion: minecraftVersion, coverSource: `${this.apiURL}/v2/mods/${modpackId}/thumbnail`, modList: modsId, - }) + }); }, getDataFromDB() { fetch(`${this.apiURL}/v2/mods/raw`) .then((res) => res.json()) .then((json) => { - this.mods = json - this.loading = false + this.mods = json; + this.loading = false; }) - .catch(console.error) + .catch(console.error); fetch(`${this.apiURL}/v2/modpacks/raw`) .then((res) => res.json()) .then((json) => { // sort by modpack name value - const sortable = [] + const sortable = []; for (const mod in json) { - sortable.push([mod, json[mod]]) + sortable.push([mod, json[mod]]); } sortable.sort((a, b) => { - if (a[1].name.toLowerCase() < b[1].name.toLowerCase()) return -1 - if (a[1].name.toLowerCase() > b[1].name.toLowerCase()) return 1 - return 0 - }) + if (a[1].name.toLowerCase() < b[1].name.toLowerCase()) return -1; + if (a[1].name.toLowerCase() > b[1].name.toLowerCase()) return 1; + return 0; + }); - const sorted = [] - sortable.forEach((item) => sorted.push({ ...item[1], id: item[0] })) + const sorted = []; + sortable.forEach((item) => sorted.push({ ...item[1], id: item[0] })); sorted.forEach((modpack) => { Object.keys(modpack.versions).forEach((version) => { @@ -79,61 +87,71 @@ document.addEventListener("DOMContentLoaded", () => { modpack.name, version, modpack.versions[version].minecraft, - modpack.versions[version].mods - ) - }) - }) - }).catch(console.error) - } + modpack.versions[version].mods, + ); + }); + }); + }) + .catch(console.error); + }, }, computed: { apiURL() { - return window.location.hostname === '127.0.0.1' ? - 'http://localhost:8000' : - 'https://api.faithfulpack.net' + return window.location.hostname === "127.0.0.1" + ? "http://localhost:8000" + : "https://api.faithfulpack.net"; }, currentModpack() { - return this.currentModpackIndex > -1 ? this.modpacks[this.currentModpackIndex] : undefined + return this.currentModpackIndex > -1 ? this.modpacks[this.currentModpackIndex] : undefined; }, filteredModpacks() { if (this.modpacks.length === 0) { - return [] + return []; } if (this.form.search.length >= 1 && !isNaN(parseInt(this.form.search.charAt(0)))) { return this.modpacks.filter((mp) => { - return mp.minecraftVersion.startsWith(this.form.search) || mp.modpackVersion.startsWith(this.form.search) - }) + return ( + mp.minecraftVersion.startsWith(this.form.search) || + mp.modpackVersion.startsWith(this.form.search) + ); + }); } if (this.form.search.length >= this.form.minSearchLetters) { - return this.modpacks.filter((mp) => mp.modpackName.toLowerCase().includes(this.form.search.toLowerCase())) + return this.modpacks.filter((mp) => + mp.modpackName.toLowerCase().includes(this.form.search.toLowerCase()), + ); } - return this.modpacks + return this.modpacks; }, searchAdvice() { - if (this.modpacks.length === 0) { return '' } + if (this.modpacks.length === 0) { + return ""; + } if ( this.form.search.length >= 1 && !isNaN(parseInt(this.form.search.charAt(0))) && this.filteredModpacks.length === 0 ) - return this.sentences.typeAnotherVersion + ' ' + this.form.search + return this.sentences.typeAnotherVersion + " " + this.form.search; if (this.form.search.length < this.form.minSearchLetters) - return String((this.form.minSearchLetters - this.form.search.length) + ' ' + this.sentences.lettersLeft) - return '' - } + return String( + this.form.minSearchLetters - this.form.search.length + " " + this.sentences.lettersLeft, + ); + return ""; + }, }, created() { - document.addEventListener('DOMContentLoaded', () => { + document.addEventListener("DOMContentLoaded", () => { retryAxios.attach(axios, { retries: 5, - retryDelay: () => 3000 - }) - }) + retryDelay: () => 3000, + }); + }); - this.getDataFromDB() - } - }) -}) + this.getDataFromDB(); + }, + }); +}); diff --git a/js/mods/mods.js b/js/mods/mods.js index e7e63077..0ba9a6c3 100644 --- a/js/mods/mods.js +++ b/js/mods/mods.js @@ -3,17 +3,18 @@ Object.filter = (obj, predicate) => Object.keys(obj) .filter((key) => predicate(obj[key])) - .reduce((res, key) => (res[key] = obj[key], res), {}); + .reduce((res, key) => ((res[key] = obj[key]), res), {}); document.addEventListener("DOMContentLoaded", () => { - Vue.config.devtools = location.hostname === 'localhost' || location.hostname === '127.0.0.1' - const v = new Vue({ // eslint-disable-line no-unused-vars - el: '#app', + Vue.config.devtools = location.hostname === "localhost" || location.hostname === "127.0.0.1"; + const v = new Vue({ + // eslint-disable-line no-unused-vars + el: "#app", data() { return { form: { - search: '', - minSearchLetters: 3 + search: "", + minSearchLetters: 3, }, isMounted: false, isLoadingDownload: false, @@ -21,60 +22,60 @@ document.addEventListener("DOMContentLoaded", () => { loadingVersions: true, mods: [], sentences: { - searchAdvice: 'You can search by name or by version', - lettersLeft: 'letters to start search...', + searchAdvice: "You can search by name or by version", + lettersLeft: "letters to start search...", loading: ' Loading mods...', - failed: 'Failed to load mods. Check console for more informations', - noresults: 'No results found for your search: ', - noResultsVersion: 'No results found for version', - typeAnotherVersion: 'Try to type another version than' + failed: "Failed to load mods. Check console for more informations", + noresults: "No results found for your search: ", + noResultsVersion: "No results found for version", + typeAnotherVersion: "Try to type another version than", }, versions: {}, breakpointLimits: { xs: 575, sm: 785, md: 1200, - lg: Infinity + lg: Infinity, }, - windowSize: window.innerWidth + windowSize: window.innerWidth, }; }, computed: { apiURL() { - return window.location.hostname === '127.0.0.1' ? - 'http://localhost:8000' : - 'https://api.faithfulpack.net' + return window.location.hostname === "127.0.0.1" + ? "http://localhost:8000" + : "https://api.faithfulpack.net"; }, breakpoints() { - const result = {} + const result = {}; - const keys = Object.keys(this.breakpointLimits) + const keys = Object.keys(this.breakpointLimits); for (let i = 0; i < keys.length; ++i) { - result[keys[i]] = this.windowSize <= this.breakpointLimits[keys[i]] + result[keys[i]] = this.windowSize <= this.breakpointLimits[keys[i]]; } - return result + return result; }, canPackMods() { - return this.modPackageVersion !== undefined + return this.modPackageVersion !== undefined; }, emptyTable() { - if (this.loading === true) return this.sentences.loading + if (this.loading === true) return this.sentences.loading; - if (this.mods.length === 0) return this.sentences.failed + if (this.mods.length === 0) return this.sentences.failed; if ( this.form.search.length >= 1 && !isNaN(parseInt(this.form.search.charAt(0))) && this.filteredMods.length === 0 ) { - return this.sentences.noResultsVersion + ' ' + this.form.search + return this.sentences.noResultsVersion + " " + this.form.search; } - if (this.filteredMods.length === 0) return this.sentences.noresults + this.form.search + if (this.filteredMods.length === 0) return this.sentences.noresults + this.form.search; - return '' + return ""; }, /** * Filter mods following the research @@ -83,216 +84,251 @@ document.addEventListener("DOMContentLoaded", () => { filteredMods() { if (this.form.search.length >= 1 && !isNaN(parseInt(this.form.search.charAt(0)))) { return this.mods.filter((mod) => { - let found = false - let i = 0 + let found = false; + let i = 0; while (i < mod.resource_pack.versions.length && !found) { - found = mod.resource_pack.versions[i].startsWith(this.form.search) - ++i + found = mod.resource_pack.versions[i].startsWith(this.form.search); + ++i; } - return found - }) + return found; + }); } if (this.form.search.length >= this.form.minSearchLetters) { return this.mods.filter((mod) => { - const searchTerm = this.form.search.toLowerCase() - if (this.modToDisplayName(mod).toLowerCase().includes(searchTerm)) return true + const searchTerm = this.form.search.toLowerCase(); + if (this.modToDisplayName(mod).toLowerCase().includes(searchTerm)) return true; - let inAliases = false - let i = 0 - let aliases = mod.aliases || [] + let inAliases = false; + let i = 0; + let aliases = mod.aliases || []; while (i < aliases.length && !inAliases) { - inAliases = aliases[i].toLowerCase().includes(searchTerm) + inAliases = aliases[i].toLowerCase().includes(searchTerm); i++; } - return inAliases - }) + return inAliases; + }); } - return this.mods + return this.mods; }, exactVersionMode() { - if (this.loadingVersions) { return false } + if (this.loadingVersions) { + return false; + } - return this.modSelection.findIndex((mod) => { - const correspondingNumbers = MinecraftUtils.minecraftVersionsToNumbers([this.versions['1'].min, mod.version]) + return ( + this.modSelection.findIndex((mod) => { + const correspondingNumbers = MinecraftUtils.minecraftVersionsToNumbers([ + this.versions["1"].min, + mod.version, + ]); - return correspondingNumbers[1] < correspondingNumbers[0] - }) !== -1 + return correspondingNumbers[1] < correspondingNumbers[0]; + }) !== -1 + ); }, modSelection() { - const selection = this.mods.filter((mod) => mod.selected && !!mod.versionSelected) + const selection = this.mods.filter((mod) => mod.selected && !!mod.versionSelected); return selection.map((mod) => { - return this.modToSelection(mod) - }) + return this.modToSelection(mod); + }); }, downloadButtonText() { - return this.isLoadingDownload ? ' Sending request...' : 'Download Resource Pack' + return this.isLoadingDownload + ? ' Sending request...' + : "Download Resource Pack"; }, minecraftVersions() { - const mcVersions = [] + const mcVersions = []; for (let i = 0; i < this.mods.length; ++i) { for (let a = 0; a < this.mods[i].resource_pack.versions.length; ++a) { - let index - if ((index = mcVersions.findIndex((item) => item.version === this.mods[i].resource_pack.versions[a])) === -1) { + let index; + if ( + (index = mcVersions.findIndex( + (item) => item.version === this.mods[i].resource_pack.versions[a], + )) === -1 + ) { mcVersions.push({ version: this.mods[i].resource_pack.versions[a], - count: 1 - }) + count: 1, + }); } else { - mcVersions[index].count = mcVersions[index].count + 1 + mcVersions[index].count = mcVersions[index].count + 1; } } } - return mcVersions + return mcVersions; }, modPackageVersion() { // you can pack mods if they have the same package version number // (list of package number must not change) // we need mods and versions to be loaded - if (this.loading || this.loadingVersions || this.modSelection.length === 0) { return undefined } + if (this.loading || this.loadingVersions || this.modSelection.length === 0) { + return undefined; + } - let result - let versionChanged = false - let minecraftVersion + let result; + let versionChanged = false; + let minecraftVersion; - let i = 0 + let i = 0; while (i < this.modSelection.length && !versionChanged) { if (this.exactVersionMode) { - const tmp = this.modSelection[i].version + const tmp = this.modSelection[i].version; if (minecraftVersion === undefined) { - minecraftVersion = tmp + minecraftVersion = tmp; } else { - if (minecraftVersion !== tmp) { versionChanged = true } + if (minecraftVersion !== tmp) { + versionChanged = true; + } } } else { - const tmp = this.packageVersion(this.modSelection[i].version) + const tmp = this.packageVersion(this.modSelection[i].version); if (result === undefined) { - result = tmp + result = tmp; } else { - if (result !== tmp) { versionChanged = true } + if (result !== tmp) { + versionChanged = true; + } } } - ++i + ++i; } - return versionChanged ? undefined : (result || minecraftVersion) + return versionChanged ? undefined : result || minecraftVersion; }, searchAdvice() { - if (this.loading === true || this.mods.length === 0) { return '' } + if (this.loading === true || this.mods.length === 0) { + return ""; + } if ( this.form.search.length >= 1 && !isNaN(parseInt(this.form.search.charAt(0))) && this.filteredMods.length === 0 ) - return this.sentences.typeAnotherVersion + ' ' + this.form.search + return this.sentences.typeAnotherVersion + " " + this.form.search; if (this.form.search.length < this.form.minSearchLetters) - return String((this.form.minSearchLetters - this.form.search.length) + ' ' + this.sentences.lettersLeft) - } + return String( + this.form.minSearchLetters - this.form.search.length + " " + this.sentences.lettersLeft, + ); + }, }, methods: { modToDisplayName(mod) { - return mod.name + return mod.name; }, modToRepoName(mod) { if (!mod || !mod.resource_pack || !mod.resource_pack.git_repository) { - console.error(mod) - throw new Error("Mod doesn't have a repository") + console.error(mod); + throw new Error("Mod doesn't have a repository"); } - return mod.resource_pack.git_repository.split('/').pop() + return mod.resource_pack.git_repository.split("/").pop(); }, modToRepoURL(mod) { - return mod.resource_pack.git_repository + return mod.resource_pack.git_repository; }, modToSelection(mod, version = undefined) { return { name: this.modToRepoName(mod), displayName: this.modToDisplayName(mod), repositoryURL: this.modToRepoURL(mod), - version: mod.versionSelected || version - } + version: mod.versionSelected || version, + }; }, packageVersion(modVersion) { - const numbers = MinecraftUtils.minecraftVersionToNumberArray(modVersion) + const numbers = MinecraftUtils.minecraftVersionToNumberArray(modVersion); - const versionKeys = Object.keys(this.versions) + const versionKeys = Object.keys(this.versions); - let i = 0 - let result = -1 + let i = 0; + let result = -1; while (i < versionKeys.length && result === -1) { - const otherNumbersMin = MinecraftUtils.minecraftVersionToNumberArray(this.versions[versionKeys[i]].min) - const otherNumbersMax = MinecraftUtils.minecraftVersionToNumberArray(this.versions[versionKeys[i]].max) + const otherNumbersMin = MinecraftUtils.minecraftVersionToNumberArray( + this.versions[versionKeys[i]].min, + ); + const otherNumbersMax = MinecraftUtils.minecraftVersionToNumberArray( + this.versions[versionKeys[i]].max, + ); // we compute the corresponding numbers - const correspondingNumbers = MinecraftUtils.minecraftVersionsToNumbers([numbers, otherNumbersMin, otherNumbersMax]) - - if (correspondingNumbers[0] >= correspondingNumbers[1] && correspondingNumbers[0] <= correspondingNumbers[2]) { - result = versionKeys[i] + const correspondingNumbers = MinecraftUtils.minecraftVersionsToNumbers([ + numbers, + otherNumbersMin, + otherNumbersMax, + ]); + + if ( + correspondingNumbers[0] >= correspondingNumbers[1] && + correspondingNumbers[0] <= correspondingNumbers[2] + ) { + result = versionKeys[i]; } - ++i + ++i; } - if (result === -1) - throw new Error('No versions file') + if (result === -1) throw new Error("No versions file"); - return result - } + return result; + }, }, mounted() { - this.isMounted = true + this.isMounted = true; // acquire mods json from Faithful database fetch(`${this.apiURL}/v2/mods/raw`) .then((res) => res.json()) .then((json) => { // sort by mod name value - const sortable = [] + const sortable = []; for (const mod in json) { - sortable.push([mod, json[mod]]) + sortable.push([mod, json[mod]]); } sortable.sort((a, b) => { - if (a[1].name.toLowerCase() < b[1].name.toLowerCase()) return -1 - if (a[1].name.toLowerCase() > b[1].name.toLowerCase()) return 1 - return 0 - }) + if (a[1].name.toLowerCase() < b[1].name.toLowerCase()) return -1; + if (a[1].name.toLowerCase() > b[1].name.toLowerCase()) return 1; + return 0; + }); - const sorted = [] - sortable.forEach((item) => sorted.push({ ...item[1], id: item[0] })) + const sorted = []; + sortable.forEach((item) => sorted.push({ ...item[1], id: item[0] })); - this.mods = sorted - this.loading = false + this.mods = sorted; + this.loading = false; }) - .catch(console.error) + .catch(console.error); fetch(`${this.apiURL}/v2/mods/pack_versions`) .then((res) => res.json()) .then((json) => { - this.loadingVersions = false - this.versions = json + this.loadingVersions = false; + this.versions = json; }) - .catch(console.error) + .catch(console.error); // we need this part for breakpoints - this.windowSize = window.innerWidth - window.addEventListener('resize', () => { this.windowSize = window.innerWidth }) + this.windowSize = window.innerWidth; + window.addEventListener("resize", () => { + this.windowSize = window.innerWidth; + }); - document.addEventListener('DOMContentLoaded', () => { + document.addEventListener("DOMContentLoaded", () => { retryAxios.attach(axios, { retries: 5, - retryDelay: () => 3000 - }) - }) - } - }) -}) + retryDelay: () => 3000, + }); + }); + }, + }); +}); diff --git a/js/mods/polyfill.js b/js/mods/polyfill.js index 152ca4b3..13027fb5 100644 --- a/js/mods/polyfill.js +++ b/js/mods/polyfill.js @@ -1,16 +1,16 @@ if (!String.prototype.startsWith) { - Object.defineProperty(String.prototype, 'startsWith', { - value(search, rawPos) { - var pos = rawPos > 0 ? rawPos|0 : 0; - return this.substring(pos, pos + search.length) === search; - } - }); + Object.defineProperty(String.prototype, "startsWith", { + value(search, rawPos) { + var pos = rawPos > 0 ? rawPos | 0 : 0; + return this.substring(pos, pos + search.length) === search; + }, + }); } if (!Array.prototype.findIndex) { - Object.defineProperty(Array.prototype, 'findIndex', { + Object.defineProperty(Array.prototype, "findIndex", { value(predicate) { - // 1. Let O be ? ToObject(this value). + // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } @@ -21,8 +21,8 @@ if (!Array.prototype.findIndex) { var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. - if (typeof predicate !== 'function') { - throw new TypeError('predicate must be a function'); + if (typeof predicate !== "function") { + throw new TypeError("predicate must be a function"); } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. @@ -49,6 +49,6 @@ if (!Array.prototype.findIndex) { return -1; }, configurable: true, - writable: true + writable: true, }); -} \ No newline at end of file +} diff --git a/js/mods/worker/downloadWorker.js b/js/mods/worker/downloadWorker.js index 5a3c060d..a2ab91f6 100644 --- a/js/mods/worker/downloadWorker.js +++ b/js/mods/worker/downloadWorker.js @@ -1,54 +1,64 @@ /* global ResourcePackCreator, self, postMessage, importScripts */ -var window = self +var window = self; -importScripts('../core/MinecraftUtils.js', '../core/ResourcePackCreator.js', '../../axios.min.js', '../jszip.min.js', 'https://cdn.jsdelivr.net/npm/idb@6.1.5/build/iife/index-min.js', 'https://unpkg.com/retry-axios@2.4.0/dist/index.umd.js') +importScripts( + "../core/MinecraftUtils.js", + "../core/ResourcePackCreator.js", + "../../axios.min.js", + "../jszip.min.js", + "https://cdn.jsdelivr.net/npm/idb@6.1.5/build/iife/index-min.js", + "https://unpkg.com/retry-axios@2.4.0/dist/index.umd.js", +); const sendMessage = function (type, content) { postMessage({ type: type, - content: content - }) -} + content: content, + }); +}; -self.addEventListener('message', (ev) => { - const message = ev.data +self.addEventListener("message", (ev) => { + const message = ev.data; - let modSelection, canPack + let modSelection, canPack; switch (message.channel) { - case 'createPack': + case "createPack": retryAxios.attach(axios, { retries: 5, - retryDelay: () => 500 - }) + retryDelay: () => 500, + }); - modSelection = message.data.modSelection + modSelection = message.data.modSelection; - canPack = ResourcePackCreator.canPackMods(modSelection) + canPack = ResourcePackCreator.canPackMods(modSelection); if (!canPack) { - console.error('Oh no we can\'t pack your mod selection..') - return + console.error("Oh no we can't pack your mod selection.."); + return; } ResourcePackCreator.downloadLocally(modSelection, message.data.forceDownload, function (log) { - sendMessage('log', log) - }) - .catch((err) => { - sendMessage('log', err) - }) - - break - case 'fillPackVersions': - ResourcePackCreator.packVersions = message.data - break - case 'fillZipOptions': - ResourcePackCreator.zipOptions = message.data - break - case 'openDatabase': - ResourcePackCreator.openDatabase(message.data.dbName, message.data.dbVersion, message.data.storeName) - break + sendMessage("log", log); + }).catch((err) => { + sendMessage("log", err); + }); + + break; + case "fillPackVersions": + ResourcePackCreator.packVersions = message.data; + break; + case "fillZipOptions": + ResourcePackCreator.zipOptions = message.data; + break; + case "openDatabase": + ResourcePackCreator.openDatabase( + message.data.dbName, + message.data.dbVersion, + message.data.storeName, + ); + break; default: - break + break; } -}) +}); diff --git a/js/snow.js b/js/snow.js index b5ced193..13ae2168 100644 --- a/js/snow.js +++ b/js/snow.js @@ -1,35 +1,34 @@ /* global matchMedia, requestAnimationFrame */ // source : https://www.kirupa.com/html5/the_falling_snow_effect.htm -const month = new Date().getMonth() +const month = new Date().getMonth(); // december because indexed from 0 -if (month == 11 && !matchMedia('(prefers-reduced-motion)').matches) { - +if (month == 11 && !matchMedia("(prefers-reduced-motion)").matches) { // Custom CSS - const snowCSS = document.createElement("link") - snowCSS.rel = "stylesheet" - snowCSS.href = "/css/snow.css" - snowCSS.type = "text/css" - document.getElementsByTagName("head")[0].appendChild(snowCSS) + const snowCSS = document.createElement("link"); + snowCSS.rel = "stylesheet"; + snowCSS.href = "/css/snow.css"; + snowCSS.type = "text/css"; + document.getElementsByTagName("head")[0].appendChild(snowCSS); // Array to store our Snowflake objects - const snowflakes = [] + const snowflakes = []; // Global variables to store our browser's window size - let browserWidth - let browserHeight + let browserWidth; + let browserHeight; // Specify the number of snowflakes you want visible - const numberOfSnowflakes = 40 + const numberOfSnowflakes = 40; // Flag to reset the position of the snowflakes - let resetPosition = false + let resetPosition = false; // // It all starts here... // - window.addEventListener('DOMContentLoaded', generateSnowflakes, false) - window.addEventListener('resize', setResetFlag, false) + window.addEventListener("DOMContentLoaded", generateSnowflakes, false); + window.addEventListener("resize", setResetFlag, false); // // Constructor for our Snowflake object @@ -37,31 +36,31 @@ if (month == 11 && !matchMedia('(prefers-reduced-motion)').matches) { class Snowflake { constructor(element, speed, xPos, yPos) { // set initial snowflake properties - this.element = element - this.speed = speed - this.xPos = xPos - this.yPos = yPos - this.scale = 1 + this.element = element; + this.speed = speed; + this.xPos = xPos; + this.yPos = yPos; + this.scale = 1; // declare variables used for snowflake's motion - this.counter = 0 - this.sign = Math.random() < 0.5 ? 1 : -1 + this.counter = 0; + this.sign = Math.random() < 0.5 ? 1 : -1; // setting an initial opacity and size for our snowflake - this.element.style.opacity = (0.1 + Math.random()) / 3 + this.element.style.opacity = (0.1 + Math.random()) / 3; } // // The function responsible for actually moving our snowflake // update() { // using some trigonometry to determine our x and y position - this.counter += this.speed / 5000 - this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40 - this.yPos += Math.sin(this.counter) / 40 + this.speed / 30 - this.scale = 0.5 + Math.abs(10 * Math.cos(this.counter) / 20) + this.counter += this.speed / 5000; + this.xPos += (this.sign * this.speed * Math.cos(this.counter)) / 40; + this.yPos += Math.sin(this.counter) / 40 + this.speed / 30; + this.scale = 0.5 + Math.abs((10 * Math.cos(this.counter)) / 20); // setting our snowflake's position - setTransform(Math.round(this.xPos), Math.round(this.yPos), this.scale, this.element) + setTransform(Math.round(this.xPos), Math.round(this.yPos), this.scale, this.element); // if snowflake goes below the browser window, move it back to the top if (this.yPos > browserHeight) { - this.yPos = -50 + this.yPos = -50; } } } @@ -69,69 +68,69 @@ if (month == 11 && !matchMedia('(prefers-reduced-motion)').matches) { // // A performant way to set your snowflake's position and size // - function setTransform (xPos, yPos, scale, el) { - el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0) scale(${scale}, ${scale})` + function setTransform(xPos, yPos, scale, el) { + el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0) scale(${scale}, ${scale})`; } // // The function responsible for creating the snowflake // - function generateSnowflakes () { + function generateSnowflakes() { // get our snowflake element from the DOM and store it - const originalSnowflake0 = document.querySelector('.snowflake0') - const originalSnowflake1 = document.querySelector('.snowflake1') - const originalSnowflake2 = document.querySelector('.snowflake2') - const originalSnowflake3 = document.querySelector('.snowflake3') + const originalSnowflake0 = document.querySelector(".snowflake0"); + const originalSnowflake1 = document.querySelector(".snowflake1"); + const originalSnowflake2 = document.querySelector(".snowflake2"); + const originalSnowflake3 = document.querySelector(".snowflake3"); // access our snowflake element's parent container - const snowflakeContainer = originalSnowflake0.parentNode // could be originalSnowflake0/1/2 - snowflakeContainer.style.display = 'block' + const snowflakeContainer = originalSnowflake0.parentNode; // could be originalSnowflake0/1/2 + snowflakeContainer.style.display = "block"; // get our browser's size - browserWidth = document.documentElement.clientWidth - browserHeight = document.documentElement.clientHeight + browserWidth = document.documentElement.clientWidth; + browserHeight = document.documentElement.clientHeight; // create each individual snowflake for (let i = 0; i < numberOfSnowflakes / 4; i++) { // clone our original snowflake and add it to snowflakeContainer - const snowflakeClone0 = originalSnowflake0.cloneNode(true) - snowflakeContainer.appendChild(snowflakeClone0) + const snowflakeClone0 = originalSnowflake0.cloneNode(true); + snowflakeContainer.appendChild(snowflakeClone0); - const snowflakeClone1 = originalSnowflake1.cloneNode(true) - snowflakeContainer.appendChild(snowflakeClone1) + const snowflakeClone1 = originalSnowflake1.cloneNode(true); + snowflakeContainer.appendChild(snowflakeClone1); - const snowflakeClone2 = originalSnowflake2.cloneNode(true) - snowflakeContainer.appendChild(snowflakeClone2) + const snowflakeClone2 = originalSnowflake2.cloneNode(true); + snowflakeContainer.appendChild(snowflakeClone2); - const snowflakeClone3 = originalSnowflake3.cloneNode(true) - snowflakeContainer.appendChild(snowflakeClone3) + const snowflakeClone3 = originalSnowflake3.cloneNode(true); + snowflakeContainer.appendChild(snowflakeClone3); // set our snowflake's initial position and related properties - const initialXPos = getPosition(50, browserWidth) - const initialYPos = getPosition(50, browserHeight) - const speed = 5 + Math.random() * 40 + const initialXPos = getPosition(50, browserWidth); + const initialYPos = getPosition(50, browserHeight); + const speed = 5 + Math.random() * 40; // create our Snowflake object - const snowflakeObject0 = new Snowflake(snowflakeClone0, speed, initialXPos, initialYPos) - snowflakes.push(snowflakeObject0) + const snowflakeObject0 = new Snowflake(snowflakeClone0, speed, initialXPos, initialYPos); + snowflakes.push(snowflakeObject0); - const snowflakeObject1 = new Snowflake(snowflakeClone1, speed, initialXPos, initialYPos) - snowflakes.push(snowflakeObject1) + const snowflakeObject1 = new Snowflake(snowflakeClone1, speed, initialXPos, initialYPos); + snowflakes.push(snowflakeObject1); - const snowflakeObject2 = new Snowflake(snowflakeClone2, speed, initialXPos, initialYPos) - snowflakes.push(snowflakeObject2) + const snowflakeObject2 = new Snowflake(snowflakeClone2, speed, initialXPos, initialYPos); + snowflakes.push(snowflakeObject2); - const snowflakeObject3 = new Snowflake(snowflakeClone3, speed, initialXPos, initialYPos) - snowflakes.push(snowflakeObject3) + const snowflakeObject3 = new Snowflake(snowflakeClone3, speed, initialXPos, initialYPos); + snowflakes.push(snowflakeObject3); } // remove the original snowflake because we no longer need it visible - snowflakeContainer.removeChild(originalSnowflake0) - snowflakeContainer.removeChild(originalSnowflake1) - snowflakeContainer.removeChild(originalSnowflake2) - snowflakeContainer.removeChild(originalSnowflake3) - moveSnowflakes() + snowflakeContainer.removeChild(originalSnowflake0); + snowflakeContainer.removeChild(originalSnowflake1); + snowflakeContainer.removeChild(originalSnowflake2); + snowflakeContainer.removeChild(originalSnowflake3); + moveSnowflakes(); } // @@ -139,36 +138,36 @@ if (month == 11 && !matchMedia('(prefers-reduced-motion)').matches) { // function moveSnowflakes() { snowflakes.forEach((item) => { - item.update() - }) + item.update(); + }); // Reset the position of all the snowflakes to a new value if (resetPosition) { - browserWidth = document.documentElement.clientWidth - browserHeight = document.documentElement.clientHeight + browserWidth = document.documentElement.clientWidth; + browserHeight = document.documentElement.clientHeight; snowflakes.forEach((item) => { - item.xPos = getPosition(50, browserWidth) - item.yPos = getPosition(50, browserHeight) - }) + item.xPos = getPosition(50, browserWidth); + item.yPos = getPosition(50, browserHeight); + }); - resetPosition = false + resetPosition = false; } - requestAnimationFrame(moveSnowflakes) + requestAnimationFrame(moveSnowflakes); } // // This function returns a number between (maximum - offset) and (maximum + offset) // function getPosition(offset, size) { - return Math.round(-1 * offset + Math.random() * (size + 2 * offset)) + return Math.round(-1 * offset + Math.random() * (size + 2 * offset)); } // // Trigger a reset of all the snowflakes' positions // function setResetFlag() { - resetPosition = true + resetPosition = true; } } diff --git a/js/stats.js b/js/stats.js index 97bd7f77..7a840440 100644 --- a/js/stats.js +++ b/js/stats.js @@ -1,28 +1,33 @@ /* global Vue */ document.addEventListener("DOMContentLoaded", () => { -Vue.config.devtools = location.hostname === 'localhost' || location.hostname === '127.0.0.1' - const v = new Vue({ // eslint-disable-line no-unused-vars - el: '#stats', + Vue.config.devtools = location.hostname === "localhost" || location.hostname === "127.0.0.1"; + const v = new Vue({ + // eslint-disable-line no-unused-vars + el: "#stats", data() { return { addons: {}, - keys: ['numberOfMinecraftVersions', 'totalNumberOfResourcePacksStored', 'numberOfModsSupported'], + keys: [ + "numberOfMinecraftVersions", + "totalNumberOfResourcePacksStored", + "numberOfModsSupported", + ], messages: { - loading: 'Loading', - numberOfMinecraftVersions: 'Minecraft Versions Supported', - numberOfModsSupported: 'Mods Supported', - totalNumberOfResourcePacksStored: 'Mod Resource Packs Stored' + loading: "Loading", + numberOfMinecraftVersions: "Minecraft Versions Supported", + numberOfModsSupported: "Mods Supported", + totalNumberOfResourcePacksStored: "Mod Resource Packs Stored", }, loading: true, numberOfMinecraftVersions: undefined, numberOfModsSupported: undefined, - totalNumberOfResourcePacksStored: undefined + totalNumberOfResourcePacksStored: undefined, }; }, computed: { loadingMessage() { - return ' ' + this.messages.loading + return ' ' + this.messages.loading; }, addonsStats() { // super duper dynamic addons stats @@ -42,56 +47,57 @@ Vue.config.devtools = location.hostname === 'localhost' || location.hostname === } } return acc; - }, {}) + }, {}); Object.keys(result).forEach((res) => { allEditions .filter((e) => !result[res][e]) .forEach((e) => { - result[res][e] = 0 - }) - }) + result[res][e] = 0; + }); + }); return result; - } + }, }, created() { - fetch('https://api.faithfulpack.net/v2/mods/raw') + fetch("https://api.faithfulpack.net/v2/mods/raw") .then((res) => res.json()) .then((json) => { - const mods = json - const versionList = [] - let resourcePacks = 0 - let modAmount = 0 - - Object.values(mods).map((e) => e.resource_pack.versions).forEach((versions) => { - versions.forEach((version) => { - // version sum - if (!versionList.includes(version)) versionList.push(version) + const mods = json; + const versionList = []; + let resourcePacks = 0; + let modAmount = 0; - // resource pack sum - ++resourcePacks - }) - // mod sum - ++modAmount - }) + Object.values(mods) + .map((e) => e.resource_pack.versions) + .forEach((versions) => { + versions.forEach((version) => { + // version sum + if (!versionList.includes(version)) versionList.push(version); + // resource pack sum + ++resourcePacks; + }); + // mod sum + ++modAmount; + }); - this.numberOfMinecraftVersions = versionList.length - this.numberOfModsSupported = modAmount - this.totalNumberOfResourcePacksStored = resourcePacks + this.numberOfMinecraftVersions = versionList.length; + this.numberOfModsSupported = modAmount; + this.totalNumberOfResourcePacksStored = resourcePacks; - this.loading = false + this.loading = false; }) .catch(console.error); - fetch('https://api.faithfulpack.net/v2/addons/approved') + fetch("https://api.faithfulpack.net/v2/addons/approved") .then((response) => response.json()) .then((data) => { - this.addons = data + this.addons = data; }) .catch(() => { - this.addons = undefined - }) - } - }) -}) + this.addons = undefined; + }); + }, + }); +}); diff --git a/js/theme.js b/js/theme.js index ae85b71d..8ab52948 100644 --- a/js/theme.js +++ b/js/theme.js @@ -1,66 +1,65 @@ /* global localStorage */ -const css = document.getElementById('theme') -const btn = document.getElementById('ThemeBtn') +const css = document.getElementById("theme"); +const btn = document.getElementById("ThemeBtn"); const THEME_VALUES = [ { - value: 'auto', - html: ' Auto Theme' + value: "auto", + html: ' Auto Theme', }, { - value: 'dark', - html: ' Dark Theme' + value: "dark", + html: ' Dark Theme', }, { - value: 'light', - html: ' Light Theme' - } -] + value: "light", + html: ' Light Theme', + }, +]; -const THEME_DEFAULT_VALUE = THEME_VALUES[0].value -const THEME_LOCALSTORAGE_KEY = 'theme' +const THEME_DEFAULT_VALUE = THEME_VALUES[0].value; +const THEME_LOCALSTORAGE_KEY = "theme"; window.theme = { get currentTheme() { - return localStorage.getItem(THEME_LOCALSTORAGE_KEY) || THEME_DEFAULT_VALUE + return localStorage.getItem(THEME_LOCALSTORAGE_KEY) || THEME_DEFAULT_VALUE; }, set currentTheme(value) { - localStorage.setItem(THEME_LOCALSTORAGE_KEY, value) + localStorage.setItem(THEME_LOCALSTORAGE_KEY, value); }, get currentThemeIndex() { - return THEME_VALUES.findIndex((el) => el.value === this.currentTheme) + return THEME_VALUES.findIndex((el) => el.value === this.currentTheme); }, set currentThemeIndex(_v) {}, get currentThemeHTML() { - return THEME_VALUES[this.currentThemeIndex].html + return THEME_VALUES[this.currentThemeIndex].html; }, set currentThemeHTML(_v) {}, get nextTheme() { - return THEME_VALUES[(this.currentThemeIndex + 1) % THEME_VALUES.length].value + return THEME_VALUES[(this.currentThemeIndex + 1) % THEME_VALUES.length].value; }, - set nextTheme(_v) {} -} + set nextTheme(_v) {}, +}; // update btn -btn.innerHTML = theme.currentThemeHTML +btn.innerHTML = theme.currentThemeHTML; window.changeMod = (change) => { // true if the btn calls the method, false otherwise if (change) { - window.theme.currentTheme = theme.nextTheme - btn.innerHTML = theme.currentThemeHTML + window.theme.currentTheme = theme.nextTheme; + btn.innerHTML = theme.currentThemeHTML; } // update theme - const isDark = ( - theme.currentTheme === 'dark' || - (theme.currentTheme === 'auto' && matchMedia('(prefers-color-scheme: dark)').matches) - ) - css.href = isDark ? '/css/dark.css' : '/css/light.css' -} + const isDark = + theme.currentTheme === "dark" || + (theme.currentTheme === "auto" && matchMedia("(prefers-color-scheme: dark)").matches); + css.href = isDark ? "/css/dark.css" : "/css/light.css"; +}; -changeMod(false) +changeMod(false); diff --git a/license.html b/license.html index 31fe5e61..bb1d1a09 100644 --- a/license.html +++ b/license.html @@ -3,97 +3,96 @@ title: License permalink: /license --- - +>

    @@ -126,7 +125,8 @@