182 lines
6.2 KiB
Plaintext
182 lines
6.2 KiB
Plaintext
---
|
|
import { type CollectionEntry, getCollection } from 'astro:content';
|
|
import getReadingTime from 'reading-time';
|
|
import { readItems, readSingleton } from '@directus/sdk';
|
|
|
|
import directus from '@lib/directus';
|
|
import { getDirectusImageURL } from '@lib/directusFunctions';
|
|
import BaseLayout from '@layouts/BaseLayout.astro';
|
|
import Image from '@components/ui/images/Image.astro';
|
|
import { formatDateTime } from '@support/time';
|
|
|
|
export async function getStaticPaths() {
|
|
const posts = await directus.request(readItems('posts'));
|
|
return posts.map((post) => ({
|
|
params: { slug: post.slug },
|
|
props: post,
|
|
}));
|
|
}
|
|
const post = Astro.props;
|
|
|
|
const global = await directus.request(readSingleton('site_global'));
|
|
const category: CollectionEntry<'categories'> = (await getCollection('categories'))
|
|
.filter((c) => c.slug === post.category)
|
|
.pop() as CollectionEntry<'categories'>;
|
|
const readingTime = getReadingTime(post.content);
|
|
---
|
|
|
|
<BaseLayout
|
|
title={post.title}
|
|
description={post.description}
|
|
ogImage={getDirectusImageURL(post.image)}
|
|
structuredData={{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'NewsArticle',
|
|
inLanguage: 'en-US',
|
|
'@id': Astro.url.href,
|
|
url: Astro.url.href,
|
|
description: post.description,
|
|
isPartOf: {
|
|
'@type': 'WebSite',
|
|
url: `${global.site_url}/blog`,
|
|
name: global.name,
|
|
description: global.about,
|
|
},
|
|
image: [
|
|
// post.data.banner,
|
|
],
|
|
headline: post.title,
|
|
datePublished: post.published_date,
|
|
dateModified: post.updated_date,
|
|
author: [
|
|
{
|
|
'@type': 'Person',
|
|
name: `${global.name}`,
|
|
url: `${global.site_url}`,
|
|
},
|
|
],
|
|
}}
|
|
>
|
|
<section class="mx-auto max-w-6xl px-4 pt-8 pb-12 sm:px-6 lg:px-8 lg:pt-12">
|
|
<div class="smooth-reveal relative w-full">
|
|
<div class="mt-4 rounded-2xl shadow-none sm:mt-0 sm:shadow-sm">
|
|
<Image
|
|
class="max-h-[600px] w-full rounded-t-2xl object-cover"
|
|
src={getDirectusImageURL(post.image)}
|
|
alt={post.image_alt}
|
|
draggable="false"
|
|
format="webp"
|
|
loading="lazy"
|
|
inferSize={true}
|
|
/>
|
|
<div
|
|
class="rounded-b-2xl px-0 py-6 sm:bg-neutral-100 sm:px-6 md:px-10 lg:px-14 sm:dark:bg-neutral-900/30"
|
|
>
|
|
<div class="mb-16">
|
|
<h2
|
|
class="mb-6 block text-3xl font-bold tracking-tight text-balance text-neutral-800 md:text-4xl lg:text-5xl dark:text-neutral-300"
|
|
>
|
|
{post.title}
|
|
</h2>
|
|
<ol class="mt-8 flex items-center whitespace-nowrap">
|
|
<li class="inline-flex items-center">
|
|
<a
|
|
class="flex items-center text-sm text-neutral-500 transition-all duration-300 hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
|
|
href=`/categories/${category.slug}`
|
|
>
|
|
{category?.data?.title}
|
|
</a>
|
|
<svg
|
|
class="mx-2 size-5 flex-shrink-0 text-neutral-500 dark:text-neutral-500"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 16 16"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
aria-hidden="true"
|
|
>
|
|
<path d="M6 13L10 3" stroke="currentColor" stroke-linecap="round"></path>
|
|
</svg>
|
|
</li>
|
|
<li
|
|
class="inline-flex items-center text-sm text-neutral-500 transition-all duration-300 hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
|
|
>
|
|
{formatDateTime(post.published_date)}
|
|
<svg
|
|
class="mx-2 size-5 flex-shrink-0 text-neutral-500 dark:text-neutral-500"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 16 16"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
aria-hidden="true"
|
|
>
|
|
<path d="M6 13L10 3" stroke="currentColor" stroke-linecap="round"></path>
|
|
</svg>
|
|
</li>
|
|
<li
|
|
class="inline-flex items-center text-sm text-neutral-500 transition-all duration-300 hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
|
|
aria-current="page"
|
|
>
|
|
{readingTime.minutes.toPrecision(1)} minutes to read
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
|
|
<article
|
|
class="prose prose-blog sm:prose-lg dark:prose-invert max-w-none text-justify text-neutral-800 dark:text-neutral-200"
|
|
>
|
|
<div set:html={post.content} />
|
|
</article>
|
|
|
|
<div
|
|
class="mx-auto mt-10 grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0 md:mt-14"
|
|
>
|
|
<div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0">
|
|
{
|
|
post.tags.map((tag: string) => (
|
|
<span class="bg-steel/30 dark:bg-bermuda/60 inline-flex items-center gap-x-1.5 rounded-lg px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:ring focus-visible:outline-none dark:text-neutral-200">
|
|
{tag}
|
|
</span>
|
|
))
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<style is:inline>
|
|
code[data-theme*=' '],
|
|
code[data-theme*=' '] span {
|
|
color: var(--shiki-light);
|
|
}
|
|
|
|
html.dark {
|
|
code[data-theme*=' '],
|
|
code[data-theme*=' '] span {
|
|
color: var(--shiki-dark);
|
|
}
|
|
}
|
|
</style>
|
|
</BaseLayout>
|
|
|
|
<script>
|
|
// Add smooth reveal animations for content after loading
|
|
document.addEventListener('astro:page-load', () => {
|
|
const animateContent = () => {
|
|
const smoothReveal = document.querySelectorAll('.smooth-reveal');
|
|
smoothReveal.forEach((el, index) => {
|
|
setTimeout(
|
|
() => {
|
|
el.classList.add('animate-reveal');
|
|
},
|
|
100 + index * 100
|
|
);
|
|
});
|
|
};
|
|
|
|
animateContent();
|
|
});
|
|
</script>
|