mirror of
				https://github.com/valentineus/popov.link.git
				synced 2025-11-03 22:39:44 +03:00 
			
		
		
		
	@@ -51,4 +51,4 @@ Comments on the site are powered by [giscus.app](https://giscus.app) and stored
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
This project is licensed under the [MIT License](LICENSE.txt).
 | 
			
		||||
This project is licensed under the [MIT License](LICENSE.txt).
 | 
			
		||||
 
 | 
			
		||||
@@ -15,10 +15,4 @@ export default defineConfig({
 | 
			
		||||
			theme: "vitesse-dark",
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	redirects: {
 | 
			
		||||
		"/blog": {
 | 
			
		||||
			destination: "/",
 | 
			
		||||
			status: 301,
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								src/components/Header.astro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/components/Header.astro
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	@import "../scss/_variables.scss";
 | 
			
		||||
 | 
			
		||||
	header {
 | 
			
		||||
		padding-bottom: 1rem;
 | 
			
		||||
		text-align: right;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a {
 | 
			
		||||
		text-decoration: none;
 | 
			
		||||
		margin-right: 1.5rem;
 | 
			
		||||
 | 
			
		||||
		&:last-child {
 | 
			
		||||
			margin-right: 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<header>
 | 
			
		||||
	<a href="/">Home</a>
 | 
			
		||||
	<a href="/blog/">Blog</a>
 | 
			
		||||
</header>
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
type Props = {
 | 
			
		||||
	readonly nextUrl?: string;
 | 
			
		||||
	readonly prevUrl?: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const { nextUrl, prevUrl } = Astro.props;
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		text-align: center;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	span {
 | 
			
		||||
		margin: 0 2em;
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<div>
 | 
			
		||||
	{
 | 
			
		||||
		prevUrl && (
 | 
			
		||||
			<span>
 | 
			
		||||
				<a href={prevUrl}>< Prev</a>
 | 
			
		||||
			</span>
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		nextUrl && (
 | 
			
		||||
			<span>
 | 
			
		||||
				<a href={nextUrl}>Next ></a>
 | 
			
		||||
			</span>
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										32
									
								
								src/components/PostElement.astro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/components/PostElement.astro
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
---
 | 
			
		||||
import { type CollectionEntry } from "astro:content";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
	readonly post: CollectionEntry<"blog">;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const { post } = Astro.props;
 | 
			
		||||
const { remarkPluginFrontmatter } = await post.render();
 | 
			
		||||
const formattedDate = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY");
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	@import "../scss/_variables.scss";
 | 
			
		||||
 | 
			
		||||
	small {
 | 
			
		||||
		font-size: $fontSizeBase * 0.75;
 | 
			
		||||
		opacity: 0.5;
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<li>
 | 
			
		||||
	<a href={`/blog/${post.slug}`}>{post.data.title}</a>
 | 
			
		||||
	<div>
 | 
			
		||||
		<small>
 | 
			
		||||
			<time datetime={post.data.pubDate.toISOString()}>{formattedDate}</time>
 | 
			
		||||
			<span>•</span>
 | 
			
		||||
			<span>{remarkPluginFrontmatter.minutesRead}</span>
 | 
			
		||||
		</small>
 | 
			
		||||
	</div>
 | 
			
		||||
</li>
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
---
 | 
			
		||||
import Analytics from "../components/Analytics.astro";
 | 
			
		||||
import Head from "../components/Head.astro";
 | 
			
		||||
import Header from "../components/Header.astro";
 | 
			
		||||
import "../scss/global.scss";
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
@@ -19,6 +20,10 @@ const { description, title } = Astro.props;
 | 
			
		||||
 | 
			
		||||
	<body>
 | 
			
		||||
		<main>
 | 
			
		||||
			<section>
 | 
			
		||||
				<Header />
 | 
			
		||||
			</section>
 | 
			
		||||
 | 
			
		||||
			<slot />
 | 
			
		||||
		</main>
 | 
			
		||||
		<Analytics title={title ?? import.meta.env.DEFAULT_TITLE} />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
import type { GetStaticPaths, InferGetStaticPropsType } from "astro";
 | 
			
		||||
import { getCollection } from "astro:content";
 | 
			
		||||
import Layout from "../layouts/BaseLayout.astro";
 | 
			
		||||
import Pagination from "../components/Pagination.astro";
 | 
			
		||||
import PostSummary from "../components/PostSummary.astro";
 | 
			
		||||
 | 
			
		||||
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
 | 
			
		||||
 | 
			
		||||
export const getStaticPaths = (async ({ paginate }) => {
 | 
			
		||||
	const posts = await getCollection("blog", ({ data }) => {
 | 
			
		||||
		return data.draft !== true;
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	posts.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
 | 
			
		||||
 | 
			
		||||
	return paginate(posts, {
 | 
			
		||||
		pageSize: 10,
 | 
			
		||||
	});
 | 
			
		||||
}) satisfies GetStaticPaths;
 | 
			
		||||
 | 
			
		||||
const { page } = Astro.props;
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<Layout>
 | 
			
		||||
	<section style={{ "margin-top": "3rem" }}>
 | 
			
		||||
		{page.data.map((post) => <PostSummary post={post} />)}
 | 
			
		||||
	</section>
 | 
			
		||||
 | 
			
		||||
	<section>
 | 
			
		||||
		<Pagination nextUrl={page.url.next} prevUrl={page.url.prev} />
 | 
			
		||||
	</section>
 | 
			
		||||
</Layout>
 | 
			
		||||
@@ -32,11 +32,13 @@ const formattedDate = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY"
 | 
			
		||||
 | 
			
		||||
<Layout description={post.data.description} title={post.data.title}>
 | 
			
		||||
	<article>
 | 
			
		||||
		<section>
 | 
			
		||||
			<h1>{post.data.title}</h1>
 | 
			
		||||
		</section>
 | 
			
		||||
 | 
			
		||||
		<section>
 | 
			
		||||
			<p>
 | 
			
		||||
				<small>
 | 
			
		||||
					<a href="/">< Home</a>
 | 
			
		||||
					<span> • </span>
 | 
			
		||||
					Posted
 | 
			
		||||
					<time datetime={post.data.pubDate.toISOString()}>{formattedDate}</time>
 | 
			
		||||
					by {post.data.author}
 | 
			
		||||
@@ -46,10 +48,6 @@ const formattedDate = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY"
 | 
			
		||||
			</p>
 | 
			
		||||
		</section>
 | 
			
		||||
 | 
			
		||||
		<section>
 | 
			
		||||
			<h1>{post.data.title}</h1>
 | 
			
		||||
		</section>
 | 
			
		||||
 | 
			
		||||
		<section>
 | 
			
		||||
			<Content />
 | 
			
		||||
		</section>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								src/pages/blog/index.astro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/pages/blog/index.astro
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
---
 | 
			
		||||
import { getCollection } from "astro:content";
 | 
			
		||||
import Layout from "../../layouts/BaseLayout.astro";
 | 
			
		||||
import PostElement from "../../components/PostElement.astro";
 | 
			
		||||
 | 
			
		||||
const posts = await getCollection("blog", ({ data }) => {
 | 
			
		||||
	return data.draft !== true;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
posts.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<Layout>
 | 
			
		||||
	<section style={{ "margin-top": "3rem" }}>
 | 
			
		||||
		<ul>
 | 
			
		||||
			{posts.map((post) => <PostElement post={post} />)}
 | 
			
		||||
		</ul>
 | 
			
		||||
	</section>
 | 
			
		||||
</Layout>
 | 
			
		||||
							
								
								
									
										17
									
								
								src/pages/index.astro
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/pages/index.astro
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
---
 | 
			
		||||
import { getCollection } from "astro:content";
 | 
			
		||||
import Layout from "../layouts/BaseLayout.astro";
 | 
			
		||||
import PostSummary from "../components/PostSummary.astro";
 | 
			
		||||
 | 
			
		||||
const posts = await getCollection("blog", ({ data }) => {
 | 
			
		||||
	return data.draft !== true;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
posts.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<Layout>
 | 
			
		||||
	<section style={{ "margin-top": "3rem" }}>
 | 
			
		||||
		{posts.map((post) => <PostSummary post={post} />)}
 | 
			
		||||
	</section>
 | 
			
		||||
</Layout>
 | 
			
		||||
		Reference in New Issue
	
	Block a user