mirror of
https://github.com/ChenQihan666/MyBlog-Next.git
synced 2026-08-14 07:33:07 +08:00
feat: add archives page with configurable menu (#386)
* feat: add archives page with configurable menu * optimize: compat mobile layout * fix: update archive menu layout * fix: hide archives page from URL if showArchives is false * docs: add `showArchives` option in docs Resolves #361 --------- Co-authored-by: satnaing <satnaingdev@gmail.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import Hr from "./Hr.astro";
|
||||
import LinkButton from "./LinkButton.astro";
|
||||
|
||||
export interface Props {
|
||||
activeNav?: "posts" | "tags" | "about" | "search";
|
||||
activeNav?: "posts" | "archives" | "tags" | "about" | "search";
|
||||
}
|
||||
|
||||
const { activeNav } = Astro.props;
|
||||
@@ -70,6 +70,41 @@ const { activeNav } = Astro.props;
|
||||
About
|
||||
</a>
|
||||
</li>
|
||||
{
|
||||
SITE.showArchives && (
|
||||
<li>
|
||||
<LinkButton
|
||||
href="/archives/"
|
||||
className={`focus-outline flex justify-center p-3 sm:p-1`}
|
||||
ariaLabel="archives"
|
||||
title="Archives"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class:list={[
|
||||
"icon icon-tabler icons-tabler-outline !hidden sm:!inline-block",
|
||||
activeNav === "archives" && "!stroke-skin-accent",
|
||||
]}
|
||||
>
|
||||
<>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M3 4m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z" />
|
||||
<path d="M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10" />
|
||||
<path d="M10 12l4 0" />
|
||||
</>
|
||||
</svg>
|
||||
<span
|
||||
class:list={[
|
||||
"sm:sr-only",
|
||||
activeNav === "archives" && "active",
|
||||
]}
|
||||
>
|
||||
Archives
|
||||
</span>
|
||||
</LinkButton>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
<li>
|
||||
<LinkButton
|
||||
href="/search/"
|
||||
@@ -155,7 +190,7 @@ const { activeNav } = Astro.props;
|
||||
nav ul li:nth-last-child(2) {
|
||||
@apply col-span-1;
|
||||
}
|
||||
nav a.active {
|
||||
nav .active {
|
||||
@apply underline decoration-wavy decoration-2 underline-offset-4;
|
||||
}
|
||||
nav a.active svg {
|
||||
|
||||
@@ -11,6 +11,7 @@ export const SITE: Site = {
|
||||
postPerIndex: 4,
|
||||
postPerPage: 3,
|
||||
scheduledPostMargin: 15 * 60 * 1000, // 15 minutes
|
||||
showArchives: true,
|
||||
editPost: {
|
||||
url: "https://github.com/satnaing/astro-paper/edit/main/src/content/blog",
|
||||
text: "Suggest Changes",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
author: Sat Naing
|
||||
pubDatetime: 2022-09-23T04:58:53Z
|
||||
modDatetime: 2024-01-15T13:05:56.066Z
|
||||
modDatetime: 2024-10-14T09:27:28.605Z
|
||||
title: How to configure AstroPaper theme
|
||||
slug: how-to-configure-astropaper-theme
|
||||
featured: true
|
||||
@@ -33,6 +33,7 @@ export const SITE = {
|
||||
lightAndDarkMode: true,
|
||||
postPerPage: 3,
|
||||
scheduledPostMargin: 15 * 60 * 1000, // 15 minutes
|
||||
showArchives: true,
|
||||
editPost: {
|
||||
url: "https://github.com/satnaing/astro-paper/edit/main/src/content/blog",
|
||||
text: "Suggest Changes",
|
||||
@@ -54,6 +55,7 @@ Here are SITE configuration options
|
||||
| `postPerIndex` | The number of posts to be displayed at the home page under `Recent` section. |
|
||||
| `postPerPage` | You can specify how many posts will be displayed in each posts page. (eg: if you set SITE.postPerPage to 3, each page will only show 3 posts per page) |
|
||||
| `scheduledPostMargin` | In Production mode, posts with a future `pubDatetime` will not be visible. However, if a post's `pubDatetime` is within the next 15 minutes, it will be visible. You can set `scheduledPostMargin` if you don't like the default 15 minutes margin. |
|
||||
| `showArchives` | Determines whether to display the `Archives` menu (positioned between the `About` and `Search` menus) and its corresponding page on the site. This option is set to `true` by default. |
|
||||
| `editPost` | This option allows users to suggest changes to a blog post by providing an edit link under blog post titles. This feature can be disabled by removing it from the `SITE` config. You can also set `appendFilePath` to `true` to automatically append the file path of the post to the url, directing users to the specific post they wish to edit. |
|
||||
|
||||
## Configuring locale
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import Card from "@components/Card";
|
||||
import Footer from "@components/Footer.astro";
|
||||
import Header from "@components/Header.astro";
|
||||
import { SITE } from "@config";
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import Main from "@layouts/Main.astro";
|
||||
import getPostsByGroupCondition from "@utils/getPostsByGroupCondition";
|
||||
|
||||
// Redirect to 404 page if `showArchives` config is false
|
||||
if (!SITE.showArchives) {
|
||||
return Astro.redirect("/404");
|
||||
}
|
||||
|
||||
const posts = await getCollection("blog", ({ data }) => !data.draft);
|
||||
|
||||
const MonthMap: Record<string, string> = {
|
||||
"1": "January",
|
||||
"2": "February",
|
||||
"3": "March",
|
||||
"4": "April",
|
||||
"5": "May",
|
||||
"6": "June",
|
||||
"7": "July",
|
||||
"8": "August",
|
||||
"9": "September",
|
||||
"10": "October",
|
||||
"11": "November",
|
||||
"12": "December",
|
||||
};
|
||||
---
|
||||
|
||||
<Layout title={`Archives | ${SITE.title}`}>
|
||||
<Header activeNav="archives" />
|
||||
<Main pageTitle="Archives" pageDesc="All the articles I've archived.">
|
||||
{
|
||||
Object.entries(
|
||||
getPostsByGroupCondition(posts, post =>
|
||||
post.data.pubDatetime.getFullYear()
|
||||
)
|
||||
)
|
||||
.sort(([yearA], [yearB]) => Number(yearB) - Number(yearA))
|
||||
.map(([year, yearGroup]) => (
|
||||
<div>
|
||||
<span class="text-2xl font-bold">{year}</span>
|
||||
<sup class="text-sm">{yearGroup.length}</sup>
|
||||
{Object.entries(
|
||||
getPostsByGroupCondition(
|
||||
yearGroup,
|
||||
post => post.data.pubDatetime.getMonth() + 1
|
||||
)
|
||||
)
|
||||
.sort(([monthA], [monthB]) => Number(monthB) - Number(monthA))
|
||||
.map(([month, monthGroup]) => (
|
||||
<div class="flex flex-col sm:flex-row">
|
||||
<div class="mt-6 min-w-36 text-lg sm:my-6">
|
||||
<span class="font-bold">{MonthMap[month]}</span>
|
||||
<sup class="text-xs">{monthGroup.length}</sup>
|
||||
</div>
|
||||
<ul>
|
||||
{monthGroup.map(({ data, slug }) => (
|
||||
<Card href={`/posts/${slug}`} frontmatter={data} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</Main>
|
||||
|
||||
<Footer />
|
||||
</Layout>
|
||||
@@ -11,6 +11,7 @@ export type Site = {
|
||||
postPerIndex: number;
|
||||
postPerPage: number;
|
||||
scheduledPostMargin: number;
|
||||
showArchives?: boolean;
|
||||
editPost?: {
|
||||
url?: URL["href"];
|
||||
text?: string;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
|
||||
type GroupKey = string | number | symbol;
|
||||
|
||||
interface GroupFunction<T> {
|
||||
(item: T, index?: number): GroupKey;
|
||||
}
|
||||
|
||||
const getPostsByGroupCondition = (
|
||||
posts: CollectionEntry<"blog">[],
|
||||
groupFunction: GroupFunction<CollectionEntry<"blog">>
|
||||
) => {
|
||||
const result: Record<GroupKey, CollectionEntry<"blog">[]> = {};
|
||||
for (let i = 0; i < posts.length; i++) {
|
||||
const item = posts[i];
|
||||
const groupKey = groupFunction(item, i);
|
||||
if (!result[groupKey]) {
|
||||
result[groupKey] = [];
|
||||
}
|
||||
result[groupKey].push(item);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default getPostsByGroupCondition;
|
||||
Reference in New Issue
Block a user