Skip to content

Commit

Permalink
[Release] 2024-12-23
Browse files Browse the repository at this point in the history
[Release] 2024-12-23
  • Loading branch information
Hong-JunHyeok authored Dec 23, 2024
2 parents ccb54db + f1c0325 commit 5e94bb0
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 10 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"next": "15.0.2",
"react": "19.0.0-rc-02c0e824-20241028",
"react-dom": "19.0.0-rc-02c0e824-20241028",
"react-icons": "^5.4.0",
"remark": "^15.0.1",
"remark-html": "^16.0.1",
"tailwind-merge": "^2.5.5"
Expand Down
12 changes: 12 additions & 0 deletions src/app/home/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Container from "@/components/container";
import ScrollToTopButton from "@/components/scroll-to-top-button";
import { PropsWithChildren } from "react";

export default function Layout({ children }: PropsWithChildren) {
return (
<main>
<Container>{children}</Container>
<ScrollToTopButton />
</main>
);
}
15 changes: 6 additions & 9 deletions src/app/home/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import Container from "@/components/container";
import { getAllPosts } from "@/lib/api";
import Intro from "./_components/intro";
import HeroPost from "./_components/hero-post";
import MorePosts from "./_components/more-posts";

export default function Index() {
export default function Page() {
const allPosts = getAllPosts();

const [heroPost, ...morePosts] = allPosts;

return (
<main>
<Container>
<Intro />
<HeroPost {...heroPost} />
{morePosts.length > 0 && <MorePosts posts={morePosts} />}
</Container>
</main>
<>
<Intro />
<HeroPost {...heroPost} />
{morePosts.length > 0 && <MorePosts posts={morePosts} />}
</>
);
}
2 changes: 1 addition & 1 deletion src/app/posts/[slug]/_components/post-alert/PostAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default function PostAlert({ slug }: Props) {
const GITHUB_FILE_LINK = `https://github.com/Hong-JunHyeok/liam-tech-blog/blob/main/_posts/${slug}.md`;

return (
<div className="border-b bg-accent-1 border-accent-2 fixed top-0 w-full">
<div className="border-b bg-accent-1 border-accent-2 fixed top-0 w-full z-50">
<div className="container mx-auto px-5">
<div className="py-2 text-center text-sm ">
지금 보시는 글은 100% 완벽하지 않습니다. 수정사항은{" "}
Expand Down
9 changes: 9 additions & 0 deletions src/app/posts/[slug]/_components/post-body/PostBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ const marked = new Marked(
})
);

const renderer = new marked.Renderer();

renderer.heading = ({ text, depth }) => {
const id = text;
return `<h${depth} id="${id}">${text}</h${depth}>`;
};

marked.setOptions({ renderer });

export function PostBody({ content }: Props) {
return (
<div className="max-w-2xl mx-auto">
Expand Down
46 changes: 46 additions & 0 deletions src/app/posts/[slug]/_components/post-toc/PostTOC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client";
import Link from "next/link";
import { getHeadingList, moveToTitleTag } from "./utils";
import classNames from "classnames";

type Props = {
content: string;
};

function PostTOC({ content }: Props) {
const headingList = getHeadingList(content);

const handleClickAnchor =
(title: string) => (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
moveToTitleTag(title);
};

return (
<ul className="max-w-2xl mx-auto flex-row">
{headingList.map(({ title, level }, index) => {
return (
<li
key={index}
className={classNames(
"mb-2",
{ "ml-6": level === 2 },
{ "ml-12": level === 3 },
{ "ml-18": level === 4 }
)}
>
<Link
href={`#${title}`}
onClick={handleClickAnchor(title)}
className="text-slate-600 underline opacity-60 inline-block"
>
{title}
</Link>
</li>
);
})}
</ul>
);
}

export default PostTOC;
3 changes: 3 additions & 0 deletions src/app/posts/[slug]/_components/post-toc/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import PostTOC from "./PostTOC";

export default PostTOC;
38 changes: 38 additions & 0 deletions src/app/posts/[slug]/_components/post-toc/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const getHeadingWithLevel = (heading: string) => {
const headingPattern = /^(#+)\s+(.*)$/;

const match = heading.match(headingPattern);
if (!match) return { level: 0, title: "" };

const level = match[1].length;
const title = match[2].trim();

return { level, title };
};

export const getHeadingList = (content: string) => {
const headingPattern = /^(#+)\s+(.*)$/gm;
const matchedHeadings = content.match(headingPattern);

if (!matchedHeadings) return [];

const headingsWithLevel = matchedHeadings.map(getHeadingWithLevel);

const minLevel = Math.min(...headingsWithLevel.map(({ level }) => level));

return headingsWithLevel.map(({ level, title }) => ({
level: level - minLevel + 1,
title,
}));
};

export const moveToTitleTag = (targetId: string) => {
const targetElement = document.getElementById(targetId);
if (!targetElement) return;
const position = targetElement.getBoundingClientRect();
window.scrollTo({
behavior: "smooth",
left: position.left,
top: position.top + window.scrollY - 60,
});
};
2 changes: 2 additions & 0 deletions src/app/posts/[slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import Footer from "@/components/footer";
import ScrollToTopButton from "@/components/scroll-to-top-button";
import { PropsWithChildren } from "react";

export default function PostLayout({ children }: PropsWithChildren) {
return (
<>
{children}
<Footer />
<ScrollToTopButton />
</>
);
}
2 changes: 2 additions & 0 deletions src/app/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Header from "@/components/header";
import PostHeader from "./_components/post-header";
import PostBody from "./_components/post-body";
import PostAlert from "./_components/post-alert";
import PostTOC from "./_components/post-toc";

type Params = {
params: Promise<{
Expand All @@ -27,6 +28,7 @@ export default async function Post(props: Params) {
<Header />
<article className="mb-32">
<PostHeader {...post} />
<PostTOC content={post.content} />
<PostBody content={post.content} />
</article>
</Container>
Expand Down
20 changes: 20 additions & 0 deletions src/components/scroll-to-top-button/ScrollToTopButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use client";
import { FaArrowUp } from "react-icons/fa";
import { useButtonVisible } from "./hooks";

function ScrollToTopButton() {
const { isVisible, scrollToTop } = useButtonVisible();

return (
isVisible && (
<button
onClick={scrollToTop}
className="fixed bottom-5 right-5 p-3 bg-content text-white rounded-full shadow-lg focus:outline-none focus:ring-2 focus:ring-opacity-50 transition-all"
>
<FaArrowUp />
</button>
)
);
}

export default ScrollToTopButton;
30 changes: 30 additions & 0 deletions src/components/scroll-to-top-button/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect, useState } from "react";

export const useButtonVisible = () => {
const [isVisible, setIsVisible] = useState(false);

const handleScroll = () => {
if (window.scrollY > 1200) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};

const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};

useEffect(() => {
window.addEventListener("scroll", handleScroll);

return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);

return { isVisible, scrollToTop };
};
3 changes: 3 additions & 0 deletions src/components/scroll-to-top-button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ScrollToTopButton from "./ScrollToTopButton";

export default ScrollToTopButton;
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,11 @@ [email protected]:
dependencies:
scheduler "0.25.0-rc-02c0e824-20241028"

react-icons@^5.4.0:
version "5.4.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.4.0.tgz#443000f6e5123ee1b21ea8c0a716f6e7797f7416"
integrity sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==

[email protected]:
version "19.0.0-rc-02c0e824-20241028"
resolved "https://registry.yarnpkg.com/react/-/react-19.0.0-rc-02c0e824-20241028.tgz#d0f92b734b245471359fec4be89b3f26e23f3197"
Expand Down

0 comments on commit 5e94bb0

Please sign in to comment.