-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Release] 2024-12-23
- Loading branch information
Showing
14 changed files
with
178 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} />} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import PostTOC from "./PostTOC"; | ||
|
||
export default PostTOC; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 /> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import ScrollToTopButton from "./ScrollToTopButton"; | ||
|
||
export default ScrollToTopButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|