diff --git a/README.md b/README.md
index 77f68d6..7cc754f 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ npm run dev [-- --open]
### Formatting
``` bash
-npx run eslint
+npx eslint
```
### Testing
diff --git a/src/content/post/placeholder1.md b/src/content/post/placeholder1.md
index ec423d5..72a5f65 100644
--- a/src/content/post/placeholder1.md
+++ b/src/content/post/placeholder1.md
@@ -3,6 +3,7 @@ title: Placeholder 1
date: '2024-09-01'
description: "This is a placeholder description"
tags: ["a123", "ボースト"]
+series: ["placeholder"]
---
# 1st Level Heading
diff --git a/src/content/post/placeholder2.md b/src/content/post/placeholder2.md
new file mode 100644
index 0000000..356955e
--- /dev/null
+++ b/src/content/post/placeholder2.md
@@ -0,0 +1,8 @@
+---
+title: Placeholder 2
+date: '2024-09-20'
+description: "This is a placeholder description"
+tags: ["a123"]
+series: ["placeholder"]
+---
+## Content
diff --git a/src/content/post/placeholder3.md b/src/content/post/placeholder3.md
new file mode 100644
index 0000000..52bf7b5
--- /dev/null
+++ b/src/content/post/placeholder3.md
@@ -0,0 +1,8 @@
+---
+title: Placeholder 3
+date: '2024-09-24'
+description: "This is a placeholder description"
+tags: []
+series: ["placeholder"]
+---
+## Content
diff --git a/src/content/post/the-perfect-math-class.md b/src/content/post/the-perfect-math-class.md
new file mode 100644
index 0000000..e1d3717
--- /dev/null
+++ b/src/content/post/the-perfect-math-class.md
@@ -0,0 +1,6 @@
+---
+title: The Perfect Math Class
+date: '2024-09-15'
+tags: ["Cirno"]
+---
+# Content
diff --git a/src/hooks.ts b/src/hooks.ts
new file mode 100644
index 0000000..7ea2285
--- /dev/null
+++ b/src/hooks.ts
@@ -0,0 +1,11 @@
+import type { Reroute } from '@sveltejs/kit';
+
+const translated: Record = {
+ '/post': '/page/1',
+};
+
+export const reroute: Reroute = ({ url }) => {
+ if (url.pathname in translated) {
+ return translated[url.pathname];
+ }
+};
diff --git a/src/routes/post/Heading.svelte b/src/lib/components/PostHeader.svelte
similarity index 75%
rename from src/routes/post/Heading.svelte
rename to src/lib/components/PostHeader.svelte
index 8911892..edfba5c 100644
--- a/src/routes/post/Heading.svelte
+++ b/src/lib/components/PostHeader.svelte
@@ -3,11 +3,15 @@
export let metadata : { title: string, description: string, tags: [string], date: Date };
export let link: Option = null;
- const date = metadata.date.toLocaleDateString();
+ const date = metadata.date.toISOString().slice(0,-14);
+ const series = metadata?.series || [];
+ {#each series as seriesTag}
+
{seriesTag}
+ {/each}
{#if link}
{metadata.title}
{:else}
@@ -25,7 +29,7 @@
{/if}
- {tag}
+ {tag}
{/each}
{date}
@@ -35,9 +39,12 @@
diff --git a/src/lib/posts.ts b/src/lib/posts.ts
new file mode 100644
index 0000000..0c31b6e
--- /dev/null
+++ b/src/lib/posts.ts
@@ -0,0 +1,41 @@
+export async function getPosts(tag: string | null = null) {
+ const allPostFiles = import.meta.glob('$content/post/*.md');
+ const iterablePostFiles = Object.entries(allPostFiles);
+
+ let posts = await Promise.all(
+ iterablePostFiles.map(async ([pathMarkdown, resolver]) => {
+ const { metadata } = await resolver();
+ const pathPost = "/post/" + pathMarkdown.slice(pathMarkdown.lastIndexOf("/") + 1, -".md".length);
+
+ return {
+ meta: {
+ ...metadata,
+ date: new Date(metadata.date),
+ },
+ path: pathPost
+ };
+ })
+ );
+ if (tag)
+ posts = posts.filter(obj => obj.meta.tags.includes(tag))
+
+ posts.sort((post1, post2) => {
+ const date1: Date = post1.meta.date;
+ const date2: Date = post2.meta.date;
+ return date2.getTime() - date1.getTime();
+ });
+ return posts;
+}
+
+export async function getTags() {
+ const allPostFiles = import.meta.glob('$content/post/*.md');
+ const iterablePostFiles = Object.entries(allPostFiles);
+
+ const allPosts: string[][] = await Promise.all(
+ iterablePostFiles.map(async ([_, resolver]) => {
+ const { metadata } = await resolver();
+ return metadata.tags;
+ })
+ );
+ return new Set(allPosts.flat());
+}
diff --git a/src/lib/sitemap.ts b/src/lib/sitemap.ts
index 34c2365..3b312b9 100644
--- a/src/lib/sitemap.ts
+++ b/src/lib/sitemap.ts
@@ -1,6 +1,7 @@
-export const routes: { route: string, name: string, inactive?: boolean }[] = [
+export const routes: { route: string, name: string, disabled?: boolean }[] = [
{ route: "/", name: "Home" },
{ route: "/post", name: "Blog" },
- { route: "/art", name: "Art", inactive: true },
+ { route: "/tag", name: "Tags" },
+ { route: "/gallery", name: "Gallery", disabled: true },
{ route: "/archives", name: "Archives" },
];
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index f152ced..7170bf9 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -3,6 +3,9 @@
import { page } from '$app/stores';
import Footer from "./Footer.svelte";
import Navbar from "./Navbar.svelte";
+ import PageTransition from "./PageTransition.svelte";
+
+ export let data : { url: string };
@@ -12,24 +15,30 @@
-
+
{:else}
-
+
+
+
+
{/if}
diff --git a/src/routes/gallery/+page.svelte b/src/routes/gallery/+page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/page/[slug]/+page.svelte b/src/routes/page/[slug]/+page.svelte
new file mode 100644
index 0000000..a57b3e5
--- /dev/null
+++ b/src/routes/page/[slug]/+page.svelte
@@ -0,0 +1,64 @@
+
+
+
+ Page {pageN } | {siteMetadata.blogName}
+
+
+
+
+ {#each posts as post}
+ -
+
+
+ {/each}
+
+
+
+
+
diff --git a/src/routes/page/[slug]/+page.ts b/src/routes/page/[slug]/+page.ts
new file mode 100644
index 0000000..dd9e8c7
--- /dev/null
+++ b/src/routes/page/[slug]/+page.ts
@@ -0,0 +1,22 @@
+import { error } from '@sveltejs/kit';
+import type { PageLoad } from './$types';
+import { getPosts } from '$lib/posts';
+import siteMetadata from '$content/metadata.json';
+
+export const load: PageLoad = async ({ params }) => {
+ const pageN: number = +params.slug;
+ if (!pageN) throw error(404);
+
+ const posts = await getPosts();
+
+ const pageSize = siteMetadata?.pageSize || 3;
+
+ const maxPageN = Math.ceil(posts.length / pageSize);
+ if (pageN < 0 || pageN > maxPageN) throw error(404);
+
+ return {
+ pageN,
+ posts: posts.slice((pageN - 1) * pageSize, pageN * pageSize),
+ maxPageN,
+ };
+}
diff --git a/src/routes/post/+page.server.ts b/src/routes/post/+page.server.ts
index 368c4b9..fc78cd1 100644
--- a/src/routes/post/+page.server.ts
+++ b/src/routes/post/+page.server.ts
@@ -1,30 +1,7 @@
import type { PageLoad } from './$types';
+import { getPosts } from '$lib/posts';
export const load: PageLoad = async (_) => {
- const allPostFiles = import.meta.glob('$content/post/*.md');
- const iterablePostFiles = Object.entries(allPostFiles);
-
- const allPosts = await Promise.all(
- iterablePostFiles.map(async ([pathMarkdown, resolver]) => {
- const { metadata } = await resolver();
- const pathPost = pathMarkdown.slice(pathMarkdown.lastIndexOf("/") + 1, -".md".length);
-
- return {
- meta: {
- ...metadata,
- date: new Date(metadata.date),
- },
- path: pathPost
- };
- })
- );
-
- allPosts.sort((post1, post2) => {
- const date1: Date = post1.meta.date;
- const date2: Date = post2.meta.date;
- return date2.getTime() - date1.getTime();
- });
- return {
- allPosts
- };
+ const allPosts = await getPosts();
+ return { allPosts };
};
diff --git a/src/routes/post/+page.svelte b/src/routes/post/+page.svelte
index f5925fd..5298603 100644
--- a/src/routes/post/+page.svelte
+++ b/src/routes/post/+page.svelte
@@ -3,7 +3,7 @@
export let data: PageData;
const { allPosts } = data;
import siteMetadata from '$content/metadata.json';
- import Heading from './Heading.svelte';
+ import PostHeader from '$lib/components/PostHeader.svelte';
@@ -14,7 +14,7 @@
{#each allPosts as post}
-
-
+
{/each}
diff --git a/src/routes/post/[slug]/+page.svelte b/src/routes/post/[slug]/+page.svelte
index 80f44ee..e25a1a1 100644
--- a/src/routes/post/[slug]/+page.svelte
+++ b/src/routes/post/[slug]/+page.svelte
@@ -3,14 +3,14 @@
export let data: PageData;
const { metadata, Content } = data;
import siteMetadata from '$content/metadata.json';
- import Heading from '../Heading.svelte';
+ import PostHeader from '$lib/components/PostHeader.svelte';
{metadata.title} | {siteMetadata.blogName}
-
+
diff --git a/src/routes/tag/+page.server.ts b/src/routes/tag/+page.server.ts
new file mode 100644
index 0000000..a5bf330
--- /dev/null
+++ b/src/routes/tag/+page.server.ts
@@ -0,0 +1,7 @@
+import type { PageLoad } from './$types';
+import { getTags } from '$lib/posts';
+
+export const load: PageLoad = async (_) => {
+ const allTags = await getTags();
+ return { allTags };
+};
diff --git a/src/routes/tag/+page.svelte b/src/routes/tag/+page.svelte
new file mode 100644
index 0000000..b0b49de
--- /dev/null
+++ b/src/routes/tag/+page.svelte
@@ -0,0 +1,27 @@
+
+
+
+ Tags | {siteMetadata.blogName}
+
+
+Tags
+
+
+
+ {#each allTags as tag}
+
{tag}
+ {/each}
+
+
+
+
diff --git a/src/routes/tag/[slug]/+page.svelte b/src/routes/tag/[slug]/+page.svelte
new file mode 100644
index 0000000..ccf9660
--- /dev/null
+++ b/src/routes/tag/[slug]/+page.svelte
@@ -0,0 +1,29 @@
+
+
+
+ {name} | {siteMetadata.blogName}
+
+
+{name}
+
+
+
+ {#each posts as post}
+ -
+
+
+ {/each}
+
+
+
+
diff --git a/src/routes/tag/[slug]/+page.ts b/src/routes/tag/[slug]/+page.ts
new file mode 100644
index 0000000..f3a0fe0
--- /dev/null
+++ b/src/routes/tag/[slug]/+page.ts
@@ -0,0 +1,10 @@
+import type { PageLoad } from './$types';
+import { getPosts } from '$lib/posts';
+
+export const load: PageLoad = async ({ params }) => {
+ const posts = await getPosts(params.slug);
+ return {
+ name: params.slug,
+ posts,
+ };
+}
diff --git a/svelte.config.js b/svelte.config.js
index 10d220e..2ffb103 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -40,6 +40,12 @@ const config = {
precompress: false,
trailingSlash: 'always',
}),
+ prerender: {
+ crawl: true,
+ entries: [
+ "/page/1/",
+ ],
+ },
alias: {
$content: contentDir,
"@/*": "./*",
diff --git a/tests/post.spec.ts b/tests/post.spec.ts
new file mode 100644
index 0000000..bcd1052
--- /dev/null
+++ b/tests/post.spec.ts
@@ -0,0 +1,7 @@
+import { expect, test } from '@playwright/test';
+
+test('Navigate to blog post', async ({ page }) => {
+ await page.goto('/post');
+ await page.getByText('The Perfect Math Class').click();
+ await expect(page).toHaveURL("/post/the-perfect-math-class/");
+});