mirror of
https://github.com/thiloho/thiloho.github.io.git
synced 2025-11-22 10:21:36 +01:00
Add RSS feed, add links for direct md editing on GitHub and update favicon
This commit is contained in:
@@ -6,7 +6,7 @@ interface Props {
|
||||
const { date } = Astro.props;
|
||||
---
|
||||
|
||||
<time datetime={date.toISOString()}>
|
||||
<time datetime={date.toISOString()} class="underline decoration-dotted">
|
||||
{
|
||||
date.toLocaleString("en-us", {
|
||||
year: "numeric",
|
||||
|
||||
@@ -4,10 +4,10 @@ import "../styles/global.css";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
metaDescription: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
const { title, metaDescription } = Astro.props;
|
||||
const { title, description } = Astro.props;
|
||||
---
|
||||
|
||||
<head>
|
||||
@@ -21,7 +21,14 @@ const { title, metaDescription } = Astro.props;
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={metaDescription} />
|
||||
<meta name="description" content={description} />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/rss+xml"
|
||||
title="Your Site's Title"
|
||||
href={new URL("rss.xml", Astro.site)}
|
||||
/>
|
||||
<ClientRouter />
|
||||
<script is:inline>
|
||||
const setTheme = () => {
|
||||
|
||||
@@ -5,9 +5,10 @@ interface Props {
|
||||
title: string;
|
||||
pubDate?: Date;
|
||||
modDate?: Date;
|
||||
slug?: string;
|
||||
}
|
||||
|
||||
const { title, pubDate, modDate } = Astro.props;
|
||||
const { title, pubDate, modDate, slug } = Astro.props;
|
||||
---
|
||||
|
||||
<header class="bg-white dark:bg-neutral-800">
|
||||
@@ -24,6 +25,21 @@ const { title, pubDate, modDate } = Astro.props;
|
||||
Last modified:{" "}
|
||||
{modDate ? <Date date={modDate} /> : <span>No modifications</span>}
|
||||
</p>
|
||||
<a
|
||||
href={`https://github.com/thiloho/thiloho.github.io/edit/main/src/content/blog/${slug}/index.md`}
|
||||
class="text-blue-800 dark:text-blue-300 inline-flex items-center gap-1 hover:no-underline"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="size-5"
|
||||
>
|
||||
<path d="m5.433 13.917 1.262-3.155A4 4 0 0 1 7.58 9.42l6.92-6.918a2.121 2.121 0 0 1 3 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 0 1-.65-.65Z" />
|
||||
<path d="M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0 0 10 3H4.75A2.75 2.75 0 0 0 2 5.75v9.5A2.75 2.75 0 0 0 4.75 18h9.5A2.75 2.75 0 0 0 17 15.25V10a.75.75 0 0 0-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5Z" />
|
||||
</svg>
|
||||
Edit this page
|
||||
</a>
|
||||
</hgroup>
|
||||
) : (
|
||||
<h1>{title}</h1>
|
||||
|
||||
@@ -6,7 +6,7 @@ const routes = ["blog"];
|
||||
|
||||
<nav class="max-w-none bg-neutral-100 dark:bg-neutral-900 sticky top-0 z-10">
|
||||
<div
|
||||
class="dark:text-neutral-300 flex items-center justify-between max-w-screen-lg mx-auto ps-4 pe-2"
|
||||
class="text-neutral-700 dark:text-neutral-300 flex items-center justify-between max-w-screen-lg mx-auto ps-4 pe-2"
|
||||
>
|
||||
<a href="/" title="Home">
|
||||
<Logo width={42} height={42} />
|
||||
@@ -54,6 +54,26 @@ const routes = ["blog"];
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<a
|
||||
class="inline-grid place-content-center p-2 cursor-pointer border-b-2 border-transparent hover:bg-neutral-200 hover:border-neutral-400 hover:dark:bg-neutral-700 hover:dark:border-neutral-600"
|
||||
title="RSS feed"
|
||||
href="/rss.xml"
|
||||
>
|
||||
<!-- RSS -->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="size-5"
|
||||
>
|
||||
<path
|
||||
d="M3.75 3a.75.75 0 0 0-.75.75v.5c0 .414.336.75.75.75H4c6.075 0 11 4.925 11 11v.25c0 .414.336.75.75.75h.5a.75.75 0 0 0 .75-.75V16C17 8.82 11.18 3 4 3h-.25Z"
|
||||
></path>
|
||||
<path
|
||||
d="M3 8.75A.75.75 0 0 1 3.75 8H4a8 8 0 0 1 8 8v.25a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1-.75-.75V16a6 6 0 0 0-6-6h-.25A.75.75 0 0 1 3 9.25v-.5ZM7 15a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -8,7 +8,6 @@ const index = defineCollection({
|
||||
const blog = defineCollection({
|
||||
loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
|
||||
schema: z.object({
|
||||
id: z.number().positive(),
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
pubDate: z.coerce.date(),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
id: 1
|
||||
title: "Steps to install NixOS on a system with ext4 and LUKS"
|
||||
description: "A guide to installing NixOS with full disk encryption using LUKS and LVM, showing the complete process from disk partitioning to system configuration"
|
||||
pubDate: "2025-01-04"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
id: 2
|
||||
title: "Privacy-focused operating systems"
|
||||
description: "Good choices for privacy-focused operating systems for desktop and mobile phones."
|
||||
pubDate: "2025-01-16"
|
||||
@@ -6,19 +6,20 @@ import Footer from "../components/Footer.astro";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
metaDescription: string;
|
||||
description: string;
|
||||
pubDate?: Date;
|
||||
modDate?: Date;
|
||||
slug?: string;
|
||||
}
|
||||
|
||||
const { title, metaDescription, pubDate, modDate } = Astro.props;
|
||||
const { title, description, pubDate, modDate, slug } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en" class="light">
|
||||
<Head {title} {metaDescription} />
|
||||
<Head {title} {description} />
|
||||
<body class="min-h-screen flex flex-col">
|
||||
<Nav />
|
||||
<Header {title} {pubDate} {modDate} />
|
||||
<Header {title} {pubDate} {modDate} {slug} />
|
||||
<main class="flex-1 bg-white dark:bg-neutral-800">
|
||||
<div
|
||||
class={`relative prose prose-neutral dark:prose-invert mx-auto px-4 ${pubDate ? "pt-0" : "pt-8"} pb-16 prose-headings:scroll-mt-16 prose-h1:font-bold prose-pre:!bg-neutral-700 prose-a:text-blue-800 prose-a:dark:text-blue-300 prose-a:hover:no-underline`}
|
||||
|
||||
@@ -22,9 +22,10 @@ const { Content, headings } = await render(article);
|
||||
|
||||
<PageLayout
|
||||
title={article.data.title}
|
||||
metaDescription="Blog"
|
||||
description="Blog"
|
||||
pubDate={article.data.pubDate}
|
||||
modDate={article.data.modDate}
|
||||
{slug}
|
||||
>
|
||||
<details class="toc sticky top-0 z-20">
|
||||
<summary
|
||||
|
||||
@@ -9,11 +9,11 @@ const sortedArticles = allArticles.sort((a, b) => {
|
||||
});
|
||||
---
|
||||
|
||||
<PageLayout title="Blog" metaDescription="Blog">
|
||||
<PageLayout title="Blog" description="Blog">
|
||||
<ul>
|
||||
{
|
||||
sortedArticles.map((article) => (
|
||||
<li class="gap-1">
|
||||
<li class="flex gap-2">
|
||||
<Date date={article.data.pubDate} />
|
||||
<span>»</span>
|
||||
<a
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
import PageLayout from "../layouts/PageLayout.astro";
|
||||
---
|
||||
|
||||
<PageLayout title="Contact" metaDescription="Contact">
|
||||
<PageLayout title="Contact" description="Contact">
|
||||
<p>Example content</p>
|
||||
</PageLayout>
|
||||
|
||||
@@ -11,6 +11,6 @@ if (!indexContent) {
|
||||
const { Content } = await render(indexContent);
|
||||
---
|
||||
|
||||
<PageLayout title="Thilo Hohlt" metaDescription="Thilo Hohlt">
|
||||
<PageLayout title="Thilo Hohlt" description="Thilo Hohlt">
|
||||
<Content />
|
||||
</PageLayout>
|
||||
|
||||
@@ -11,6 +11,6 @@ if (!legalContent) {
|
||||
const { Content } = await render(legalContent);
|
||||
---
|
||||
|
||||
<PageLayout title="Legal Disclosure" metaDescription="Legal Disclosure">
|
||||
<PageLayout title="Legal Disclosure" description="Legal Disclosure">
|
||||
<Content />
|
||||
</PageLayout>
|
||||
|
||||
23
src/pages/rss.xml.js
Normal file
23
src/pages/rss.xml.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import rss from "@astrojs/rss";
|
||||
import { getCollection } from "astro:content";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
import MarkdownIt from "markdown-it";
|
||||
const parser = new MarkdownIt();
|
||||
|
||||
export const GET = async (context) => {
|
||||
const blog = await getCollection("blog");
|
||||
return rss({
|
||||
title: "Thilo Hohlt’s Blog",
|
||||
description: "Thilo Hohlt’s Blog",
|
||||
site: context.site,
|
||||
trailingSlash: false,
|
||||
stylesheet: "pretty-feed-v3.xsl",
|
||||
items: blog.map((article) => ({
|
||||
link: `/blog/${article.id}/`,
|
||||
content: sanitizeHtml(parser.render(article.body), {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
|
||||
}),
|
||||
...article.data,
|
||||
})),
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user