Major rewrite for 0.1.6 - Dynamic database entry generation based on json files, dynamic run page generation and more
|
@ -2,9 +2,7 @@ on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- '[0-9]+\.[0-9]+\.[0-9]+'
|
- '[0-9]+\.[0-9]+\.[0-9]+'
|
||||||
- '[0-9]+\.[0-9]+\.[0-9]+a[0-9]+'
|
- '[0-9]+\.[0-9]+\.[0-9]+pre[0-9]+'
|
||||||
- '[0-9]+\.[0-9]+\.[0-9]+b[0-9]+'
|
|
||||||
- '[0-9]+\.[0-9]+\.[0-9]+rc[0-9]+'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
checking:
|
checking:
|
||||||
|
@ -25,6 +23,10 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
config-inline: |
|
||||||
|
[registry."docker.io"]
|
||||||
|
mirrors = ["https://docker-cache.neshweb.net"]
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
|
|
5
.prettierignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
**/.git
|
||||||
|
**/node_modules
|
||||||
|
**/.vscode
|
||||||
|
**/public
|
||||||
|
**/dist
|
6
.prettierrc
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
2
.vscode/settings.json
vendored
|
@ -7,7 +7,7 @@
|
||||||
"**/.DS_Store": true,
|
"**/.DS_Store": true,
|
||||||
"**/Thumbs.db": true,
|
"**/Thumbs.db": true,
|
||||||
"**/__pycache__": true,
|
"**/__pycache__": true,
|
||||||
"**/node_modules": false
|
"**/node_modules": true
|
||||||
},
|
},
|
||||||
"hide-files.files": []
|
"hide-files.files": []
|
||||||
}
|
}
|
2265
package-lock.json
generated
16
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "fgo-ta-com-website",
|
"name": "fgo-ta-com-website",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.1.5",
|
"version": "0.1.6",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"start": "astro dev",
|
"start": "astro dev",
|
||||||
|
@ -10,7 +10,17 @@
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astro-community/astro-embed-youtube": "^0.4.3",
|
||||||
|
"@astrojs/check": "^0.3.4",
|
||||||
"@astrojs/sitemap": "^3.0.3",
|
"@astrojs/sitemap": "^3.0.3",
|
||||||
"astro": "^4.0.7"
|
"astro": "^4.0.7",
|
||||||
}
|
"autoprefixer": "^10.4.16",
|
||||||
|
"iconoir": "^7.3.0",
|
||||||
|
"postcss-preset-env": "^9.3.0",
|
||||||
|
"typescript": "^5.3.3"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"last 2 versions",
|
||||||
|
">0.5% and not dead"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 7 KiB After Width: | Height: | Size: 7 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/ta_servants/shishou.png
Normal file
After Width: | Height: | Size: 31 KiB |
|
@ -1,4 +1,7 @@
|
||||||
---
|
---
|
||||||
|
import packagejson from '../../package.json'
|
||||||
|
const version = packagejson.version
|
||||||
|
const release = `https://forgejo.neshweb.net/Firq/fgo-ta-com-website/releases/tag/${version}`
|
||||||
---
|
---
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -9,6 +12,8 @@
|
||||||
game in general.
|
game in general.
|
||||||
<br />
|
<br />
|
||||||
<a href="https://firq.dev" target="_blank" rel="noopener noreferrer">Feel free to check out my own site.</a>
|
<a href="https://firq.dev" target="_blank" rel="noopener noreferrer">Feel free to check out my own site.</a>
|
||||||
|
<br />
|
||||||
|
<span class="version">(Website version: <a href={release} target="_blank" rel="noopener noreferrer">{version}</a>)</span>
|
||||||
</span>
|
</span>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,5 +35,10 @@
|
||||||
a {
|
a {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
color: var(--c-darkpurple);
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
font-size: 0.7em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
---
|
---
|
||||||
|
import { Image } from 'astro:assets';
|
||||||
|
import logo from '../assets/logo.svg'
|
||||||
|
import hamburger from 'iconoir/icons/menu.svg'
|
||||||
|
const hamburger_src_url = `url("${hamburger.src}")`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<a href="/" rel="noopener noreferrer" aria-label="Home">
|
<a href="/" rel="noopener noreferrer" aria-label="Home">
|
||||||
<img src="/assets/logo.svg" alt="" />
|
<Image src={logo} alt="Website Logo"/>
|
||||||
</a>
|
</a>
|
||||||
<ul class="desktop">
|
<ul class="desktop">
|
||||||
<slot />
|
<slot />
|
||||||
|
@ -13,11 +17,11 @@
|
||||||
<slot />
|
<slot />
|
||||||
</ul>
|
</ul>
|
||||||
<div class="placeholder"></div>
|
<div class="placeholder"></div>
|
||||||
<i class="iconoir-menu"></i>
|
<div class="hamburger-menu"></div>
|
||||||
</button>
|
</button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<style>
|
<style define:vars={{ hamburger_src_url }}>
|
||||||
header {
|
header {
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
|
@ -79,16 +83,6 @@
|
||||||
height: 64px;
|
height: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile > i {
|
|
||||||
position: static;
|
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 2em;
|
|
||||||
align-self: flex-start;
|
|
||||||
padding-right: 1em;
|
|
||||||
padding-top: 1.15rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile > ul {
|
.mobile > ul {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
@ -111,6 +105,17 @@
|
||||||
justify-self: top;
|
justify-self: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hamburger-menu {
|
||||||
|
mask: var(--hamburger_src_url) no-repeat center;
|
||||||
|
background-color: white;
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
position: static;
|
||||||
|
align-self: flex-start;
|
||||||
|
padding-right: 1em;
|
||||||
|
padding-top: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 1140px) {
|
@media (min-width: 1140px) {
|
||||||
.mobile {
|
.mobile {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -3,7 +3,7 @@ export interface Props {
|
||||||
currentPage?: string
|
currentPage?: string
|
||||||
link: string
|
link: string
|
||||||
text: string
|
text: string
|
||||||
icon: string
|
icon: ImageMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
const { icon, text, link, currentPage } = Astro.props
|
const { icon, text, link, currentPage } = Astro.props
|
||||||
|
@ -17,6 +17,7 @@ if (currentPage === slug) {
|
||||||
currPage = 'current'
|
currPage = 'current'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const icon_src_url = `url("${icon.src}")`;
|
||||||
const fulllink = `/${slug}`
|
const fulllink = `/${slug}`
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -28,12 +29,12 @@ const fulllink = `/${slug}`
|
||||||
class={currPage}
|
class={currPage}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<i class={icon}></i>
|
<div class="icon"></div>
|
||||||
{text}
|
{text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<style>
|
<style define:vars={{ icon_src_url }}>
|
||||||
li {
|
li {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -41,7 +42,9 @@ const fulllink = `/${slug}`
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
li > a {
|
li > a {
|
||||||
|
display: inline-flex;
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -49,11 +52,29 @@ const fulllink = `/${slug}`
|
||||||
font-size: 1.4em;
|
font-size: 1.4em;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
gap: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
li > a:hover {
|
li > a:hover {
|
||||||
color: var(--c-purplepink);
|
color: var(--c-purplepink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li > a:hover > .icon {
|
||||||
|
background-color: var(--c-purplepink);
|
||||||
|
}
|
||||||
|
|
||||||
.current {
|
.current {
|
||||||
color: var(--c-darkpurple);
|
color: var(--c-darkpurple) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current > .icon {
|
||||||
|
background-color: var(--c-darkpurple) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
mask: var(--icon_src_url) no-repeat center;
|
||||||
|
background-color: white;
|
||||||
|
width: 1.4em;
|
||||||
|
height: 1.4em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
103
src/components/questListing.astro
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
export interface Props {
|
||||||
|
url: string | undefined
|
||||||
|
title: string
|
||||||
|
questReleaseDate: string
|
||||||
|
shortdescription: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const options_date: Intl.DateTimeFormatOptions = {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: '2-digit',
|
||||||
|
}
|
||||||
|
const { shortdescription, questReleaseDate, url, title } = Astro.props
|
||||||
|
const render_date = new Date(questReleaseDate).toLocaleDateString('en-GB', options_date)
|
||||||
|
---
|
||||||
|
|
||||||
|
<a href={url} rel="noopener noreferrer">
|
||||||
|
<div class="circle"></div>
|
||||||
|
<article>
|
||||||
|
<h2>{title}</h2>
|
||||||
|
<h3>{render_date}</h3>
|
||||||
|
<p>{shortdescription}</p>
|
||||||
|
</article>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.circle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (min-width: 900px) {
|
||||||
|
.circle {
|
||||||
|
margin: 1rem 1rem 1rem 0rem;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
visibility: visible;
|
||||||
|
height: 1.5rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
border-radius: 40%;
|
||||||
|
background-color: var(--c-darkpurple);
|
||||||
|
transition: transform var(--speed) var(--ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover > .circle {
|
||||||
|
height: 1.75rem;
|
||||||
|
width: 1.75rem;
|
||||||
|
translate: -0.125rem;
|
||||||
|
margin-right: 0.825rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
text-decoration: none;
|
||||||
|
height: auto;
|
||||||
|
margin: 0.5rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: white;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
article > h2 {
|
||||||
|
margin: 0.3rem 0.5rem;
|
||||||
|
color: var(--c-darkpurple);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
article > h3 {
|
||||||
|
margin: 0.2em 0.5rem;
|
||||||
|
color: white;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
article {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-content: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: var(--c-darkergray);
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
transition: transform var(--speed) var(--ease);
|
||||||
|
min-height: 100%;
|
||||||
|
border-radius: 1.25rem;
|
||||||
|
}
|
||||||
|
a:hover > article {
|
||||||
|
transform: scaleY(102.5%) scaleX(101%);
|
||||||
|
}
|
||||||
|
</style>
|
184
src/components/taCard.astro
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
---
|
||||||
|
import type { ImageMetadata } from 'astro'
|
||||||
|
import { Image } from 'astro:assets'
|
||||||
|
export interface Props {
|
||||||
|
title: string,
|
||||||
|
link: string,
|
||||||
|
date: string,
|
||||||
|
servant: string,
|
||||||
|
turns: string,
|
||||||
|
runner: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { turns, runner, date, servant, link, title } =
|
||||||
|
Astro.props
|
||||||
|
|
||||||
|
const options_date: Intl.DateTimeFormatOptions = {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
}
|
||||||
|
|
||||||
|
const servantImagePath = `/src/assets/ta_servants/${servant}.png`
|
||||||
|
|
||||||
|
const formatted_date = new Date(date).toLocaleDateString('de-DE', options_date)
|
||||||
|
const servant_images = import.meta.glob<{ default: ImageMetadata }>(
|
||||||
|
'/src/assets/ta_servants/*.png'
|
||||||
|
)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a href={link} target="_blank" rel="noopener noreferrer" aria-label={title}>
|
||||||
|
<article>
|
||||||
|
<Image src={servant_images[servantImagePath]()} alt="" class="icon"/>
|
||||||
|
<div class="title">
|
||||||
|
<h2>{title}</h2>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<span>
|
||||||
|
By {runner}<br /> •
|
||||||
|
</span>
|
||||||
|
{formatted_date}
|
||||||
|
</p>
|
||||||
|
<div class="expand-on-hover">
|
||||||
|
<h2>{turns}</h2>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
background-color: var(--c-darkergray);
|
||||||
|
border-color: var(--c-darkgray);
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
transition: transform var(--speed) var(--ease);
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
max-width: 8rem;
|
||||||
|
border-radius: 1.25rem;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
--size-value: 7rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
article:hover {
|
||||||
|
transform: scale(var(--hover-scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
article > .icon {
|
||||||
|
border-radius: 1.25rem;
|
||||||
|
width: var(--size-value);
|
||||||
|
height: var(--size-value);
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article:hover .title {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
background-color: var(--c-darkgray);
|
||||||
|
height: calc(var(--size-value) + 0.1rem);
|
||||||
|
width: calc(var(--size-value) + 0.1rem);
|
||||||
|
opacity: 90%;
|
||||||
|
border-radius: 1.25rem;
|
||||||
|
top: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
article:hover .title h2 {
|
||||||
|
margin: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 150%;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article .title h2 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
article .title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
margin: 0.5rem 0px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-on-hover {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
background-color: var(--c-duskgray);
|
||||||
|
z-index: 99;
|
||||||
|
transform: scaleY(0);
|
||||||
|
transform-origin: top;
|
||||||
|
position: absolute;
|
||||||
|
top: 90%;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
color: white;
|
||||||
|
border-radius: 0px 0px 1.25rem 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-on-hover img {
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-on-hover h2 {
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
article:hover .expand-on-hover {
|
||||||
|
transform: scaleY(1);
|
||||||
|
transition: transform 200ms ease-in-out;
|
||||||
|
background-color: var(--c-duskgray);
|
||||||
|
}
|
||||||
|
</style>
|
26
src/content/data/cernunnos.json
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"info": {
|
||||||
|
"title": "Cernunnos",
|
||||||
|
"questReleaseDate": "2023-07-10",
|
||||||
|
"shortdescription": "One of FGOs most notorious boss fights due to up to 100% special defense, strong DoT damage and powerful field effects",
|
||||||
|
"description": "One of FGOs most notorious boss fights due to up to 100% special defense, strong DoT damage and powerful field effects - and still, the TA community prevailed and created some of the most amazing runs of all time"
|
||||||
|
},
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"title": "Cernunnos 4T (No Castoria)",
|
||||||
|
"link": "https://www.youtube.com/watch?v=WrHudtdfivA",
|
||||||
|
"date": "2023-07-19",
|
||||||
|
"servant": "shishou",
|
||||||
|
"turns": "4T",
|
||||||
|
"runner": "Firq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Cernunnos 4T (FLO)",
|
||||||
|
"link": "https://www.youtube.com/watch?O1f-go7uJQM",
|
||||||
|
"date": "2023-07-19",
|
||||||
|
"servant": "shishou",
|
||||||
|
"turns": "4T",
|
||||||
|
"runner": "Requiem"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,7 +1,11 @@
|
||||||
---
|
---
|
||||||
import Navbar from '../components/navbar.astro'
|
import Navbar from '../components/navbar.astro'
|
||||||
import NavbarEntry from '../components/navbarEntry.astro'
|
import NavbarEntry from '../components/navbarEntry.astro'
|
||||||
import navdata from '../../static/assets/data/_navdata.json'
|
import navdata from '../../static/data/_navdata.json'
|
||||||
|
import embed from '../assets/embed.png'
|
||||||
|
import home from 'iconoir/icons/home.svg'
|
||||||
|
import database from 'iconoir/icons/database.svg'
|
||||||
|
import type { IconsLookup } from '../types/icons'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string
|
title: string
|
||||||
|
@ -9,6 +13,11 @@ export interface Props {
|
||||||
descriptionOverride?: string
|
descriptionOverride?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const icons: IconsLookup = {
|
||||||
|
home: home,
|
||||||
|
database: database
|
||||||
|
}
|
||||||
|
|
||||||
const { descriptionOverride, currentpage, title } = Astro.props
|
const { descriptionOverride, currentpage, title } = Astro.props
|
||||||
let description
|
let description
|
||||||
|
|
||||||
|
@ -22,6 +31,11 @@ let currPage = 'https://fgo-ta.com/'
|
||||||
if (currentpage !== 'home') {
|
if (currentpage !== 'home') {
|
||||||
currPage += currentpage
|
currPage += currentpage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapped_navdata = navdata.map((item) => ({
|
||||||
|
...item,
|
||||||
|
...{ icon: icons[item.icon] },
|
||||||
|
}))
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
@ -36,23 +50,19 @@ if (currentpage !== 'home') {
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:url" content={currPage} />
|
<meta property="og:url" content={currPage} />
|
||||||
<meta property="og:description" content={description} />
|
<meta property="og:description" content={description} />
|
||||||
<meta property="og:image" content="/assets/embed.png" />
|
<meta property="og:image" content={embed.src} />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:locale" content="en_US" />
|
<meta property="og:locale" content="en_US" />
|
||||||
<meta name="theme-color" content="#b86cff" />
|
<meta name="theme-color" content="#b86cff" />
|
||||||
<!-- Links -->
|
<!-- Links -->
|
||||||
<link rel="icon" type="image/ico" href="/assets/favicon.ico" />
|
<link rel="icon" type="image/ico" href="/favicon.ico" />
|
||||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||||
<link href="https://mastodon.neshweb.net/@Firq" rel="me" />
|
<link href="https://mastodon.neshweb.net/@Firq" rel="me" />
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="https://cdn.jsdelivr.net/gh/iconoir-icons/iconoir@main/css/iconoir.css"
|
|
||||||
/>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Navbar>
|
<Navbar>
|
||||||
{
|
{
|
||||||
navdata.map((item) => (
|
mapped_navdata.map((item) => (
|
||||||
<NavbarEntry currentPage={currentpage} {...item} />
|
<NavbarEntry currentPage={currentpage} {...item} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
---
|
---
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string
|
title: string
|
||||||
|
description: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title } = Astro.props
|
const { title, description } = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="base">
|
<div class="base">
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
|
<h2>{description}</h2>
|
||||||
<div>
|
<div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,6 +47,16 @@ const { title } = Astro.props
|
||||||
background-color: var(--c-darkgray);
|
background-color: var(--c-darkgray);
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div h2 {
|
||||||
|
color: white;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
max-width: 75;
|
||||||
|
margin: 1rem;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@media (min-width: 512px) {
|
@media (min-width: 512px) {
|
||||||
div {
|
div {
|
||||||
row-gap: 1.5em;
|
row-gap: 1.5em;
|
||||||
|
@ -64,10 +76,18 @@ const { title } = Astro.props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1500px) {
|
@media (min-width: 1140px) {
|
||||||
.base {
|
.base {
|
||||||
margin-left: 10%;
|
margin-left: 10%;
|
||||||
margin-right: 10%;
|
margin-right: 10%;
|
||||||
}
|
}
|
||||||
|
div h1 {
|
||||||
|
margin-left: unset;
|
||||||
|
margin-right: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
div h2 {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
100
src/layouts/databaseSection.astro
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
---
|
||||||
|
export interface Props {
|
||||||
|
title: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="line"></div>
|
||||||
|
<slot />
|
||||||
|
<div class="drop"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.drop {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
visibility: visible;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: -5rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
height: 1.5rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
border-radius: 0% 50% 50% 50%;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
background-color: var(--c-darkpurple);
|
||||||
|
}
|
||||||
|
.line {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
visibility: visible;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
background-color: var(--c-darkpurple);
|
||||||
|
height: calc(100% + 5rem);
|
||||||
|
translate: 0% 2rem;
|
||||||
|
width: 0.25rem;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
line-height: 48px;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
color: white;
|
||||||
|
font-size: 2.25rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
max-width: max-content;
|
||||||
|
background-color: var(--c-darkgray);
|
||||||
|
padding: 0.25rem 1.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
margin: 2rem 3rem 0.5rem 3rem;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column wrap;
|
||||||
|
row-gap: 1em;
|
||||||
|
column-gap: 1em;
|
||||||
|
align-self: center;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 1em;
|
||||||
|
color: white;
|
||||||
|
font-size: 1em;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
@media (min-width: 900px) {
|
||||||
|
.drop {
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
}
|
||||||
|
.line {
|
||||||
|
margin-left: 2.1rem;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin-left: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1500px) {
|
||||||
|
.wrapper {
|
||||||
|
margin-left: 20rem;
|
||||||
|
margin-right: 20rem;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin-left: 20rem;
|
||||||
|
margin-right: 20rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
52
src/layouts/taShowcaseLayout.astro
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
import Layout from '../layouts/Layout.astro'
|
||||||
|
import BaseSection from '../layouts/baseSection.astro'
|
||||||
|
import TACard from '../components/taCard.astro'
|
||||||
|
import type { filedata } from '../types/ta'
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
datafile: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { datafile } = Astro.props
|
||||||
|
const fulldata = import.meta.glob<{ default: any }>(
|
||||||
|
`../content/data/*.json`
|
||||||
|
)
|
||||||
|
const filecontent: filedata = (
|
||||||
|
await fulldata[`../content/data/${datafile}.json`]()
|
||||||
|
)['default']
|
||||||
|
|
||||||
|
const title = filecontent.info.title
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout
|
||||||
|
title={title}
|
||||||
|
currentpage="database-entry"
|
||||||
|
descriptionOverride={filecontent.info.shortdescription}
|
||||||
|
>
|
||||||
|
<a href="/database"><< Back to database</a>
|
||||||
|
<BaseSection title={title} description={filecontent.info.description}>
|
||||||
|
{filecontent.data.map((item) => <TACard {...item} />)}
|
||||||
|
</BaseSection>
|
||||||
|
<div class="placeholder"></div>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.placeholder {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
background-color: var(--c-gray);
|
||||||
|
padding: 0.5rem 0px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
37
src/pages/database.astro
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
import Layout from '../layouts/Layout.astro'
|
||||||
|
import QuestListing from '../components/questListing.astro'
|
||||||
|
import DatabaseSection from '../layouts/databaseSection.astro'
|
||||||
|
import { findSlug } from '../utils/slugTools'
|
||||||
|
import type { filedata } from '../types/ta'
|
||||||
|
|
||||||
|
const description =
|
||||||
|
'My own small blog. Topics include FGO, TA, Programming, web technologies and more!'
|
||||||
|
|
||||||
|
const questInfo = []
|
||||||
|
const fulldata = import.meta.glob<{ default: filedata }>(`../content/data/*.json`)
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(fulldata)) {
|
||||||
|
const url = `${Astro.url}/${findSlug(key)}`
|
||||||
|
questInfo.push({
|
||||||
|
...(await value())['default'].info,
|
||||||
|
url: url,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
questInfo.sort(
|
||||||
|
(a, b) => Date.parse(b.questReleaseDate) - Date.parse(a.questReleaseDate)
|
||||||
|
)
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout
|
||||||
|
title="TA Database"
|
||||||
|
currentpage="database"
|
||||||
|
descriptionOverride={description}
|
||||||
|
>
|
||||||
|
<DatabaseSection title="FGO NA TA Database">
|
||||||
|
{questInfo.map((quest) => <QuestListing {...quest} />)}
|
||||||
|
</DatabaseSection>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
<style></style>
|
23
src/pages/database/[slug].astro
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
import TaShowcaseLayout from '../../layouts/taShowcaseLayout.astro'
|
||||||
|
import {findSlug} from '../../utils/slugTools'
|
||||||
|
|
||||||
|
export function getStaticPaths() {
|
||||||
|
const fulldata = import.meta.glob<{ default: any }>(
|
||||||
|
`../../content/data/*.json`
|
||||||
|
)
|
||||||
|
const keylist = Object.keys(fulldata).map(
|
||||||
|
(item) => findSlug(item)
|
||||||
|
)
|
||||||
|
|
||||||
|
const paths: { params: { slug: string } }[] = []
|
||||||
|
for (const key of keylist) {
|
||||||
|
paths.push({ params: { slug: key! } })
|
||||||
|
}
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
|
const { slug } = Astro.params
|
||||||
|
---
|
||||||
|
|
||||||
|
<TaShowcaseLayout datafile={slug} />
|
3
src/types/icons.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export interface IconsLookup {
|
||||||
|
[key: string]: ImageMetadata
|
||||||
|
}
|
20
src/types/ta.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
interface tadata {
|
||||||
|
title: string
|
||||||
|
link: string
|
||||||
|
servant: string
|
||||||
|
turns: string
|
||||||
|
runner: string
|
||||||
|
date: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface info {
|
||||||
|
title: string
|
||||||
|
questReleaseDate: string
|
||||||
|
description: string
|
||||||
|
shortdescription: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface filedata {
|
||||||
|
info: info
|
||||||
|
data: tadata[]
|
||||||
|
}
|
3
src/utils/slugTools.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export function findSlug(filepath: string) {
|
||||||
|
return filepath.match(/(?:.*[\\/])(.+)(?:\.json)/)?.[1]
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"link": "/",
|
|
||||||
"text": "Home",
|
|
||||||
"icon": "iconoir-home-alt"
|
|
||||||
}
|
|
||||||
]
|
|
12
static/data/_navdata.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"link": "/",
|
||||||
|
"text": "Home",
|
||||||
|
"icon": "home"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"link": "/database",
|
||||||
|
"text": "TA Database",
|
||||||
|
"icon": "database"
|
||||||
|
}
|
||||||
|
]
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
7
static/robots.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
user-agent:*
|
||||||
|
Disallow: /assets/data/
|
||||||
|
|
||||||
|
User-agent: GPTBot
|
||||||
|
Disallow: /
|
||||||
|
|
||||||
|
Sitemap: https://firq.dev/sitemap-index.xml
|