upgrade the project
This commit is contained in:
@@ -3,7 +3,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Footer } from "@/components/utils/Footer";
|
||||
import { NavBar } from "@/components/utils/NavBar";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
import { TfiFaceSad } from "react-icons/tfi";
|
||||
|
||||
export default function NotFoundPage() {
|
||||
@@ -15,17 +14,17 @@ export default function NotFoundPage() {
|
||||
<Page>
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold font-fang-zheng-xiao-biao-song`}>
|
||||
{"404 NOT FOUND"}
|
||||
</h2>
|
||||
<Separator />
|
||||
<div className="my-5 flex flex-col justify-center">
|
||||
<TfiFaceSad className="mx-auto my-4" size={"6em"} />
|
||||
<p className={`${fontSourceSerifScreenCN.className} mx-auto my-3 text-center text-xl`}>
|
||||
<p className={`font-source-serif-screen mx-auto my-3 text-center text-xl`}>
|
||||
{"This page does not exist for it might be removed or closed."}
|
||||
</p>
|
||||
<div className="my-5 flex justify-center">
|
||||
<Button onClick={handleGoBack} className="font-bold">
|
||||
<Button className="font-bold" onClick={handleGoBack}>
|
||||
{"GO BACK"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Footer } from "@/components/utils/Footer";
|
||||
import { NavBar } from "@/components/utils/NavBar";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
import { MdOutlineDangerous } from "react-icons/md";
|
||||
|
||||
export default function ServerErrorPage() {
|
||||
@@ -15,17 +14,17 @@ export default function ServerErrorPage() {
|
||||
<Page>
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold font-fang-zheng-xiao-biao-song`}>
|
||||
{"INVALID OPERATION"}
|
||||
</h2>
|
||||
<Separator />
|
||||
<div className="my-5 flex flex-col justify-center">
|
||||
<MdOutlineDangerous className="mx-auto my-4" size={"6em"} />
|
||||
<p className={`${fontSourceSerifScreenCN.className} mx-auto my-3 text-center text-xl`}>
|
||||
<p className={`font-source-serif-screen mx-auto my-3 text-center text-xl`}>
|
||||
{"Something went wrong. Please try again later."}
|
||||
</p>
|
||||
<div className="my-5 flex justify-center">
|
||||
<Button onClick={handleGoBack} className="font-bold">
|
||||
<Button className="font-bold" onClick={handleGoBack}>
|
||||
{"GO BACK"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import "katex/dist/katex.min.css";
|
||||
import { ThemeProvider } from "next-themes";
|
||||
import type { AppProps } from "next/app";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
|
||||
@@ -5,24 +5,22 @@ import { NavBar } from "@/components/utils/NavBar";
|
||||
import { SEO } from "@/components/utils/SEO";
|
||||
import { SocialIcons } from "@/components/utils/SocialIcons";
|
||||
import { Config } from "@/data/config";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
|
||||
import Link from "next/link";
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<Page>
|
||||
<SEO
|
||||
title={`About Me - ${Config.AuthorName}`}
|
||||
description={"Type your brief self-introduction in a sentence here make SEO recognize it easily."}
|
||||
coverURL={Config.PageCovers.websiteCoverURL}
|
||||
description={"Type your brief self-introduction in a sentence here make SEO recognize it easily."}
|
||||
title={`About Me - ${Config.AuthorName}`}
|
||||
/>
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<h2 className={`my-5 flex justify-around text-2xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}>
|
||||
{"ABOUT ME"}
|
||||
</h2>
|
||||
<h2 className={`my-5 flex justify-around text-2xl font-bold font-fang-zheng-xiao-biao-song`}>{"ABOUT ME"}</h2>
|
||||
<Separator />
|
||||
<div className={`${fontSourceSerifScreenCN.className} my-5 justify-center md:flex md:space-x-10`}>
|
||||
<div className={`font-source-serif-screen my-5 justify-center md:flex md:space-x-10`}>
|
||||
<div className="my-auto flex md:w-1/3">
|
||||
<img alt="my-profile" className="mx-auto my-auto max-h-[23rem] rounded-lg" src="/images/profile.webp" />
|
||||
</div>
|
||||
@@ -46,7 +44,7 @@ export default function AboutPage() {
|
||||
{Config.SocialLinks.github && (
|
||||
<li className="my-2">
|
||||
{"📕 Check out my github profile at "}
|
||||
<Link target="_blank" className="underline" href={`https://github.com/${Config.SocialLinks.github}`}>
|
||||
<Link className="underline" href={`https://github.com/${Config.SocialLinks.github}`} target="_blank">
|
||||
Github
|
||||
</Link>
|
||||
</li>
|
||||
@@ -56,7 +54,7 @@ export default function AboutPage() {
|
||||
{Config.SocialLinks.twitter && (
|
||||
<li className="my-2">
|
||||
{"📫 How to reach me on Twitter: "}
|
||||
<Link target="_blank" className="link" href={`https://twitter.com/${Config.SocialLinks.twitter}`}>
|
||||
<Link className="link" href={`https://twitter.com/${Config.SocialLinks.twitter}`} target="_blank">
|
||||
{Config.SocialLinks.twitter}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ContentContainer, Page } from "@/components/layouts";
|
||||
import { MDXComponentsSet } from "@/components/mdx";
|
||||
import { BottomCard } from "@/components/readerpage/BottomCard";
|
||||
import { DrawerTOC } from "@/components/readerpage/DrawerTOC";
|
||||
import { PostComments } from "@/components/readerpage/PostComments";
|
||||
import { PostCover } from "@/components/readerpage/PostCover";
|
||||
@@ -13,9 +14,8 @@ import { SEO } from "@/components/utils/SEO";
|
||||
import { Config } from "@/data/config";
|
||||
import { normalizeDate } from "@/lib/date";
|
||||
import { getPostFileContent, sortedPosts } from "@/lib/post-process";
|
||||
import { getTOCTree } from "@/lib/toc";
|
||||
import { makeTOCTree } from "@/lib/toc";
|
||||
import useDrawerTOCState from "@/stores/useDrawerTOCState";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
import { TFrontmatter } from "@/types/frontmatter.type";
|
||||
import { TPostListItem } from "@/types/post-list";
|
||||
import { TTOCItem } from "@/types/toc.type";
|
||||
@@ -27,6 +27,7 @@ import Link from "next/link";
|
||||
import { renderToString } from "react-dom/server";
|
||||
import { useSwipeable } from "react-swipeable";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeHighlight from "rehype-highlight";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
import rehypePresetMinify from "rehype-preset-minify";
|
||||
import rehypeRaw from "rehype-raw";
|
||||
@@ -34,7 +35,6 @@ import rehypeSlug from "rehype-slug";
|
||||
import externalLinks from "remark-external-links";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
import remarkPrism from "remark-prism";
|
||||
|
||||
type ReaderPageProps = {
|
||||
compiledSource: MDXRemoteSerializeResult;
|
||||
@@ -51,7 +51,7 @@ const ReaderPage = (props: ReaderPageProps) => {
|
||||
|
||||
// Only the TOC length reaches 3 can be displayed.
|
||||
// In order to avoid large blank spaces that ruin the visual perception
|
||||
const isTOCLongEnough = props.tocList.length > 4;
|
||||
const isTOCLongEnough = props.tocList.length > 2;
|
||||
const handleRightSwipe = useSwipeable({
|
||||
onSwipedRight: () => {
|
||||
isTOCLongEnough && setIsTOCOpen(true);
|
||||
@@ -62,52 +62,55 @@ const ReaderPage = (props: ReaderPageProps) => {
|
||||
return (
|
||||
<Page>
|
||||
<SEO
|
||||
title={`${props.frontMatter.title} - ${Config.SiteTitle}`}
|
||||
description={props.frontMatter.summary}
|
||||
coverURL={props.frontMatter.coverURL ?? Config.AvatarURL}
|
||||
description={props.frontMatter.summary}
|
||||
title={`${props.frontMatter.title} - ${Config.SiteTitle}`}
|
||||
/>
|
||||
<Toaster />
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<div className="py-5 justify-center lg:flex" style={{ borderRadius: "5px" }}>
|
||||
<div
|
||||
className={`py-1 ${isTOCLongEnough ? "justify-between" : "justify-center"} lg:flex space-x-5`}
|
||||
style={{ borderRadius: "5px" }}
|
||||
>
|
||||
<div className={`${isTOCLongEnough ? "lg:w-2/3" : "lg:w-5/6"} py-5`}>
|
||||
<div className="typesetting">
|
||||
{props.frontMatter.coverURL && <PostCover coverURL={props.frontMatter.coverURL} />}
|
||||
<div
|
||||
className={`${fontFangZhengXiaoBiaoSongCN.className} my-5 text-black dark:text-white flex justify-center whitespace-normal break-words text-3xl font-bold capitalize`}
|
||||
>
|
||||
{props.frontMatter?.title}
|
||||
</div>
|
||||
{props.frontMatter?.subtitle && (
|
||||
<div className="pb-1 border-b-2 border-black dark:border-gray-300">
|
||||
<div
|
||||
className={`${fontFangZhengXiaoBiaoSongCN.className} my-1 flex justify-center text-xl font-bold capitalize`}
|
||||
className={`font-fang-zheng-xiao-biao-song my-2 text-black dark:text-white flex justify-center whitespace-normal break-words text-3xl font-bold capitalize`}
|
||||
>
|
||||
{props.frontMatter.subtitle}
|
||||
{props.frontMatter?.title}
|
||||
</div>
|
||||
)}
|
||||
<div className="my-2 flex justify-center text-sm italic">{normalizeDate(props.frontMatter?.time)}</div>
|
||||
{props.frontMatter?.summary && (
|
||||
<p className={`${fontSourceSerifScreenCN.className} my-4 indent-8 text-gray-800 dark:text-gray-300`}>
|
||||
{props.frontMatter?.summary}
|
||||
</p>
|
||||
)}
|
||||
{props.frontMatter.tags && (
|
||||
<div className={`py-3 flex flex-wrap justify-start border-t border-b`}>
|
||||
<div className="my-auto font-bold mr-2">{"TAGS: "}</div>
|
||||
{props.frontMatter.tags.map((tagName) => (
|
||||
<Link
|
||||
className="mx-1 my-auto text-gray-700 underline-offset-4 hover:text-black dark:text-gray-300 dark:hover:text-white font-bold text-sm"
|
||||
href={`/tags/${tagName}`}
|
||||
key={`tags-${nanoid()}`}
|
||||
>
|
||||
{tagName}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.frontMatter?.subtitle && (
|
||||
<div
|
||||
className={`font-fang-zheng-xiao-biao-song my-1 flex justify-center text-xl font-bold capitalize`}
|
||||
>
|
||||
{props.frontMatter.subtitle}
|
||||
</div>
|
||||
)}
|
||||
<div className="my-1 flex justify-center text-sm italic">{normalizeDate(props.frontMatter?.time)}</div>
|
||||
{props.frontMatter?.summary && (
|
||||
<p className={"font-source-serif-screen my-4 indent-8 text-gray-800 dark:text-gray-300"}>
|
||||
{props.frontMatter?.summary}
|
||||
</p>
|
||||
)}
|
||||
{props.frontMatter.tags && (
|
||||
<div className={"pt-1 flex flex-wrap border-t-2 border-black dark:border-gray-300"}>
|
||||
{props.frontMatter.tags.map((tagName) => (
|
||||
<Link
|
||||
className="not-prose mr-2 px-2 py-1 font-bold border-2 border-black dark:border-gray-300 my-1 text-gray-700 hover:text-black text-xs dark:text-gray-300 dark:hover:text-gray-200"
|
||||
href={`/tags/${tagName}`}
|
||||
key={`tags-${nanoid()}`}
|
||||
>
|
||||
{tagName}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className={`py-5 ${fontSourceSerifScreenCN.className} ${
|
||||
className={`text-wrap border-gray-500 font-source-serif-screen ${
|
||||
!props.frontMatter.allowShare ? "select-none" : ""
|
||||
}`}
|
||||
{...handleRightSwipe}
|
||||
@@ -115,21 +118,23 @@ const ReaderPage = (props: ReaderPageProps) => {
|
||||
{compiledSource && (
|
||||
<MDXRemote
|
||||
compiledSource={compiledSource.compiledSource}
|
||||
// @ts-ignore
|
||||
components={MDXComponentsSet}
|
||||
frontmatter={compiledSource.frontmatter}
|
||||
scope={compiledSource.scope}
|
||||
//@ts-ignore
|
||||
components={MDXComponentsSet}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Separator />
|
||||
<BottomCard />
|
||||
<Separator />
|
||||
<ShareButtons
|
||||
allowShare={props.frontMatter.allowShare}
|
||||
postId={props.postId}
|
||||
quote={props.frontMatter.summary}
|
||||
subtitle={props.frontMatter.subtitle}
|
||||
title={props.frontMatter.title}
|
||||
quote={props.frontMatter.summary}
|
||||
postId={props.postId}
|
||||
allowShare={props.frontMatter.allowShare}
|
||||
/>
|
||||
<Separator />
|
||||
<ul className="my-5 px-5 flex flex-col justify-center list-disc">
|
||||
@@ -158,7 +163,9 @@ const ReaderPage = (props: ReaderPageProps) => {
|
||||
</div>
|
||||
{isTOCLongEnough && (
|
||||
<div className="hidden lg:block md:w-1/3 py-5">
|
||||
<TOC data={props.tocList} />
|
||||
<div className="sticky top-[5em]">
|
||||
<TOC data={props.tocList} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -199,13 +206,20 @@ export const getStaticProps: GetStaticProps<ReaderPageProps> = async (context) =
|
||||
const mdxSource = await serialize(source, {
|
||||
parseFrontmatter: true,
|
||||
mdxOptions: {
|
||||
remarkPlugins: [remarkPrism, externalLinks, remarkMath, remarkGfm],
|
||||
rehypePlugins: [rehypeRaw, rehypeKatex as any, rehypeAutolinkHeadings, rehypeSlug, rehypePresetMinify],
|
||||
remarkPlugins: [externalLinks, remarkMath, remarkGfm],
|
||||
rehypePlugins: [
|
||||
rehypeRaw,
|
||||
rehypeKatex as any,
|
||||
rehypeAutolinkHeadings,
|
||||
rehypeSlug,
|
||||
rehypePresetMinify.plugins,
|
||||
() => rehypeHighlight({ detect: true }),
|
||||
],
|
||||
format: "md",
|
||||
},
|
||||
});
|
||||
|
||||
const tocList = getTOCTree(renderToString(<MDXRemote {...mdxSource} />));
|
||||
const tocList = makeTOCTree(renderToString(<MDXRemote {...mdxSource} />));
|
||||
|
||||
const postIndexInAllPosts = sortedPosts.allPostList.findIndex((item) => item.id === postId);
|
||||
|
||||
|
||||
@@ -5,21 +5,18 @@ import { NavBar } from "@/components/utils/NavBar";
|
||||
import { SEO } from "@/components/utils/SEO";
|
||||
import { Config } from "@/data/config";
|
||||
import { FriendsList } from "@/data/friends";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
import { nanoid } from "nanoid";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function FriendsPage() {
|
||||
return (
|
||||
<Page>
|
||||
<SEO title={`${Config.SiteTitle} - Friends`} description={"My Friend Links"} />
|
||||
<SEO description={"My Friend Links"} title={`${Config.SiteTitle} - Friends`} />
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}>
|
||||
{"FRIENDS"}
|
||||
</h2>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold font-fang-zheng-xiao-biao-song`}>{"FRIENDS"}</h2>
|
||||
<Separator />
|
||||
<div className={`my-5 flex flex-wrap justify-center text-2xl ${fontSourceSerifScreenCN.className}`}>
|
||||
<div className={`my-5 flex flex-wrap justify-center text-2xl font-source-serif-screen`}>
|
||||
{FriendsList.map((item) => (
|
||||
<Link className="mx-2 p-2 underline" href={item.url} key={nanoid()}>
|
||||
{item.title}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { LatestPostCountInHomePage } from "@/consts/consts";
|
||||
import { Config } from "@/data/config";
|
||||
import { sortedPosts } from "@/lib/post-process";
|
||||
import { generateRSSFeed } from "@/lib/rss";
|
||||
import { fontFangZhengXiaoBiaoSongCN } from "@/styles/font";
|
||||
import { TPostListItem } from "@/types/post-list";
|
||||
import { GetStaticProps } from "next";
|
||||
import Link from "next/link";
|
||||
@@ -26,9 +25,9 @@ export default function Home(props: HomePageProps) {
|
||||
return (
|
||||
<Page>
|
||||
<SEO
|
||||
title={`${Config.SiteTitle} - The personal blog for ${Config.Nickname}`}
|
||||
description={`Welcome to the ${Config.Nickname}'s blog website. It's the website for recording thoughts for technology, life experience and so on.`}
|
||||
coverURL={Config.PageCovers.websiteCoverURL}
|
||||
description={`Welcome to the ${Config.Nickname}'s blog website. It's the website for recording thoughts for technology, life experience and so on.`}
|
||||
title={`${Config.SiteTitle} - The personal blog for ${Config.Nickname}`}
|
||||
/>
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
@@ -36,7 +35,7 @@ export default function Home(props: HomePageProps) {
|
||||
{props.pinnedPostList.length !== 0 && (
|
||||
<div>
|
||||
<Separator />
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold font-fang-zheng-xiao-biao-song`}>
|
||||
<RiStarFill className="mx-2 my-auto" />
|
||||
{"PINNED POSTS"}
|
||||
</h2>
|
||||
@@ -47,7 +46,7 @@ export default function Home(props: HomePageProps) {
|
||||
{props.latestPostList.length !== 0 && (
|
||||
<div>
|
||||
<Separator />
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold font-fang-zheng-xiao-biao-song`}>
|
||||
<LuPenTool className="mx-2 my-auto" />
|
||||
{"LATEST POSTS"}
|
||||
</h2>
|
||||
@@ -56,7 +55,7 @@ export default function Home(props: HomePageProps) {
|
||||
<Separator />
|
||||
<div className="my-5 flex justify-end">
|
||||
<Button asChild>
|
||||
<Link href="/posts" className="font-bold">
|
||||
<Link className="font-bold" href="/posts">
|
||||
{"MORE POSTS >"}
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ContentContainer, Page } from "@/components/layouts";
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
@@ -10,7 +11,6 @@ import { PostCountPerPagination } from "@/consts/consts";
|
||||
import { Config } from "@/data/config";
|
||||
import { sortedPosts } from "@/lib/post-process";
|
||||
import { isEmptyArray, paginateArray } from "@/lib/utils";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
import { TPostListItem } from "@/types/post-list";
|
||||
import { nanoid } from "nanoid";
|
||||
import { GetStaticPaths, GetStaticProps } from "next";
|
||||
@@ -49,31 +49,36 @@ export default function PostsPage(props: PostsPageProps) {
|
||||
return (
|
||||
<Page>
|
||||
<SEO
|
||||
title={`${Config.SiteTitle} - All published posts`}
|
||||
description={"Here is the list page for all published posts. Click here for more details."}
|
||||
coverURL={Config.PageCovers.websiteCoverURL}
|
||||
description={"Here is the list page for all published posts. Click here for more details."}
|
||||
title={`${Config.SiteTitle} - All published posts`}
|
||||
/>
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<h2 className={`my-5 flex justify-center text-2xl ${fontFangZhengXiaoBiaoSongCN.className} font-bold`}>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-fang-zheng-xiao-biao-song font-bold`}>
|
||||
<LuPenTool className="mx-2 my-auto" />
|
||||
{"ALL POSTS"}
|
||||
</h2>
|
||||
{!isEmptyArray(props.tagList) && props.pageNumber === 1 && (
|
||||
<>
|
||||
<Separator />
|
||||
<div className={`my-5 flex flex-wrap text-sm justify-center px-2 ${fontSourceSerifScreenCN.className}`}>
|
||||
{props.tagList.map((item) => (
|
||||
<Link
|
||||
className="m-1 p-1 underline underline-offset-[5px] my-auto text-gray-700 hover:text-black dark:text-gray-300 dark:hover:text-white font-bold"
|
||||
href={`/tags/${item.name}`}
|
||||
key={`tags-${nanoid()}`}
|
||||
>
|
||||
{`${item.name} (${item.count})`}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
{!isEmptyArray(props.tagList) && (
|
||||
<Accordion collapsible type="single">
|
||||
<AccordionItem className="border-t" value="item-1">
|
||||
<AccordionTrigger className="hover:no-underline font-bold">{"TAG FILTER"}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Separator />
|
||||
<div className={`my-5 flex flex-wrap text-wrap text-sm justify-center px-2`}>
|
||||
{props.tagList.map((item) => (
|
||||
<Link
|
||||
className="m-1 p-1 underline underline-offset-[5px] my-auto text-gray-700 decoration-2 hover:text-black dark:text-gray-300 dark:hover:text-white font-bold"
|
||||
href={`/tags/${item.name}`}
|
||||
key={`tags-${nanoid()}`}
|
||||
>
|
||||
{`${item.name} (${item.count})`}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)}
|
||||
<Separator />
|
||||
<PostList data={props.postList} />
|
||||
@@ -81,23 +86,24 @@ export default function PostsPage(props: PostsPageProps) {
|
||||
<div className="my-5 flex justify-between text-base font-bold">
|
||||
{props.pageNumber !== 1 && (
|
||||
<Button asChild>
|
||||
<Link href={`/posts/${props.pageNumber - 1}/`} className="font-bold">
|
||||
<Link className="font-bold" href={`/posts/${props.pageNumber - 1}/`}>
|
||||
{"< PREV"}
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
<div className="my-auto font-bold flex justify-center">
|
||||
<Input
|
||||
onKeyDown={handleEnterKeyJump}
|
||||
onChange={handleInputPageNumber}
|
||||
className="my-auto mx-2 w-11 h-6"
|
||||
onChange={handleInputPageNumber}
|
||||
onKeyDown={handleEnterKeyJump}
|
||||
title="Type the specified page number and press Enter to jump."
|
||||
value={pageNumber}
|
||||
/>
|
||||
<div className="my-auto">{` / ${props.pageAmount}`}</div>
|
||||
</div>
|
||||
{props.pageNumber !== props.pageAmount && (
|
||||
<Button asChild>
|
||||
<Link href={`/posts/${props.pageNumber + 1}/`} className="font-bold">
|
||||
<Link className="font-bold" href={`/posts/${props.pageNumber + 1}/`}>
|
||||
{"NEXT >"}
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -133,10 +139,12 @@ export const getStaticProps: GetStaticProps<PostsPageProps> = async (context) =>
|
||||
const tagList: {
|
||||
name: string;
|
||||
count: number;
|
||||
}[] = Object.keys(sortedPosts.tagSubPostSet).map((tagName) => ({
|
||||
name: tagName,
|
||||
count: sortedPosts.tagSubPostSet[tagName].length,
|
||||
}));
|
||||
}[] = Object.keys(sortedPosts.postsByTag)
|
||||
.map((tagName) => ({
|
||||
name: tagName,
|
||||
count: sortedPosts.postsByTag[tagName].length,
|
||||
}))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
||||
@@ -8,7 +8,6 @@ import { NavBar } from "@/components/utils/NavBar";
|
||||
import { SEO } from "@/components/utils/SEO";
|
||||
import { Config } from "@/data/config";
|
||||
import { isEmptyString } from "@/lib/utils";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
import { TSearchResultItem } from "@/types/search-result";
|
||||
import axios from "axios";
|
||||
import { nanoid } from "nanoid";
|
||||
@@ -61,35 +60,35 @@ export default function SearchPage() {
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<SEO title={`${Config.SiteTitle} - Search`} description={"Search the posts on your demand."} />
|
||||
<SEO description={"Search the posts on your demand."} title={`${Config.SiteTitle} - Search`} />
|
||||
<Toaster />
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<h2 className={`my-10 flex justify-center text-2xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}>
|
||||
<h2 className={`my-10 flex justify-center text-2xl font-bold font-fang-zheng-xiao-biao-song`}>
|
||||
{"SEARCH POSTS"}
|
||||
</h2>
|
||||
<div className="flex my-10 h-1/2">
|
||||
<div className="flex my-10">
|
||||
<Input
|
||||
className="my-auto py-0"
|
||||
onChange={handleInputSearchText}
|
||||
onKeyDown={handleEnterKeySearch}
|
||||
placeholder="Input the keyword"
|
||||
value={searchText}
|
||||
onKeyDown={handleEnterKeySearch}
|
||||
onChange={handleInputSearchText}
|
||||
/>
|
||||
<Button className="mx-3 w-32 my-auto" disabled={querySearch.isLoading} onClick={handleMakeSearch}>
|
||||
{querySearch.isFetching ? "Loading" : "Search"}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-col justify-center">
|
||||
<div className={`min-h-full flex flex-col ${fontSourceSerifScreenCN.className}`}>
|
||||
<div className={`min-h-full flex flex-col font-source-serif-screen`}>
|
||||
{querySearch.isSuccess &&
|
||||
searchResult.map((item, index) => (
|
||||
<Link
|
||||
className={`py-2 px-5 border-t ${
|
||||
index === searchResult.length - 1 && "border-b"
|
||||
} hover:bg-gray-50 dark:hover:bg-gray-900 flex flex-col`}
|
||||
key={nanoid()}
|
||||
href={`/blog/${item.id}`}
|
||||
key={nanoid()}
|
||||
target="_blank"
|
||||
>
|
||||
<div className="my-1 capitalize">{item.title}</div>
|
||||
|
||||
@@ -1,120 +1,35 @@
|
||||
import { ContentContainer, Page } from "@/components/layouts";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { SponsorBoard } from "@/components/sponsor-page/SponsorBoard";
|
||||
import { SponsorDescription } from "@/components/sponsor-page/SponsorDescription";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import { Footer } from "@/components/utils/Footer";
|
||||
import { NavBar } from "@/components/utils/NavBar";
|
||||
import { SEO } from "@/components/utils/SEO";
|
||||
import { Config } from "@/data/config";
|
||||
import { isEmptyString } from "@/lib/utils";
|
||||
import { fontFangZhengXiaoBiaoSongCN, fontSourceSerifScreenCN } from "@/styles/font";
|
||||
import Link from "next/link";
|
||||
import { QRCodeSVG } from "qrcode.react";
|
||||
import { FaCcPaypal } from "react-icons/fa";
|
||||
import { GoHeartFill } from "react-icons/go";
|
||||
import { SiAlipay, SiPatreon, SiWechat } from "react-icons/si";
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<Page>
|
||||
<SEO
|
||||
title={`${Config.SiteTitle} - Sponsor Me`}
|
||||
description={
|
||||
"If you like my works, I would deeply appreciate your support as a patron. Your contribution not only fuels my creative journey but also allows me to delve deeper into my passion."
|
||||
}
|
||||
title={`${Config.SiteTitle} - Sponsor Me`}
|
||||
/>
|
||||
<Toaster />
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<div className="md:flex">
|
||||
<div className="md:flex mt-10">
|
||||
<div className="flex flex-col justify-center md:w-1/2">
|
||||
<h2
|
||||
className={`my-5 flex justify-center text-2xl font-bold text-red-500 ${fontFangZhengXiaoBiaoSongCN.className}`}
|
||||
>
|
||||
<h2 className={`my-5 flex justify-center text-2xl font-bold text-red-500 font-fang-zheng-xiao-biao-song`}>
|
||||
<GoHeartFill className="mx-2 my-auto" />
|
||||
{"SPONSOR"}
|
||||
</h2>
|
||||
<p className={`${fontSourceSerifScreenCN.className} break-words text-lg`}>
|
||||
{
|
||||
"If you like my works, I would deeply appreciate your support as a patron. Your contribution not only fuels my creative journey but also allows me to delve deeper into my passion. Your support plays a vital role in making this vision a reality. Thank you for considering becoming a patron and being an integral part of this work endeavor."
|
||||
}
|
||||
<br />
|
||||
<br />
|
||||
{"Here are the ways you can become a patron. Thank you for your support!"}
|
||||
<br />
|
||||
<br />
|
||||
{`Yours, ${Config.AuthorName}`}
|
||||
</p>
|
||||
<SponsorDescription />
|
||||
</div>
|
||||
<div className="md:px-15 md:w-1/2">
|
||||
<div className="mx-2 my-10 flex flex-col justify-around font-bold">
|
||||
{!isEmptyString(Config.Sponsor?.WechatPayQRCodeContent) && (
|
||||
<div className="my-3 flex justify-between">
|
||||
<div className="my-auto flex">
|
||||
<SiWechat className="mx-3 my-auto text-4xl text-green-500" />
|
||||
<div className="my-auto">
|
||||
<h3 className="mx-auto text-sm">{"WECHAT-PAY"}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="my-2 bg-white p-1">
|
||||
<QRCodeSVG width={100} height={100} value={Config.Sponsor?.WechatPayQRCodeContent!} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Separator />
|
||||
{!isEmptyString(Config.Sponsor?.AlipayLink) && (
|
||||
<div className="my-6 flex justify-between">
|
||||
<div className="my-auto flex">
|
||||
<SiAlipay className="mx-3 my-auto text-4xl text-blue-500" />
|
||||
<div className="my-auto">
|
||||
<h3 className="mx-auto text-sm">{"ALIPAY"}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="my-2">
|
||||
<Button className="my-auto" asChild>
|
||||
<Link target="_blank" href={Config.Sponsor?.AlipayLink!}>
|
||||
{"DONATE"}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Separator />
|
||||
{!isEmptyString(Config.Sponsor?.PaypalId) && (
|
||||
<div className="my-6 flex justify-between">
|
||||
<div className="my-auto flex">
|
||||
<FaCcPaypal className="mx-3 my-auto text-4xl text-blue-600" />
|
||||
<div className="my-auto">
|
||||
<h3 className="mx-auto text-sm">{"PAYPAL"}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="my-2">
|
||||
<Button className="my-auto" asChild>
|
||||
<Link target="_blank" href={`https://paypal.me/${Config.Sponsor?.PaypalId}`}>
|
||||
{"DONATE"}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Separator />
|
||||
{!isEmptyString(Config.Sponsor?.PatreonId) && (
|
||||
<div className="my-6 flex justify-between">
|
||||
<div className="my-auto flex">
|
||||
<SiPatreon className="mx-3 my-auto text-4xl text-gray-500" />
|
||||
<div className="my-auto">
|
||||
<h3 className="mx-auto text-sm">{"PATREON"}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="my-2">
|
||||
<Button className="my-auto" asChild>
|
||||
<Link target="_blank" href={`https://patreon.com/${Config.Sponsor?.PatreonId}`}>
|
||||
{"DONATE"}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Separator />
|
||||
</div>
|
||||
<SponsorBoard />
|
||||
</div>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
|
||||
@@ -10,7 +10,6 @@ import { PostCountPerPagination } from "@/consts/consts";
|
||||
import { Config } from "@/data/config";
|
||||
import { sortedPosts } from "@/lib/post-process";
|
||||
import { paginateArray } from "@/lib/utils";
|
||||
import { fontFangZhengXiaoBiaoSongCN } from "@/styles/font";
|
||||
import { TPostListItem } from "@/types/post-list";
|
||||
import { GetStaticPaths, GetStaticProps } from "next";
|
||||
import Link from "next/link";
|
||||
@@ -47,16 +46,14 @@ export default function TagsContentPage(props: TagsContentPageProps) {
|
||||
return (
|
||||
<Page>
|
||||
<SEO
|
||||
title={`Tag - ${props.tagName}`}
|
||||
description={`Here are posts under the tag ${props.tagName}.`}
|
||||
coverURL={Config.PageCovers.websiteCoverURL}
|
||||
description={`Here are posts under the tag ${props.tagName}.`}
|
||||
title={`Tag - ${props.tagName}`}
|
||||
/>
|
||||
<NavBar />
|
||||
<ContentContainer>
|
||||
<h2
|
||||
className={`my-5 flex flex-col justify-center text-center text-3xl font-bold ${fontFangZhengXiaoBiaoSongCN.className}`}
|
||||
>
|
||||
{`Posts of ${props.tagName}`}
|
||||
<h2 className={"my-5 flex flex-col justify-center text-center font-bold font-fang-zheng-xiao-biao-song"}>
|
||||
<div className="mx-auto text-2xl">{`Posts of ${props.tagName}`}</div>
|
||||
</h2>
|
||||
<Separator />
|
||||
<PostList data={props.postList} />
|
||||
@@ -64,23 +61,24 @@ export default function TagsContentPage(props: TagsContentPageProps) {
|
||||
<div className="my-5 flex justify-between text-base font-bold">
|
||||
{props.pageNumber !== 1 && (
|
||||
<Button asChild>
|
||||
<Link href={`/tags/${props.tagName}/${props.pageNumber - 1}/`} className="font-bold">
|
||||
<Link className="font-bold" href={`/tags/${props.tagName}/${props.pageNumber - 1}/`}>
|
||||
{"< PREV"}
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
<div className="my-auto font-bold flex justify-center">
|
||||
<Input
|
||||
onKeyDown={handleEnterKeyJump}
|
||||
onChange={handleInputPageNumber}
|
||||
className="my-auto mx-2 w-11 h-6"
|
||||
onChange={handleInputPageNumber}
|
||||
onKeyDown={handleEnterKeyJump}
|
||||
title="Type the specified page number and press Enter to jump."
|
||||
value={pageNumber}
|
||||
/>
|
||||
<div className="my-auto">{` / ${props.pageAmount}`}</div>
|
||||
</div>
|
||||
{props.pageNumber !== props.pageAmount && (
|
||||
<Button asChild>
|
||||
<Link href={`/tags/${props.tagName}/${props.pageNumber + 1}/`} className="font-bold">
|
||||
<Link className="font-bold" href={`/tags/${props.tagName}/${props.pageNumber + 1}/`}>
|
||||
{"NEXT >"}
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -95,9 +93,9 @@ export default function TagsContentPage(props: TagsContentPageProps) {
|
||||
export const getStaticPaths: GetStaticPaths = () => {
|
||||
const allPaths: { params: { slug: string[] } }[] = [];
|
||||
|
||||
const allTags = Object.keys(sortedPosts.tagSubPostSet).map((tagName) => ({
|
||||
const allTags = Object.keys(sortedPosts.postsByTag).map((tagName) => ({
|
||||
name: tagName,
|
||||
count: sortedPosts.tagSubPostSet[tagName].length,
|
||||
count: sortedPosts.postsByTag[tagName].length,
|
||||
}));
|
||||
|
||||
for (let i = 0; i < allTags.length; i++) {
|
||||
@@ -117,9 +115,9 @@ export const getStaticProps: GetStaticProps<TagsContentPageProps> = async (conte
|
||||
const pageNumber = params[1] ? parseInt(params[1]) : 1;
|
||||
let postList: TPostListItem[] = [];
|
||||
|
||||
postList = paginateArray(sortedPosts.tagSubPostSet[tagName], PostCountPerPagination, pageNumber);
|
||||
postList = paginateArray(sortedPosts.postsByTag[tagName], PostCountPerPagination, pageNumber);
|
||||
|
||||
const pageAmount = Math.ceil(sortedPosts.tagSubPostSet[tagName].length / PostCountPerPagination);
|
||||
const pageAmount = Math.ceil(sortedPosts.postsByTag[tagName].length / PostCountPerPagination);
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
||||
Reference in New Issue
Block a user