Skip to content

Commit

Permalink
feat: add blog module
Browse files Browse the repository at this point in the history
  • Loading branch information
ourai committed Dec 17, 2024
1 parent 2207180 commit 445b973
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const projects = defineCollection({
}),
});

const blog = defineCollection({
const posts = defineCollection({
type: 'content',
// Type-check frontmatter using a schema
schema: z.object({
Expand All @@ -72,6 +72,6 @@ export const collections = {
contributors,
tagTypes, tags,
projects,
blog,
posts,
docs,
};
3 changes: 2 additions & 1 deletion src/entry/layouts/default/NavMenu.astro
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ const i18n = I18N_CONFIG[locale];
const getLocaleUrl = getRelativeLocaleUrl.bind(null, locale);
const navs: SiteNav[] = [
{ key: 'guides', path: '/guides' },
{ key: 'projects', path: '/projects' },
{ key: 'guides', path: '/guides' },
{ key: 'posts', path: '/posts' },
];
---

Expand Down
100 changes: 100 additions & 0 deletions src/entry/layouts/post/IndexLayout.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
import type { SupportedLocale } from '@/types';
import DefaultLayout from '../default';
import { resolvePosts } from './helper';
import FormattedDate from './FormattedDate.astro';
const locale = (Astro.currentLocale || 'en') as SupportedLocale;
const posts = (await resolvePosts(locale)).sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
---

<DefaultLayout>
<style slot="custom-style">
main {
width: 960px;
}
ul {
display: flex;
flex-wrap: wrap;
gap: 2rem;
list-style-type: none;
margin: 0;
padding: 0;
}
ul li {
width: calc(50% - 1rem);
}
ul li * {
text-decoration: none;
transition: 0.2s ease;
}
ul li:first-child {
width: 100%;
margin-bottom: 1rem;
text-align: center;
}
ul li:first-child img {
width: 100%;
}
ul li:first-child .title {
font-size: 2.369rem;
}
ul li img {
margin-bottom: 0.5rem;
border-radius: 12px;
}
ul li a {
display: block;
}
.title {
margin: 0;
color: rgb(var(--black));
line-height: 1;
}
.date {
margin: 0;
color: rgb(var(--gray));
}
ul li a:hover h4,
ul li a:hover .date {
color: rgb(var(--accent));
}
ul a:hover img {
box-shadow: var(--box-shadow);
}
@media (max-width: 720px) {
ul {
gap: 0.5em;
}
ul li {
width: 100%;
text-align: center;
}
ul li:first-child {
margin-bottom: 0;
}
ul li:first-child .title {
font-size: 1.563em;
}
}
</style>
<section>
<ul>
{
posts.map((post) => (
<li>
<a href={`${locale !== 'en' ? '/' + locale : ''}/posts/${post.slug}/`}>
<img width={720} height={360} src={post.data.heroImage} alt="" />
<h4 class="title">{post.data.title}</h4>
<p class="date">
<FormattedDate date={post.data.pubDate} />
</p>
</a>
</li>
))
}
</ul>
</section>
</DefaultLayout>
2 changes: 1 addition & 1 deletion src/entry/layouts/post/PostLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { CollectionEntry } from 'astro:content';
import DefaultLayout from '../default';
import FormattedDate from './FormattedDate.astro';
type Props = CollectionEntry<'blog'>['data'];
type Props = CollectionEntry<'posts'>['data'];
const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
---
Expand Down
23 changes: 23 additions & 0 deletions src/entry/layouts/post/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { getCollection } from 'astro:content';

import type { SupportedLocale } from '@/types';

async function resolvePosts(locale: SupportedLocale) {
return (await getCollection('posts'))
.filter(post => {
const parts = post.slug.split('/');

return locale === 'en' ? parts.length === 1 : parts.length === 2 && parts[0] === locale;
})
.map(({ slug, ...others }) => {
const parts = slug.split('/');

if (parts.length > 1) {
parts.shift();
}

return { ...others, slug: parts.join('/') };
});
}

export { resolvePosts };
2 changes: 2 additions & 0 deletions src/entry/layouts/post/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { resolvePosts } from './helper';
export { default } from './PostLayout.astro';
export { default as IndexLayout } from './IndexLayout.astro';
20 changes: 20 additions & 0 deletions src/pages/posts/[...slug].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
import { type CollectionEntry, render } from 'astro:content';
import PostLayout, { resolvePosts } from '#/layouts/post';
export async function getStaticPaths() {
return (await resolvePosts('en')).map(post => ({
params: { slug: post.slug },
props: post,
}));
}
type Props = CollectionEntry<'posts'>;
const post = Astro.props;
const { Content } = await render(post);
---

<PostLayout {...post.data}>
<Content />
</PostLayout>
5 changes: 5 additions & 0 deletions src/pages/posts/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
import { IndexLayout } from '#/layouts/post';
---

<IndexLayout />
4 changes: 2 additions & 2 deletions src/pages/rss.xml.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { getCollection } from 'astro:content';
import { SITE_TITLE, SITE_DESCRIPTION } from '@/constants/config';

export async function GET(context) {
const posts = await getCollection('blog');
const posts = await getCollection('posts');
return rss({
title: SITE_TITLE,
description: SITE_DESCRIPTION,
site: context.site,
items: posts.map((post) => ({
...post.data,
link: `/blog/${post.slug}/`,
link: `/posts/${post.slug}/`,
})),
});
}
20 changes: 20 additions & 0 deletions src/pages/zh/posts/[...slug].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
import { type CollectionEntry, render } from 'astro:content';
import PostLayout, { resolvePosts } from '#/layouts/post';
export async function getStaticPaths() {
return (await resolvePosts('zh')).map(post => ({
params: { slug: post.slug },
props: post,
}));
}
type Props = CollectionEntry<'posts'>;
const post = Astro.props;
const { Content } = await render(post);
---

<PostLayout {...post.data}>
<Content />
</PostLayout>
5 changes: 5 additions & 0 deletions src/pages/zh/posts/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
import { IndexLayout } from '#/layouts/post';
---

<IndexLayout />
2 changes: 2 additions & 0 deletions src/shared/constants/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const I18N_CONFIG: LocaleValue<LocaleConfig> = {
navs: {
projects: 'Projects',
guides: 'Guides',
posts: 'Posts',
},
},
zh: {
Expand All @@ -25,6 +26,7 @@ const I18N_CONFIG: LocaleValue<LocaleConfig> = {
navs: {
projects: '项目',
guides: '指南',
posts: '博客',
},
},
};
Expand Down
1 change: 1 addition & 0 deletions src/shared/types/locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type SiteConfig = {
type NavConfig = {
projects: string;
guides: string;
posts: string;
};

type LocaleConfig = {
Expand Down

0 comments on commit 445b973

Please sign in to comment.