use collections and provide rss feed for the blog

This commit is contained in:
2024-07-22 19:37:18 +02:00
parent 0bca511144
commit 3cc883d082
13 changed files with 1876 additions and 1486 deletions
+1779 -1442
View File
File diff suppressed because it is too large Load Diff
+9 -4
View File
@@ -9,12 +9,17 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^2.0.0", "@astrojs/mdx": "^2.3.1",
"@astrojs/svelte": "^5.0.0", "@astrojs/rss": "^4.0.7",
"astro": "^4.0.1", "@astrojs/svelte": "^5.7.0",
"astro": "^4.12.2",
"markdown-it": "^14.1.0",
"marked": "^13.0.2",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
"rehype-external-links": "^3.0.0", "rehype-external-links": "^3.0.0",
"remark-gfm": "^4.0.0", "remark-gfm": "^4.0.0",
"remark-smartypants": "^2.0.0" "remark-smartypants": "^2.1.0",
"sanitize-html": "^2.13.0",
"zod": "^3.23.8"
} }
} }
View File
+6
View File
@@ -17,6 +17,12 @@ const socialUrl = Astro.site.href + 'assets/yht_logo.png'
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link
rel="alternate"
type="application/rss+xml"
title="YouHaveBlog RSS Feed"
href={new URL("rss.xml", Astro.site)}
/>
<!-- Primary Meta Tags --> <!-- Primary Meta Tags -->
<title> {title} | YouHaveTrouble's place</title> <title> {title} | YouHaveTrouble's place</title>
+1 -1
View File
@@ -9,5 +9,5 @@
</style> </style>
<a href="/"> <a href="/">
<img alt="Blog Logo" src="/assets/yht_logo.png" width="50px" height="50px" /> <img alt="Logo displaying a stylized character with brown hair wearing purple hoodie on a light blue circle background" src="/assets/yht_logo.png" width="50px" height="50px" />
</a> </a>
+14
View File
@@ -0,0 +1,14 @@
import { z, defineCollection } from 'astro:content';
const posts = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
publishDate: z.string(),
tags: z.array(z.string()),
image: z.string().optional(),
}),
});
export const collections = {
posts,
};
+1
View File
@@ -1 +1,2 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" /> /// <reference types="astro/client" />
+24 -18
View File
@@ -1,24 +1,32 @@
--- ---
import {getCollection} from "astro:content";
import BaseLayout from '../../layouts/BaseLayout.astro'; import BaseLayout from '../../layouts/BaseLayout.astro';
import Bio from '../../components/Bio.astro'; import Bio from '../../components/Bio.astro';
import getPostData from '../../utils/getPostData'; import readingTime from 'reading-time';
import { marked } from 'marked';
export async function getStaticPaths() { export async function getStaticPaths() {
let posts = [];
try { const posts = await getCollection('posts');
posts = await Astro.glob('../../data/blog-posts/*.md');
} catch (error) {
console.error("No blog posts found");
}
return posts.map(p => ({ return posts.map(p => ({
params: { slug: p.file.split('/').pop().split('.').shift() }, params: {
props: { post: p }, slug: p.slug
},
props: {
title: p.data.title,
publishDate: p.data.publishDate,
slug: p.slug,
tags: "test",
content: marked.parse(p.body),
readingTime: readingTime(p.body).text,
}
})); }));
} }
const { Content, frontmatter } = Astro.props.post; const { slug, title, description, publishDate, tags, content, readingTime } = Astro.props;
const { title, description, publishDate, tags } = frontmatter; const props = Astro.props;
const { slug, readingTime } = getPostData(Astro.props.post);
const permalink = `${Astro.site.href}blog/${slug}`; const permalink = `${Astro.site.href}blog/${slug}`;
--- ---
@@ -27,16 +35,14 @@ const permalink = `${Astro.site.href}blog/${slug}`;
<p>{publishDate} ~ {readingTime}</p> <p>{publishDate} ~ {readingTime}</p>
<h1>{title}</h1> <h1>{title}</h1>
<div class="tags" style="justify-content: center"> <div class="tags" style="justify-content: center">
{tags.map(item => ( <!--{tags.map(item => (-->
<span class="tag">{item}</span> <!-- <span class="tag">{item}</span>-->
))} <!--))}-->
</div> </div>
<hr /> <hr />
</header> </header>
<div class="container"> <div class="container">
<article class="content"> <article class="content" set:html={content}></article>
<Content />
</article>
<hr /> <hr />
<Bio /> <Bio />
</div> </div>
+2 -2
View File
@@ -2,11 +2,11 @@
import BaseLayout from '../../layouts/BaseLayout.astro'; import BaseLayout from '../../layouts/BaseLayout.astro';
const title = 'Blog'; const title = 'Blog';
const description = 'Latest articles.'; const description = 'Something that\'s supposed to be thoughts';
const permalink = `${Astro.site.href}blog`; const permalink = `${Astro.site.href}blog`;
let allPosts = []; let allPosts = [];
try { try {
allPosts = await Astro.glob('../../data/blog-posts/*.md'); allPosts = await Astro.glob('../../content/posts/*.md');
} catch (error) { } catch (error) {
console.error('No blog posts found'); console.error('No blog posts found');
} }
+22
View File
@@ -0,0 +1,22 @@
import rss from '@astrojs/rss';
import sanitizeHtml from 'sanitize-html';
import { marked } from 'marked';
import {getCollection} from "astro:content";
export async function GET(context: { site: any; }) {
const posts = await getCollection('posts');
return rss({
title: 'YouHaveBlog',
description: 'Something that\'s supposed to be thoughts.',
site: context.site,
items: posts.map((post) => ({
link: `/blog/${post.slug}/`,
content: sanitizeHtml(marked.parse(post.body), {
allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img'])
}),
pubDate: new Date(post.data.publishDate),
...post.data,
})),
});
}
+11
View File
@@ -7,6 +7,11 @@
--font-family-sans: 'Fira Sans', sans-serif; --font-family-sans: 'Fira Sans', sans-serif;
} }
/* break comment when time is right */
/*@view-transition {*/
/* navigation: auto;*/
/*}*/
:root.theme-dark { :root.theme-dark {
--background-body: #202122; --background-body: #202122;
--text-main: #fff; --text-main: #fff;
@@ -278,6 +283,12 @@ span.tag::before {
content: '#'; content: '#';
} }
iframe {
width: 100%;
aspect-ratio: 16/9;
border: 0;
}
@media (max-width: 1020px) { @media (max-width: 1020px) {
h1 { h1 {
font-size: 3em; font-size: 3em;
-14
View File
@@ -1,14 +0,0 @@
import readingTime from 'reading-time'
type Post = {
title: string
file: string
rawContent: () => string
}
export default function getPostData(post: Post) {
return {
slug: post.file.split('/').pop().split('.').shift(),
readingTime: readingTime(post.rawContent()).text,
}
}
+3 -1
View File
@@ -1,4 +1,5 @@
{ {
"extends": "astro/tsconfigs/base",
"compilerOptions": { "compilerOptions": {
// Enable top-level await, and other modern ESM features. // Enable top-level await, and other modern ESM features.
"target": "ESNext", "target": "ESNext",
@@ -10,6 +11,7 @@
// Enable stricter transpilation for better output. // Enable stricter transpilation for better output.
"isolatedModules": true, "isolatedModules": true,
// Astro will directly run your TypeScript code, no transpilation needed. // Astro will directly run your TypeScript code, no transpilation needed.
"noEmit": true "noEmit": true,
"strictNullChecks": true
} }
} }