Skip to content

Commit 7573617

Browse files
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 <[email protected]>
1 parent 58a0d25 commit 7573617

File tree

7 files changed

+146
-3
lines changed

7 files changed

+146
-3
lines changed

src/components/Header.astro

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Hr from "./Hr.astro";
44
import LinkButton from "./LinkButton.astro";
55
66
export interface Props {
7-
activeNav?: "posts" | "tags" | "about" | "search";
7+
activeNav?: "posts" | "archives" | "tags" | "about" | "search";
88
}
99
1010
const { activeNav } = Astro.props;
@@ -70,6 +70,41 @@ const { activeNav } = Astro.props;
7070
About
7171
</a>
7272
</li>
73+
{
74+
SITE.showArchives && (
75+
<li>
76+
<LinkButton
77+
href="/archives/"
78+
className={`focus-outline flex justify-center p-3 sm:p-1`}
79+
ariaLabel="archives"
80+
title="Archives"
81+
>
82+
<svg
83+
xmlns="http://www.w3.org/2000/svg"
84+
class:list={[
85+
"icon icon-tabler icons-tabler-outline !hidden sm:!inline-block",
86+
activeNav === "archives" && "!stroke-skin-accent",
87+
]}
88+
>
89+
<>
90+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
91+
<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" />
92+
<path d="M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10" />
93+
<path d="M10 12l4 0" />
94+
</>
95+
</svg>
96+
<span
97+
class:list={[
98+
"sm:sr-only",
99+
activeNav === "archives" && "active",
100+
]}
101+
>
102+
Archives
103+
</span>
104+
</LinkButton>
105+
</li>
106+
)
107+
}
73108
<li>
74109
<LinkButton
75110
href="/search/"
@@ -155,7 +190,7 @@ const { activeNav } = Astro.props;
155190
nav ul li:nth-last-child(2) {
156191
@apply col-span-1;
157192
}
158-
nav a.active {
193+
nav .active {
159194
@apply underline decoration-wavy decoration-2 underline-offset-4;
160195
}
161196
nav a.active svg {

src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const SITE: Site = {
1111
postPerIndex: 4,
1212
postPerPage: 3,
1313
scheduledPostMargin: 15 * 60 * 1000, // 15 minutes
14+
showArchives: true,
1415
editPost: {
1516
url: "https://github.com/satnaing/astro-paper/edit/main/src/content/blog",
1617
text: "Suggest Changes",

src/content/blog/how-to-configure-astropaper-theme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
author: Sat Naing
33
pubDatetime: 2022-09-23T04:58:53Z
4-
modDatetime: 2024-01-15T13:05:56.066Z
4+
modDatetime: 2024-10-14T09:27:28.605Z
55
title: How to configure AstroPaper theme
66
slug: how-to-configure-astropaper-theme
77
featured: true
@@ -33,6 +33,7 @@ export const SITE = {
3333
lightAndDarkMode: true,
3434
postPerPage: 3,
3535
scheduledPostMargin: 15 * 60 * 1000, // 15 minutes
36+
showArchives: true,
3637
editPost: {
3738
url: "https://github.com/satnaing/astro-paper/edit/main/src/content/blog",
3839
text: "Suggest Changes",
@@ -54,6 +55,7 @@ Here are SITE configuration options
5455
| `postPerIndex` | The number of posts to be displayed at the home page under `Recent` section. |
5556
| `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) |
5657
| `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. |
58+
| `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. |
5759
| `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. |
5860

5961
## Configuring locale

src/pages/archives/index.astro

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
import { getCollection } from "astro:content";
3+
import Card from "@components/Card";
4+
import Footer from "@components/Footer.astro";
5+
import Header from "@components/Header.astro";
6+
import { SITE } from "@config";
7+
import Layout from "@layouts/Layout.astro";
8+
import Main from "@layouts/Main.astro";
9+
import getPostsByGroupCondition from "@utils/getPostsByGroupCondition";
10+
11+
// Redirect to 404 page if `showArchives` config is false
12+
if (!SITE.showArchives) {
13+
return Astro.redirect("/404");
14+
}
15+
16+
const posts = await getCollection("blog", ({ data }) => !data.draft);
17+
18+
const MonthMap: Record<string, string> = {
19+
"1": "January",
20+
"2": "February",
21+
"3": "March",
22+
"4": "April",
23+
"5": "May",
24+
"6": "June",
25+
"7": "July",
26+
"8": "August",
27+
"9": "September",
28+
"10": "October",
29+
"11": "November",
30+
"12": "December",
31+
};
32+
---
33+
34+
<Layout title={`Archives | ${SITE.title}`}>
35+
<Header activeNav="archives" />
36+
<Main pageTitle="Archives" pageDesc="All the articles I've archived.">
37+
{
38+
Object.entries(
39+
getPostsByGroupCondition(posts, post =>
40+
post.data.pubDatetime.getFullYear()
41+
)
42+
)
43+
.sort(([yearA], [yearB]) => Number(yearB) - Number(yearA))
44+
.map(([year, yearGroup]) => (
45+
<div>
46+
<span class="text-2xl font-bold">{year}</span>
47+
<sup class="text-sm">{yearGroup.length}</sup>
48+
{Object.entries(
49+
getPostsByGroupCondition(
50+
yearGroup,
51+
post => post.data.pubDatetime.getMonth() + 1
52+
)
53+
)
54+
.sort(([monthA], [monthB]) => Number(monthB) - Number(monthA))
55+
.map(([month, monthGroup]) => (
56+
<div class="flex flex-col sm:flex-row">
57+
<div class="mt-6 min-w-36 text-lg sm:my-6">
58+
<span class="font-bold">{MonthMap[month]}</span>
59+
<sup class="text-xs">{monthGroup.length}</sup>
60+
</div>
61+
<ul>
62+
{monthGroup.map(({ data, slug }) => (
63+
<Card href={`/posts/${slug}`} frontmatter={data} />
64+
))}
65+
</ul>
66+
</div>
67+
))}
68+
</div>
69+
))
70+
}
71+
</Main>
72+
73+
<Footer />
74+
</Layout>

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type Site = {
1111
postPerIndex: number;
1212
postPerPage: number;
1313
scheduledPostMargin: number;
14+
showArchives?: boolean;
1415
editPost?: {
1516
url?: URL["href"];
1617
text?: string;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { CollectionEntry } from "astro:content";
2+
3+
type GroupKey = string | number | symbol;
4+
5+
interface GroupFunction<T> {
6+
(item: T, index?: number): GroupKey;
7+
}
8+
9+
const getPostsByGroupCondition = (
10+
posts: CollectionEntry<"blog">[],
11+
groupFunction: GroupFunction<CollectionEntry<"blog">>
12+
) => {
13+
const result: Record<GroupKey, CollectionEntry<"blog">[]> = {};
14+
for (let i = 0; i < posts.length; i++) {
15+
const item = posts[i];
16+
const groupKey = groupFunction(item, i);
17+
if (!result[groupKey]) {
18+
result[groupKey] = [];
19+
}
20+
result[groupKey].push(item);
21+
}
22+
return result;
23+
};
24+
25+
export default getPostsByGroupCondition;

tailwind.config.cjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ module.exports = {
5454
},
5555
transparent: "transparent",
5656
},
57+
stroke: {
58+
skin: {
59+
accent: withOpacity("--color-accent")
60+
}
61+
},
5762
fontFamily: {
5863
mono: ["IBM Plex Mono", "monospace"],
5964
},

0 commit comments

Comments
 (0)