Skip to content

Commit 4e3e212

Browse files
COMPLETE!
1 parent fa163ce commit 4e3e212

File tree

6 files changed

+193
-19
lines changed

6 files changed

+193
-19
lines changed

public/posts/2025/04/renewed-with-nextjs/article.md renamed to public/posts/article-2025/04/renewed-with-nextjs/article.md

File renamed without changes.

public/posts/2025/04/renewed-with-nextjs/thumbnail.png renamed to public/posts/article-2025/04/renewed-with-nextjs/thumbnail.png

File renamed without changes.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
@import "tailwindcss";
2+
3+
html {
4+
scroll-behavior: smooth;
5+
}
6+
7+
.article-container {
8+
display: flex;
9+
gap: 20px;
10+
flex-wrap: wrap;
11+
overflow-x: hidden auto;
12+
min-height: 100vh;
13+
/* スマートフォン対応 */
14+
}
15+
16+
.toc {
17+
flex: 1;
18+
top: 64px;
19+
left: 0;
20+
max-height: calc(100vh - 128px);
21+
overflow-y: auto;
22+
overflow-x: hidden;
23+
border: 1px solid var(--primary);
24+
padding: 16px;
25+
border-radius: 8px;
26+
background-color: var(--background);
27+
min-width: 250px;
28+
/* 最小幅を設定 */
29+
}
30+
31+
.toc h2 {
32+
font-size: 1.25rem;
33+
margin-bottom: 8px;
34+
}
35+
36+
.toc ul {
37+
list-style: none;
38+
padding: 0;
39+
}
40+
41+
.toc li {
42+
margin-bottom: 8px;
43+
}
44+
45+
.toc a {
46+
text-decoration: none;
47+
color: var(--link-color);
48+
cursor: pointer;
49+
}
50+
51+
.toc a:hover {
52+
text-decoration: underline;
53+
}
54+
55+
.article-detail {
56+
flex: 3;
57+
min-width: 300px;
58+
/* 最小幅を設定 */
59+
}
60+
61+
.article-thumbnail {
62+
width: 100%;
63+
height: auto;
64+
border-radius: 8px;
65+
margin-bottom: 16px;
66+
}
67+
68+
.article-content {
69+
line-height: 1.6;
70+
}
71+
72+
.other-articles {
73+
margin-top: 40px;
74+
top: 20px;
75+
/* スクロール時に追従 */
76+
}
77+
78+
.other-articles h2 {
79+
font-size: 1.5rem;
80+
margin-bottom: 16px;
81+
}
82+
83+
.other-articles ul {
84+
list-style: none;
85+
padding: 0;
86+
}
87+
88+
.other-articles li {
89+
margin-bottom: 8px;
90+
}
91+
92+
.other-articles a {
93+
text-decoration: none;
94+
color: var(--link-color);
95+
}
96+
97+
.other-articles a:hover {
98+
text-decoration: underline;
99+
}
100+
101+
/* スマートフォン対応 */
102+
@media (max-width: 768px) {
103+
.article-container {
104+
flex-direction: column;
105+
/* 縦並びに変更 */
106+
}
107+
108+
.toc {
109+
position: relative;
110+
/* stickyを無効化 */
111+
max-height: none;
112+
margin-bottom: 20px;
113+
order: -1;
114+
/* 記事の上部に配置 */
115+
}
116+
117+
.other-articles {
118+
position: relative;
119+
/* stickyを無効化 */
120+
top: auto;
121+
margin-top: 20px;
122+
/* 記事の下部に配置 */
123+
}
124+
}
Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { getArticleIndexes,toHTML } from "../../../article/article";
1+
import { getArticleIndexes, toHTML } from "../../../article/article";
22
import { notFound } from "next/navigation";
33
import Image from "next/image";
4+
import Link from "next/link";
45
import "./page.css"; // 必要に応じてCSSをインポート
56

67
export async function generateStaticParams() {
@@ -22,28 +23,78 @@ export default async function ArticlePage({
2223
const articles = await toHTML(indexes);
2324

2425
// スラッグに一致する記事を探す
25-
const slug = `${params.year}/${params.month}/${params.aid}`;
26+
const slug = `${await params.year}/${await params.month}/${await params.aid}`;
2627
const article = articles.find((a) => a.slug === slug);
2728

2829
if (!article) {
2930
notFound(); // 記事が見つからない場合は404ページを表示
3031
}
3132

33+
// 他の記事一覧を取得
34+
const otherArticles = articles.filter((a) => a.slug !== slug);
35+
36+
// 目次を生成
37+
const headings = article.content.match(/<h[1-6]>.*?<\/h[1-6]>/g) || [];
38+
const toc = headings.map((heading) => {
39+
const id = heading
40+
.replace(/<.*?>/g, "")
41+
.trim()
42+
.toLowerCase()
43+
.replace(/\s+/g, "-");
44+
return { id, text: heading.replace(/<.*?>/g, "").trim() };
45+
});
46+
3247
return (
33-
<article className="article-detail">
34-
<h1>{article.title}</h1>
35-
<p>{article.date}</p>
36-
{article.thumbnail && (
37-
<Image
38-
src={article.thumbnail}
39-
alt={article.title}
40-
width={600}
41-
height={400}
42-
objectFit="cover"
43-
className="article-thumbnail"
48+
<div className="article-container">
49+
<aside className="toc relative md:sticky">
50+
<h2>目次</h2>
51+
<ul>
52+
{toc.map((item) => (
53+
<li key={item.id}>
54+
<a href={`#${item.id}`}>{item.text}</a>
55+
</li>
56+
))}
57+
</ul>
58+
</aside>
59+
<article className="article-detail">
60+
<h1>{article.title}</h1>
61+
<p>{article.date}</p>
62+
{article.thumbnail && (
63+
<Image
64+
src={article.thumbnail}
65+
alt={article.title}
66+
width={800}
67+
height={450} // 16:9 の比率
68+
objectFit="cover"
69+
className="article-thumbnail"
70+
/>
71+
)}
72+
<div
73+
className="article-content"
74+
dangerouslySetInnerHTML={{
75+
__html: article.content.replace(/<h[1-6]>/g, (match) => {
76+
const id = match
77+
.replace(/<.*?>/g, "")
78+
.trim()
79+
.toLowerCase()
80+
.replace(/\s+/g, "-");
81+
return `<h2 id="${id}">`;
82+
}),
83+
}}
4484
/>
45-
)}
46-
<div dangerouslySetInnerHTML={{ __html: article.content }} />
47-
</article>
85+
</article>
86+
<section className="other-articles relative md:sticky">
87+
<h2>他の記事</h2>
88+
<ul>
89+
{otherArticles.map((other) => (
90+
<li key={other.slug}>
91+
<Link href={`/${other.slug}`}>
92+
<a>{other.title}</a>
93+
</Link>
94+
</li>
95+
))}
96+
</ul>
97+
</section>
98+
</div>
4899
);
49100
}

src/app/article/article.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export function getArticleIndexes() {
4444
const { data } = matter(fileContents);
4545

4646
return {
47-
slug: `article-${year}/${month}/${articleId}`,
47+
slug: `${year}/${month}/${articleId}`,
4848
title: data.title || "Untitled", // タイトルがない場合のデフォルト値
4949
date: data.date || "Unknown date", // 日付がない場合のデフォルト値
5050
thumbnail: thumbnailPath,

src/app/globals.css

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* /home/the-infinitys/github/the-infinitys.next.site/src/app/globals.css */
21
@import "tailwindcss";
32

43
:root {
@@ -83,7 +82,7 @@ main {
8382
main>section.title>h1 {
8483
text-align: center;
8584
font-family: "Chakra Petch", "noto-sans", sans-serif;
86-
font-size: 64px;
85+
font-size: min(64px,8vw);
8786
font-weight: 600;
8887
font-style: italic;
8988
padding: 2rem;

0 commit comments

Comments
 (0)