feat: some shit
This commit is contained in:
61
src/components/Card.astro
Normal file
61
src/components/Card.astro
Normal file
@ -0,0 +1,61 @@
|
||||
---
|
||||
interface Props {
|
||||
title: string;
|
||||
body: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
const { href, title, body } = Astro.props;
|
||||
---
|
||||
|
||||
<li class="link-card">
|
||||
<a href={href}>
|
||||
<h2>
|
||||
{title}
|
||||
<span>→</span>
|
||||
</h2>
|
||||
<p>
|
||||
{body}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<style>
|
||||
.link-card {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
padding: 1px;
|
||||
background-color: #23262d;
|
||||
background-image: none;
|
||||
background-size: 400%;
|
||||
border-radius: 7px;
|
||||
background-position: 100%;
|
||||
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.link-card > a {
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
line-height: 1.4;
|
||||
padding: calc(1.5rem - 1px);
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
background-color: #23262d;
|
||||
opacity: 0.8;
|
||||
}
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
p {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.link-card:is(:hover, :focus-within) {
|
||||
background-position: 0;
|
||||
background-image: var(--accent-gradient);
|
||||
}
|
||||
.link-card:is(:hover, :focus-within) h2 {
|
||||
color: rgb(var(--accent-light));
|
||||
}
|
||||
</style>
|
24
src/components/LanguagePicker.astro
Normal file
24
src/components/LanguagePicker.astro
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
import { locales, defaultLocale, getLocale } from "astro-i18n-aut";
|
||||
import { useTranslations } from "../i18n/utils";
|
||||
|
||||
const reg = new RegExp(`^\/(${Object.keys(locales).join("|")})\/`);
|
||||
function translatePath(lang: string) {
|
||||
const p = Astro.url.pathname.replace(reg, "").replace(/^\//, "");
|
||||
if (lang === defaultLocale) return `/${p}`;
|
||||
return `/${lang}/${p}`;
|
||||
}
|
||||
|
||||
const locale = getLocale(Astro.url);
|
||||
const t = useTranslations(locale);
|
||||
---
|
||||
|
||||
<ul>
|
||||
{
|
||||
Object.entries(locales).map(([lang, label]) => (
|
||||
<li>
|
||||
<a href={translatePath(lang)}>{t(label as "de")}</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
28
src/components/Logo.astro
Normal file
28
src/components/Logo.astro
Normal file
@ -0,0 +1,28 @@
|
||||
<svg
|
||||
width="51"
|
||||
height="51"
|
||||
viewBox="0 0 51 51"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<defs>
|
||||
<style>
|
||||
#l1 {
|
||||
fill: var(--background-fill, white);
|
||||
}
|
||||
#l2 {
|
||||
fill: var(--fill, black);
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path
|
||||
id="l1"
|
||||
d="M1 1H30C41.0457 1 50 9.95431 50 21V50H21C9.9543 50 1 41.0457 1 30V1Z"
|
||||
fill="#D9D9D9"></path>
|
||||
<path
|
||||
id="l2"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M32.1858 0H0V32.3483C0.00211949 37.2944 1.96787 42.0373 5.46525 45.5347C8.96263 49.0321 13.7055 50.9979 18.6515 51H51L50.9951 18.8068C50.9944 13.8187 49.0124 9.03512 45.485 5.50823C41.9577 1.98134 37.1739 0 32.1858 0ZM6.25226 24.0718V32.3266C7.58107 32.3026 8.90553 32.1632 10.2107 31.9098C11.926 31.5636 14.3415 30.7681 16.3608 29.4766C18.3114 28.2294 20.5948 25.9682 21.9972 23.2498C23.3186 20.6901 24.2262 16.9255 24.335 12.7292C24.3623 10.4781 24.3837 8.31912 24.3991 6.25232H16.1396C16.1244 8.28561 16.1034 10.4124 16.0768 12.6327C16.0967 15.8503 15.5564 17.7243 14.6577 19.4641C13.8422 21.0463 13.1354 21.7386 11.9127 22.5209C10.7588 23.2576 9.81681 23.5661 8.58412 23.8146C7.81609 23.9716 7.03552 24.0577 6.25226 24.0718ZM32.1461 6.25232V44.7477H40.4054V9.31633C38.1307 7.34663 35.2147 6.25232 32.1858 6.25232H32.1461Z"
|
||||
fill="#CB5A5A"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
47
src/components/Nav.astro
Normal file
47
src/components/Nav.astro
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
import { getLocale } from "astro-i18n-aut";
|
||||
import { useTranslations, useTranslatedPath } from "../i18n/utils";
|
||||
import Logo from "./Logo.astro";
|
||||
|
||||
const lang = getLocale(Astro.url);
|
||||
const t = useTranslations(lang);
|
||||
const translatePath = useTranslatedPath(lang);
|
||||
---
|
||||
|
||||
<style>
|
||||
ul {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
a {
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href={translatePath("/")}
|
||||
style="--fill: red; --background-fill: transparent;"
|
||||
>
|
||||
<Logo />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={translatePath("/blog")}>
|
||||
{t("nav.blog")}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={translatePath("/about")}>
|
||||
{t("nav.about")}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
7
src/content/blog/post-01/index.en.md
Normal file
7
src/content/blog/post-01/index.en.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
date: 2021-01-01
|
||||
author: MaxEN
|
||||
title: "First Post"
|
||||
---
|
||||
|
||||
# First Post
|
7
src/content/blog/post-01/index.md
Normal file
7
src/content/blog/post-01/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
date: 2021-01-01
|
||||
author: MaxDE
|
||||
title: "Erster Post"
|
||||
---
|
||||
|
||||
# Erster post
|
7
src/content/blog/post-02/index.en.md
Normal file
7
src/content/blog/post-02/index.en.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
date: 2021-01-01
|
||||
author: MaxEN
|
||||
title: "Second Post"
|
||||
---
|
||||
|
||||
# 2. post
|
7
src/content/blog/post-02/index.md
Normal file
7
src/content/blog/post-02/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
date: 2021-01-01
|
||||
author: MaxDE
|
||||
title: "Zweiter Post"
|
||||
---
|
||||
|
||||
# 2. post
|
7
src/content/blog/post-03/index.en.md
Normal file
7
src/content/blog/post-03/index.en.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
date: 2021-01-01
|
||||
author: MaxEN
|
||||
title: "Third Post"
|
||||
---
|
||||
|
||||
# Third Post
|
7
src/content/blog/post-03/index.md
Normal file
7
src/content/blog/post-03/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
date: 2021-01-01
|
||||
author: MaxDE
|
||||
title: "Dritter Post"
|
||||
---
|
||||
|
||||
# Dritter Post
|
13
src/content/config.ts
Normal file
13
src/content/config.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
const blogCollection = defineCollection({
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
author: z.string(),
|
||||
date: z.date()
|
||||
})
|
||||
});
|
||||
|
||||
export const collections = {
|
||||
'blog': blogCollection
|
||||
};
|
2
src/env.d.ts
vendored
Normal file
2
src/env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
26
src/i18n/ui.ts
Normal file
26
src/i18n/ui.ts
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
export const languages = {
|
||||
en: 'English',
|
||||
de: 'Deutsch',
|
||||
};
|
||||
|
||||
export const defaultLang = 'de';
|
||||
|
||||
export const ui = {
|
||||
en: {
|
||||
"en": "English",
|
||||
"de": "Deutsch",
|
||||
'nav.home': 'Home',
|
||||
'nav.blog': 'Blog',
|
||||
'nav.about': 'About',
|
||||
},
|
||||
de: {
|
||||
"en": "English",
|
||||
"de": "Deutsch",
|
||||
'nav.home': 'Home',
|
||||
'nav.blog': 'Blog',
|
||||
'nav.about': 'Über',
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const showDefaultLang = false;
|
28
src/i18n/utils.ts
Normal file
28
src/i18n/utils.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { defaultLocale } from 'astro-i18n-aut';
|
||||
import { ui, defaultLang, showDefaultLang } from './ui';
|
||||
|
||||
export function useTranslatedPath(lang: string) {
|
||||
return function translatePath(path: string, l: string = lang) {
|
||||
return !showDefaultLang && l === defaultLang ? path : `/${l}${path}`.replace(/\/$/g, '');
|
||||
}
|
||||
}
|
||||
|
||||
export function useTranslations(lang: string) {
|
||||
return function t(key: keyof typeof ui[typeof defaultLang]) {
|
||||
return ui[lang as keyof typeof ui][key] || ui[defaultLang][key];
|
||||
}
|
||||
}
|
||||
|
||||
export function parseSlug(id: string) {
|
||||
const splitPath = id.split('/');
|
||||
const split = splitPath.pop()?.split('.');
|
||||
const lang = split?.length === 2 ? defaultLocale : split?.[1];
|
||||
return [splitPath.join("/"), lang]
|
||||
}
|
||||
|
||||
export function filterCollection<T extends { id: string }>(collection: T[], locale: string) {
|
||||
return collection.filter(post => {
|
||||
const [_, lang] = parseSlug(post?.id);
|
||||
return lang === locale;
|
||||
});
|
||||
}
|
41
src/layouts/Layout.astro
Normal file
41
src/layouts/Layout.astro
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
import LanguagePicker from "../components/LanguagePicker.astro";
|
||||
import Nav from "../components/Nav.astro";
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="Astro description" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="stylesheet" href="/app.css" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<!-- <meta http-equiv="refresh" content="0;url=/" /> -->
|
||||
<title>{title}</title>
|
||||
<script>
|
||||
(function () {
|
||||
try {
|
||||
var mode = localStorage.getItem("mode");
|
||||
var supportDarkMode =
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches === true;
|
||||
if (!mode && supportDarkMode)
|
||||
document.body.classList.add("theme-dark");
|
||||
if (!mode) return;
|
||||
document.body.classList.add("theme-" + mode);
|
||||
} catch (e) {}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<Nav />
|
||||
<slot />
|
||||
<LanguagePicker />
|
||||
</body>
|
||||
</html>
|
20
src/layouts/Post.astro
Normal file
20
src/layouts/Post.astro
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import Layout from "./Layout.astro";
|
||||
|
||||
type Props = CollectionEntry<"blog">["data"];
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<Layout title={title}>
|
||||
<article>
|
||||
<div class="prose">
|
||||
<div class="title">
|
||||
<h1>{title}</h1>
|
||||
<hr />
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
</article>
|
||||
</Layout>
|
5
src/pages/about/index.astro
Normal file
5
src/pages/about/index.astro
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout title="Home"> Sup people :) </Layout>
|
26
src/pages/api/blog/[slug].json.ts
Normal file
26
src/pages/api/blog/[slug].json.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
export async function GET({ params }: { params: { slug: string } }) {
|
||||
|
||||
const pages = await getCollection('blog');
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(pages.filter(post => {
|
||||
return post.id.includes(params.slug)
|
||||
})
|
||||
))
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
|
||||
const pages = await getCollection('blog');
|
||||
|
||||
return pages.map(p => {
|
||||
const [postId] = p.id.split('/');
|
||||
return {
|
||||
params: {
|
||||
slug: postId
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
39
src/pages/blog/[slug].astro
Normal file
39
src/pages/blog/[slug].astro
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import Post from "../../layouts/Post.astro";
|
||||
import { getLocale } from "astro-i18n-aut";
|
||||
import { filterCollection, parseSlug } from "../../i18n/utils";
|
||||
|
||||
const locale = getLocale(Astro.url);
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const pages = await getCollection("blog");
|
||||
|
||||
const paths = pages.map((page) => {
|
||||
const [slug] = parseSlug(page.id);
|
||||
|
||||
return { params: { slug }, props: {...page} };
|
||||
});
|
||||
|
||||
console.log("PATHS");
|
||||
console.log(paths);
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
const pages = await getCollection("blog");
|
||||
const page = filterCollection(pages, locale).find((page) => {
|
||||
const [slug] = parseSlug(page.id);
|
||||
return slug === Astro.params.slug;
|
||||
});
|
||||
const formattedDate = page.data?.date?.toLocaleString(locale);
|
||||
|
||||
const { Content } = await page.render();
|
||||
---
|
||||
|
||||
{locale}
|
||||
{JSON.stringify(Astro.params)}
|
||||
<Post {...page.data}>
|
||||
<p>by {page.data.author} • {formattedDate}</p>
|
||||
<Content />
|
||||
</Post>
|
30
src/pages/blog/index.astro
Normal file
30
src/pages/blog/index.astro
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
const pages = await getCollection('blog');
|
||||
import Layout from '../../layouts/Layout.astro';
|
||||
|
||||
import { getLocale } from "astro-i18n-aut";
|
||||
import { filterCollection } from '../../i18n/utils';
|
||||
|
||||
const locale = getLocale(Astro.url);
|
||||
|
||||
const posts = filterCollection(pages, locale);
|
||||
console.log({posts, locale});
|
||||
---
|
||||
|
||||
<Layout title="Dude">
|
||||
<hr/>
|
||||
{
|
||||
posts.map((post) => (
|
||||
<>
|
||||
<a href={"blog/"+post.slug.split("/")[0]}>
|
||||
{post.data.title}
|
||||
</a><br/>
|
||||
</>
|
||||
))
|
||||
}
|
||||
<hr/>
|
||||
</Layout>
|
||||
|
||||
|
||||
|
13
src/pages/index.astro
Normal file
13
src/pages/index.astro
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Layout title="dude">
|
||||
|
||||
# Das ist mein Blog
|
||||
|
||||
</Layout>
|
||||
|
||||
|
Reference in New Issue
Block a user