[update] migrate the project formatter from prettier and eslint to biome
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["next/core-web-vitals"],
|
|
||||||
"rules": {
|
|
||||||
"@next/next/no-img-element": "off",
|
|
||||||
"react/jsx-uses-vars": "error",
|
|
||||||
"react/jsx-sort-props": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
*.woff2
|
|
||||||
*.woff2
|
|
||||||
*.ttf
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 120,
|
|
||||||
"endOfLine": "auto",
|
|
||||||
"trailingComma": "all",
|
|
||||||
"plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-organize-imports", "react"]
|
|
||||||
}
|
|
||||||
39
biome.json
Normal file
39
biome.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
|
||||||
|
"files": {
|
||||||
|
"ignore": [".next", "VSCodeCounter", ".turbo", "node_modules"]
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"indentStyle": "space",
|
||||||
|
"lineWidth": 120
|
||||||
|
},
|
||||||
|
"organizeImports": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"a11y": {
|
||||||
|
"useKeyWithClickEvents": "off"
|
||||||
|
},
|
||||||
|
"complexity": {
|
||||||
|
"noForEach": "off"
|
||||||
|
},
|
||||||
|
"correctness": {
|
||||||
|
"useExhaustiveDependencies": "off"
|
||||||
|
},
|
||||||
|
"suspicious": {
|
||||||
|
"noExplicitAny": "off"
|
||||||
|
},
|
||||||
|
"style": {
|
||||||
|
"noParameterAssign": "off",
|
||||||
|
"noNonNullAssertion": "off",
|
||||||
|
"useNodejsImportProtocol": "off"
|
||||||
|
},
|
||||||
|
"nursery": {
|
||||||
|
"useSortedClasses": "error"
|
||||||
|
},
|
||||||
|
"recommended": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ export const HomeCover = () => {
|
|||||||
<>
|
<>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div
|
<div
|
||||||
className="mb-20 mt-5 flex w-full justify-center rounded-xl"
|
className="mt-5 mb-20 flex w-full justify-center rounded-xl"
|
||||||
style={{
|
style={{
|
||||||
aspectRatio: "4/1",
|
aspectRatio: "4/1",
|
||||||
background: `url(${Config.PageCovers.websiteCoverURL})`,
|
background: `url(${Config.PageCovers.websiteCoverURL})`,
|
||||||
@@ -20,10 +20,10 @@ export const HomeCover = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`caption-font my-8 text-center text-4xl font-bold`}>{Config.Nickname}</div>
|
<div className={"caption-font my-8 text-center font-bold text-4xl"}>{Config.Nickname}</div>
|
||||||
{Config.Sentence && (
|
{Config.Sentence && (
|
||||||
<div className="my-5 flex justify-center">
|
<div className="my-5 flex justify-center">
|
||||||
<p className={`content-font text-lg`}>{Config.Sentence}</p>
|
<p className={"text-lg content-font"}>{Config.Sentence}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="my-8">
|
<div className="my-8">
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ export const Page = ({ children }: { children: React.ReactNode }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ContentContainer = ({ children }: { children: React.ReactNode }) => {
|
export const ContentContainer = ({ children }: { children: React.ReactNode }) => {
|
||||||
return <main className="px-5 md:px-10 lg:px-20 xl:px-32 2xl:px-52 flex-grow">{children}</main>;
|
return <main className="flex-grow px-5 md:px-10 lg:px-20 xl:px-32 2xl:px-52">{children}</main>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const Blockquote = (props: JSX.IntrinsicElements["blockquote"]) => {
|
|||||||
return (
|
return (
|
||||||
<blockquote
|
<blockquote
|
||||||
className={
|
className={
|
||||||
"not-prose scroll-mt-20 my-5 px-5 py-4 bg-gray-100 dark:bg-gray-800 dark:border-gray-700 border-gray-300 border-l-4"
|
"not-prose my-5 scroll-mt-20 border-gray-300 border-l-4 bg-gray-100 px-5 py-4 dark:border-gray-700 dark:bg-gray-800"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const H2 = (props: JSX.IntrinsicElements["h2"]) => {
|
const H2 = (props: JSX.IntrinsicElements["h2"]) => {
|
||||||
return (
|
return (
|
||||||
<h2 className={`caption-font scroll-mt-20`} id={props.id}>
|
<h2 className={"caption-font scroll-mt-20"} id={props.id}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</h2>
|
</h2>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
// but all the attributes of the img tag.
|
// but all the attributes of the img tag.
|
||||||
const ImageWrapper = (props: JSX.IntrinsicElements["img"]) => {
|
const ImageWrapper = (props: JSX.IntrinsicElements["img"]) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col my-5">
|
<div className="my-5 flex flex-col">
|
||||||
<img alt={props.alt} className="mx-auto my-0" src={props.src} />
|
<img alt={props.alt} className="mx-auto my-0" src={props.src} />
|
||||||
<div className="mx-auto my-1 text-sm text-gray-500 dark:text-gray-300">{props.alt}</div>
|
<div className="mx-auto my-1 text-gray-500 text-sm dark:text-gray-300">{props.alt}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const PreWrapper = ({ children }: { children: JSX.Element }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative flat-scrollbar-normal"
|
className="flat-scrollbar-normal relative"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
onMouseLeave={onExit}
|
onMouseLeave={onExit}
|
||||||
onMouseMove={onEnter}
|
onMouseMove={onEnter}
|
||||||
@@ -32,14 +32,14 @@ const PreWrapper = ({ children }: { children: JSX.Element }) => {
|
|||||||
{hovered && (
|
{hovered && (
|
||||||
<Button
|
<Button
|
||||||
aria-label="Copy code"
|
aria-label="Copy code"
|
||||||
className={`absolute right-2 top-2 h-8 w-8 rounded p-1 ${copied ? "hover:text-green-500 text-green-500" : ""}`}
|
className={`absolute top-2 right-2 h-8 w-8 rounded p-1 ${copied ? "text-green-500 hover:text-green-500" : ""}`}
|
||||||
onClick={onCopy}
|
onClick={onCopy}
|
||||||
variant={"outline"}
|
variant={"outline"}
|
||||||
>
|
>
|
||||||
{copied ? <FaCheck /> : <IoCopyOutline />}
|
{copied ? <FaCheck /> : <IoCopyOutline />}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<pre className="p-2 dark:bg-[#0d1117] bg-[#F6F8FA] rounded-md flat-scrollbar-normal not-prose text-sm dark:selection:bg-gray-700 selection:bg-gray-300 selection:text-inherit">
|
<pre className="flat-scrollbar-normal not-prose rounded-md bg-[#F6F8FA] p-2 text-sm selection:bg-gray-300 selection:text-inherit dark:bg-[#0d1117] dark:selection:bg-gray-700">
|
||||||
{children}
|
{children}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const TableWrapper = ({ children }: { children: React.ReactNode }) => {
|
const TableWrapper = ({ children }: { children: React.ReactNode }) => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-x-auto flat-scrollbar-normal">
|
<div className="flat-scrollbar-normal w-full overflow-x-auto">
|
||||||
<table>{children}</table>
|
<table>{children}</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { Config } from "@/data/config";
|
|||||||
|
|
||||||
export const BottomCard = () => {
|
export const BottomCard = () => {
|
||||||
return (
|
return (
|
||||||
<div className="p-8 w-full flex flex-col justify-center">
|
<div className="flex w-full flex-col justify-center p-8">
|
||||||
<img alt={Config.AuthorName} className="h-24 w-24 rounded-full mx-auto" src={Config.AvatarURL} />
|
<img alt={Config.AuthorName} className="mx-auto h-24 w-24 rounded-full" src={Config.AvatarURL} />
|
||||||
<p className="mx-auto mt-5 content-font">{Config.Sentence}</p>
|
<p className="mx-auto mt-5 content-font">{Config.Sentence}</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
|
||||||
import { useActiveHeading } from "@/hooks/useActiveHeading";
|
import { useActiveHeading } from "@/hooks/useActiveHeading";
|
||||||
import useDrawerTOCState from "@/stores/useDrawerTOCState";
|
import useDrawerTOCState from "@/stores/useDrawerTOCState";
|
||||||
import { TTOCItem } from "@/types/toc.type";
|
import type { TTOCItem } from "@/types/toc.type";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { MdMenuBook } from "react-icons/md";
|
import { MdMenuBook } from "react-icons/md";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
@@ -13,7 +13,7 @@ export const DrawerTOC = (props: { data: TTOCItem[] }) => {
|
|||||||
return (
|
return (
|
||||||
<Sheet onOpenChange={setIsTOCOpen} open={isTOCOpen}>
|
<Sheet onOpenChange={setIsTOCOpen} open={isTOCOpen}>
|
||||||
<SheetTrigger
|
<SheetTrigger
|
||||||
className="bottom-16 right-5 fixed bg-white dark:bg-black border-gray-700 border dark:border-gray-500 shadow-xl"
|
className="fixed right-5 bottom-16 border border-gray-700 bg-white shadow-xl dark:border-gray-500 dark:bg-black"
|
||||||
title="Open the table of contents"
|
title="Open the table of contents"
|
||||||
>
|
>
|
||||||
<div className="p-1 font-bold" onClick={() => setIsTOCOpen(!isTOCOpen)} title="Open the table of contents">
|
<div className="p-1 font-bold" onClick={() => setIsTOCOpen(!isTOCOpen)} title="Open the table of contents">
|
||||||
@@ -24,12 +24,12 @@ export const DrawerTOC = (props: { data: TTOCItem[] }) => {
|
|||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
<SheetTitle className="mt-8 font-bold">{"TABLE OF CONTENTS"}</SheetTitle>
|
<SheetTitle className="mt-8 font-bold">{"TABLE OF CONTENTS"}</SheetTitle>
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
<ul className="my-3 flat-scrollbar h-[70vh] flex flex-col overflow-y-auto flat-scrollbar-normal">
|
<ul className="flat-scrollbar flat-scrollbar-normal my-3 flex h-[70vh] flex-col overflow-y-auto">
|
||||||
{props.data?.map((item) => (
|
{props.data?.map((item) => (
|
||||||
<Link
|
<Link
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
"border-t border-b py-1 px-2 border-dashed hover:bg-gray-100 hover:dark:bg-gray-900",
|
"border-t border-b border-dashed px-2 py-1 hover:bg-gray-100 hover:dark:bg-gray-900",
|
||||||
activeId === `#${item.anchorId}` ? "bg-gray-100 dark:bg-gray-900 text-sky-700 dark:text-sky-500" : "",
|
activeId === `#${item.anchorId}` ? "bg-gray-100 text-sky-700 dark:bg-gray-900 dark:text-sky-500" : "",
|
||||||
)}
|
)}
|
||||||
href={`#${item.anchorId}`}
|
href={`#${item.anchorId}`}
|
||||||
key={`drawer-toc-${item.anchorId}`}
|
key={`drawer-toc-${item.anchorId}`}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export const PostCover = (props: { coverURL: string }) => {
|
export const PostCover = (props: { coverURL: string }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="mb-8 mt-0 flex w-full justify-center rounded-md"
|
className="mt-0 mb-8 flex w-full justify-center rounded-md"
|
||||||
style={{
|
style={{
|
||||||
aspectRatio: "5/2",
|
aspectRatio: "5/2",
|
||||||
background: `url(${props.coverURL})`,
|
background: `url(${props.coverURL})`,
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ export const ShareButtons = (props: {
|
|||||||
}'s Blog ${postURL}`;
|
}'s Blog ${postURL}`;
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
return (
|
return (
|
||||||
<div className="py-3 flex justify-center space-x-4 text-2xl">
|
<div className="flex justify-center space-x-4 py-3 text-2xl">
|
||||||
{props.allowShare != false ? (
|
{props.allowShare !== false ? (
|
||||||
<>
|
<>
|
||||||
<FacebookShareButton className="mx-2" quote={props.quote ?? props.title} url={postURL}>
|
<FacebookShareButton className="mx-2" quote={props.quote ?? props.title} url={postURL}>
|
||||||
<FaFacebook className="hover:text-blue-500" title="Share to Facebook" />
|
<FaFacebook className="hover:text-blue-500" title="Share to Facebook" />
|
||||||
@@ -39,13 +39,13 @@ export const ShareButtons = (props: {
|
|||||||
text={copyShareText}
|
text={copyShareText}
|
||||||
>
|
>
|
||||||
<FaLink
|
<FaLink
|
||||||
className="hover:text-gray-500 mx-2 cursor-pointer"
|
className="mx-2 cursor-pointer hover:text-gray-500"
|
||||||
title="Share with the post url and description"
|
title="Share with the post url and description"
|
||||||
/>
|
/>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="my-auto text-sm font-bold">{"SHARING IS NOT ALLOWED"}</div>
|
<div className="my-auto font-bold text-sm">{"SHARING IS NOT ALLOWED"}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useActiveHeading } from "@/hooks/useActiveHeading";
|
import { useActiveHeading } from "@/hooks/useActiveHeading";
|
||||||
import { TTOCItem } from "@/types/toc.type";
|
import type { TTOCItem } from "@/types/toc.type";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
@@ -8,16 +8,16 @@ export const TOC = (props: { data: TTOCItem[] }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-5">
|
<div className="mx-5">
|
||||||
<div className="text-lg text-center p-2 font-bold border-t-2 border-b-2 border-gray-500">
|
<div className="border-gray-500 border-t-2 border-b-2 p-2 text-center font-bold text-lg">
|
||||||
{"TABLE OF CONTENTS"}
|
{"TABLE OF CONTENTS"}
|
||||||
</div>
|
</div>
|
||||||
<div className="px-2 py-2 h-[60vh] overflow-y-auto flat-scrollbar-normal">
|
<div className="flat-scrollbar-normal h-[60vh] overflow-y-auto px-2 py-2">
|
||||||
<div>
|
<div>
|
||||||
{props.data?.map((item) => (
|
{props.data?.map((item) => (
|
||||||
<Link href={`#${item.anchorId}`} key={`toc-${item.anchorId}`}>
|
<Link href={`#${item.anchorId}`} key={`toc-${item.anchorId}`}>
|
||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
`py-2 text-sm rounded-lg hover:text-sky-700 dark:hover:text-sky-400`,
|
"rounded-lg py-2 text-sm hover:text-sky-700 dark:hover:text-sky-400",
|
||||||
activeId === `#${item.anchorId}` ? "text-sky-700 dark:text-sky-400" : "",
|
activeId === `#${item.anchorId}` ? "text-sky-700 dark:text-sky-400" : "",
|
||||||
)}
|
)}
|
||||||
style={{ paddingLeft: `${item.level - 1}em` }}
|
style={{ paddingLeft: `${item.level - 1}em` }}
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ export const SponsorBoard = () => {
|
|||||||
setIsCopiedList(Config.Sponsor?.Crypto?.map(() => false) ?? []);
|
setIsCopiedList(Config.Sponsor?.Crypto?.map(() => false) ?? []);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="mx-2 my-10 flex flex-col justify-around space-y-5">
|
<div className="mx-2 my-10 flex flex-col justify-around space-y-5">
|
||||||
{Config.Sponsor?.Crypto && (
|
{Config.Sponsor?.Crypto && (
|
||||||
<div className="py-3 flex justify-between border-b">
|
<div className="flex justify-between border-b py-3">
|
||||||
<div className="my-auto flex">
|
<div className="my-auto flex">
|
||||||
<div className="mx-3 my-auto">
|
<div className="mx-3 my-auto">
|
||||||
<h3 className="mx-auto text-sm font-bold">{"Crypto"}</h3>
|
<h3 className="mx-auto font-bold text-sm">{"Crypto"}</h3>
|
||||||
<div className="text-xs">{"Supports BTC, USDT and ETH."}</div>
|
<div className="text-xs">{"Supports BTC, USDT and ETH."}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,11 +40,11 @@ export const SponsorBoard = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{Config.Sponsor?.Github && Config.SocialLinks.github && (
|
{Config.Sponsor?.Github && Config.SocialLinks.github && (
|
||||||
<div className="py-3 flex justify-between border-b">
|
<div className="flex justify-between border-b py-3">
|
||||||
<div className="my-auto flex">
|
<div className="my-auto flex">
|
||||||
<FaGithub className="mx-3 my-auto text-4xl text-gray-900 dark:text-gray-500" />
|
<FaGithub className="mx-3 my-auto text-4xl text-gray-900 dark:text-gray-500" />
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
<h3 className="mx-auto text-sm font-bold">{"Github Sponsor"}</h3>
|
<h3 className="mx-auto font-bold text-sm">{"Github Sponsor"}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
@@ -57,11 +57,11 @@ export const SponsorBoard = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isEmptyString(Config.Sponsor?.WechatPayQRCodeContent) && (
|
{!isEmptyString(Config.Sponsor?.WechatPayQRCodeContent) && (
|
||||||
<div className="py-3 flex justify-between border-b">
|
<div className="flex justify-between border-b py-3">
|
||||||
<div className="my-auto flex">
|
<div className="my-auto flex">
|
||||||
<SiWechat className="mx-3 my-auto text-4xl text-green-500" />
|
<SiWechat className="mx-3 my-auto text-4xl text-green-500" />
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
<h3 className="mx-auto text-sm font-bold">{"Wechat Pay"}</h3>
|
<h3 className="mx-auto font-bold text-sm">{"Wechat Pay"}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-auto bg-white p-1">
|
<div className="my-auto bg-white p-1">
|
||||||
@@ -70,11 +70,11 @@ export const SponsorBoard = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isEmptyString(Config.Sponsor?.AlipayLink) && (
|
{!isEmptyString(Config.Sponsor?.AlipayLink) && (
|
||||||
<div className="py-3 flex justify-between border-b">
|
<div className="flex justify-between border-b py-3">
|
||||||
<div className="my-auto flex">
|
<div className="my-auto flex">
|
||||||
<SiAlipay className="mx-3 my-auto text-4xl text-blue-500" />
|
<SiAlipay className="mx-3 my-auto text-4xl text-blue-500" />
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
<h3 className="mx-auto text-sm font-bold">{"Alipay"}</h3>
|
<h3 className="mx-auto font-bold text-sm">{"Alipay"}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
@@ -87,11 +87,11 @@ export const SponsorBoard = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isEmptyString(Config.Sponsor?.PaypalId) && (
|
{!isEmptyString(Config.Sponsor?.PaypalId) && (
|
||||||
<div className="py-3 flex justify-between border-b">
|
<div className="flex justify-between border-b py-3">
|
||||||
<div className="my-auto flex">
|
<div className="my-auto flex">
|
||||||
<FaPaypal className="mx-3 my-auto text-4xl text-blue-600" />
|
<FaPaypal className="mx-3 my-auto text-4xl text-blue-600" />
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
<h3 className="mx-auto text-sm font-bold">{"Paypal"}</h3>
|
<h3 className="mx-auto font-bold text-sm">{"Paypal"}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
@@ -104,11 +104,11 @@ export const SponsorBoard = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isEmptyString(Config.Sponsor?.PatreonId) && (
|
{!isEmptyString(Config.Sponsor?.PatreonId) && (
|
||||||
<div className="py-3 flex justify-between border-b">
|
<div className="flex justify-between border-b py-3">
|
||||||
<div className="my-auto flex">
|
<div className="my-auto flex">
|
||||||
<FaPatreon className="mx-3 my-auto text-4xl text-gray-500" />
|
<FaPatreon className="mx-3 my-auto text-4xl text-gray-500" />
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
<h3 className="mx-auto text-sm font-bold">{"Patreon"}</h3>
|
<h3 className="mx-auto font-bold text-sm">{"Patreon"}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
@@ -125,7 +125,7 @@ export const SponsorBoard = () => {
|
|||||||
<DialogTitle className="flex">{"CRYPTO"}</DialogTitle>
|
<DialogTitle className="flex">{"CRYPTO"}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div>
|
<div>
|
||||||
<div className="w-full text-sm my-2">
|
<div className="my-2 w-full text-sm">
|
||||||
<div>
|
<div>
|
||||||
<b>NOTE: </b> Please confirm the corresponding block network and address before transferring money to
|
<b>NOTE: </b> Please confirm the corresponding block network and address before transferring money to
|
||||||
avoid loss.
|
avoid loss.
|
||||||
@@ -133,9 +133,9 @@ export const SponsorBoard = () => {
|
|||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
{Config.Sponsor?.Crypto?.map((cryptoItem, cryptoItemIndex) => (
|
{Config.Sponsor?.Crypto?.map((cryptoItem, cryptoItemIndex) => (
|
||||||
<div className="w-full py-3 border-b" key={nanoid()}>
|
<div className="w-full border-b py-3" key={nanoid()}>
|
||||||
<div className="my-2 flex space-x-2">
|
<div className="my-2 flex space-x-2">
|
||||||
<div className="font-bold my-auto text-sm">{`${cryptoItem.Name} - ${cryptoItem.Blockchain}`}</div>
|
<div className="my-auto font-bold text-sm">{`${cryptoItem.Name} - ${cryptoItem.Blockchain}`}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<Input autoFocus={false} defaultValue={cryptoItem.Address} readOnly />
|
<Input autoFocus={false} defaultValue={cryptoItem.Address} readOnly />
|
||||||
@@ -148,7 +148,7 @@ export const SponsorBoard = () => {
|
|||||||
text={cryptoItem.Address}
|
text={cryptoItem.Address}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className={`ml-3 my-auto ${isCopiedList[cryptoItemIndex] && "bg-green-500 hover:bg-green-500"}`}
|
className={`my-auto ml-3 ${isCopiedList[cryptoItemIndex] && "bg-green-500 hover:bg-green-500"}`}
|
||||||
size="sm"
|
size="sm"
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ export const SponsorDescription = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
{!Config.Sponsor ? (
|
{!Config.Sponsor ? (
|
||||||
<p className={`content-font break-words text-lg`}>
|
<p className={"break-words text-lg content-font"}>
|
||||||
{"Thank you, for data and personal private security, every sponsor method was paused."}
|
{"Thank you, for data and personal private security, every sponsor method was paused."}
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<p className={`content-font break-words text-lg`}>
|
<p className={"break-words text-lg content-font"}>
|
||||||
{
|
{
|
||||||
"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."
|
"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."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const AccordionContent = React.forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
<div className={cn("pt-0 pb-4", className)}>{children}</div>
|
||||||
</AccordionPrimitive.Content>
|
</AccordionPrimitive.Content>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { cva, type VariantProps } from "class-variance-authority";
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import * as React from "react";
|
import type * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Slot } from "@radix-ui/react-slot";
|
import { Slot } from "@radix-ui/react-slot";
|
||||||
import { cva, type VariantProps } from "class-variance-authority";
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ CardHeader.displayName = "CardHeader";
|
|||||||
|
|
||||||
const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
|
const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
|
||||||
({ className, ...props }, ref) => (
|
({ className, ...props }, ref) => (
|
||||||
<h3 className={cn("text-2xl font-semibold leading-none tracking-tight", className)} ref={ref} {...props} />
|
<h3 className={cn("font-semibold text-2xl leading-none tracking-tight", className)} ref={ref} {...props} />
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
CardTitle.displayName = "CardTitle";
|
CardTitle.displayName = "CardTitle";
|
||||||
|
|
||||||
const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
|
const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
|
||||||
({ className, ...props }, ref) => (
|
({ className, ...props }, ref) => (
|
||||||
<p className={cn("text-sm text-muted-foreground", className)} ref={ref} {...props} />
|
<p className={cn("text-muted-foreground text-sm", className)} ref={ref} {...props} />
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
CardDescription.displayName = "CardDescription";
|
CardDescription.displayName = "CardDescription";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { type DialogProps } from "@radix-ui/react-dialog";
|
import type { DialogProps } from "@radix-ui/react-dialog";
|
||||||
import { Command as CommandPrimitive } from "cmdk";
|
import { Command as CommandPrimitive } from "cmdk";
|
||||||
import { Search } from "lucide-react";
|
import { Search } from "lucide-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
@@ -82,7 +82,7 @@ const CommandGroup = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<CommandPrimitive.Group
|
<CommandPrimitive.Group
|
||||||
className={cn(
|
className={cn(
|
||||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:text-xs",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -117,7 +117,7 @@ const CommandItem = React.forwardRef<
|
|||||||
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
||||||
|
|
||||||
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||||
return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />;
|
return <span className={cn("ml-auto text-muted-foreground text-xs tracking-widest", className)} {...props} />;
|
||||||
};
|
};
|
||||||
CommandShortcut.displayName = "CommandShortcut";
|
CommandShortcut.displayName = "CommandShortcut";
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const DialogOverlay = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DialogPrimitive.Overlay
|
<DialogPrimitive.Overlay
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=closed]:animate-out data-[state=open]:animate-in",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -37,14 +37,14 @@ const DialogContent = React.forwardRef<
|
|||||||
<DialogOverlay />
|
<DialogOverlay />
|
||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:rounded-lg",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
<DialogPrimitive.Close className="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
||||||
<X className="h-4 w-4" />
|
<X className="h-4 w-4" />
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
@@ -68,7 +68,7 @@ const DialogTitle = React.forwardRef<
|
|||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DialogPrimitive.Title
|
<DialogPrimitive.Title
|
||||||
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
|
className={cn("font-semibold text-lg leading-none tracking-tight", className)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -79,7 +79,7 @@ const DialogDescription = React.forwardRef<
|
|||||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<DialogPrimitive.Description className={cn("text-sm text-muted-foreground", className)} ref={ref} {...props} />
|
<DialogPrimitive.Description className={cn("text-muted-foreground text-sm", className)} ref={ref} {...props} />
|
||||||
));
|
));
|
||||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type,
|
|||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:font-medium file:text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
||||||
import { cva, type VariantProps } from "class-variance-authority";
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ const SheetOverlay = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<SheetPrimitive.Overlay
|
<SheetPrimitive.Overlay
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=closed]:animate-out data-[state=open]:animate-in",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -63,7 +63,7 @@ const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Con
|
|||||||
<SheetOverlay />
|
<SheetOverlay />
|
||||||
<SheetPrimitive.Content className={cn(sheetVariants({ side }), className)} ref={ref} {...props}>
|
<SheetPrimitive.Content className={cn(sheetVariants({ side }), className)} ref={ref} {...props}>
|
||||||
{children}
|
{children}
|
||||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
<SheetPrimitive.Close className="absolute top-4 right-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||||
<X className="h-4 w-4" />
|
<X className="h-4 w-4" />
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</SheetPrimitive.Close>
|
</SheetPrimitive.Close>
|
||||||
@@ -87,7 +87,7 @@ const SheetTitle = React.forwardRef<
|
|||||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<SheetPrimitive.Title className={cn("text-lg font-semibold text-foreground", className)} ref={ref} {...props} />
|
<SheetPrimitive.Title className={cn("font-semibold text-foreground text-lg", className)} ref={ref} {...props} />
|
||||||
));
|
));
|
||||||
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ const SheetDescription = React.forwardRef<
|
|||||||
React.ElementRef<typeof SheetPrimitive.Description>,
|
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<SheetPrimitive.Description className={cn("text-sm text-muted-foreground", className)} ref={ref} {...props} />
|
<SheetPrimitive.Description className={cn("text-muted-foreground text-sm", className)} ref={ref} {...props} />
|
||||||
));
|
));
|
||||||
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as ToastPrimitives from "@radix-ui/react-toast";
|
import * as ToastPrimitives from "@radix-ui/react-toast";
|
||||||
import { cva, type VariantProps } from "class-variance-authority";
|
import { type VariantProps, cva } from "class-variance-authority";
|
||||||
import { X } from "lucide-react";
|
import { X } from "lucide-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ const ToastViewport = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<ToastPrimitives.Viewport
|
<ToastPrimitives.Viewport
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:top-auto sm:right-0 sm:bottom-0 sm:flex-col md:max-w-[420px]",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -51,7 +51,7 @@ const ToastAction = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<ToastPrimitives.Action
|
<ToastPrimitives.Action
|
||||||
className={cn(
|
className={cn(
|
||||||
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
|
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 font-medium text-sm ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:focus:ring-destructive group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -66,7 +66,7 @@ const ToastClose = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<ToastPrimitives.Close
|
<ToastPrimitives.Close
|
||||||
className={cn(
|
className={cn(
|
||||||
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
|
"absolute top-2 right-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600 group-[.destructive]:hover:text-red-50",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -82,7 +82,7 @@ const ToastTitle = React.forwardRef<
|
|||||||
React.ElementRef<typeof ToastPrimitives.Title>,
|
React.ElementRef<typeof ToastPrimitives.Title>,
|
||||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<ToastPrimitives.Title className={cn("text-sm font-semibold", className)} ref={ref} {...props} />
|
<ToastPrimitives.Title className={cn("font-semibold text-sm", className)} ref={ref} {...props} />
|
||||||
));
|
));
|
||||||
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
||||||
|
|
||||||
|
|||||||
@@ -8,18 +8,16 @@ export function Toaster() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
{toasts.map(function ({ id, title, description, action, ...props }) {
|
{toasts.map(({ id, title, description, action, ...props }) => (
|
||||||
return (
|
<Toast key={id} {...props}>
|
||||||
<Toast key={id} {...props}>
|
<div className="grid gap-1">
|
||||||
<div className="grid gap-1">
|
{title && <ToastTitle>{title}</ToastTitle>}
|
||||||
{title && <ToastTitle>{title}</ToastTitle>}
|
{description && <ToastDescription>{description}</ToastDescription>}
|
||||||
{description && <ToastDescription>{description}</ToastDescription>}
|
</div>
|
||||||
</div>
|
{action}
|
||||||
{action}
|
<ToastClose />
|
||||||
<ToastClose />
|
</Toast>
|
||||||
</Toast>
|
))}
|
||||||
);
|
|
||||||
})}
|
|
||||||
<ToastViewport />
|
<ToastViewport />
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ export const Footer = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
{Config.RSSFeed?.enabled && (
|
{Config.RSSFeed?.enabled && (
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<button title="Subscribe the RSS Feed.">{"Feed"}</button>
|
<button title="Subscribe the RSS Feed." type="button">
|
||||||
|
{"Feed"}
|
||||||
|
</button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -39,20 +41,20 @@ export const Footer = () => {
|
|||||||
<DialogContent className="sm:max-w-md">
|
<DialogContent className="sm:max-w-md">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="flex">
|
<DialogTitle className="flex">
|
||||||
<IoLogoRss className="mr-2 my-auto" />
|
<IoLogoRss className="my-auto mr-2" />
|
||||||
{"RSS Feed"}
|
{"RSS Feed"}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className="w-full text-sm my-2">
|
<div className="my-2 w-full text-sm">
|
||||||
<div>
|
<div>
|
||||||
<b>NOTE: </b>Some RSS Feed Reader may has deficient in rendering SVG formulations, graphs. Such as the
|
<b>NOTE: </b>Some RSS Feed Reader may has deficient in rendering SVG formulations, graphs. Such as the
|
||||||
Inoreader, Feedly. If it happens, please read the origin web page for better experience.
|
Inoreader, Feedly. If it happens, please read the origin web page for better experience.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="w-full flex my-3">
|
<div className="my-3 flex w-full">
|
||||||
<Input defaultValue={RSSFeedURL} readOnly />
|
<Input defaultValue={RSSFeedURL} readOnly />
|
||||||
<CopyToClipboard
|
<CopyToClipboard
|
||||||
onCopy={() => {
|
onCopy={() => {
|
||||||
@@ -61,7 +63,7 @@ export const Footer = () => {
|
|||||||
text={RSSFeedURL}
|
text={RSSFeedURL}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className={`ml-3 my-auto ${isCopied && "bg-green-500 hover:bg-green-500"}`}
|
className={`my-auto ml-3 ${isCopied && "bg-green-500 hover:bg-green-500"}`}
|
||||||
size="sm"
|
size="sm"
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -32,16 +32,16 @@ export const NavBar = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Sheet onOpenChange={(open) => setIsSideNavOpen(open)} open={isSideNavOpen}>
|
<Sheet onOpenChange={(open) => setIsSideNavOpen(open)} open={isSideNavOpen}>
|
||||||
<div className="sticky top-0 z-50 border-black-200 dark:border-gray-700 border-b bg-white dark:bg-gray-950 flex flex-wrap justify-between py-3 px-5 md:px-10 lg:px-20 xl:px-32 2xl:px-52">
|
<div className="sticky top-0 z-50 flex flex-wrap justify-between border-black-200 border-b bg-white px-5 py-3 md:px-10 lg:px-20 xl:px-32 2xl:px-52 dark:border-gray-700 dark:bg-gray-950">
|
||||||
<Link className="cursor-pointer my-auto text-2xl font-bold" href="/">
|
<Link className="my-auto cursor-pointer font-bold text-2xl" href="/">
|
||||||
<h1 className={`website-title-font my-auto`} title="Click to jump to home page.">
|
<h1 className={"website-title-font my-auto"} title="Click to jump to home page.">
|
||||||
{Config.SiteTitle}
|
{Config.SiteTitle}
|
||||||
</h1>
|
</h1>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="my-auto hidden sm:flex">
|
<div className="my-auto hidden sm:flex">
|
||||||
{MenuItems.map((menuItem) => (
|
{MenuItems.map((menuItem) => (
|
||||||
<Link
|
<Link
|
||||||
className="font-bold hover:text-sky-700 dark:hover:text-sky-500 mx-2 my-auto px-2"
|
className="mx-2 my-auto px-2 font-bold hover:text-sky-700 dark:hover:text-sky-500"
|
||||||
href={menuItem.href}
|
href={menuItem.href}
|
||||||
key={nanoid()}
|
key={nanoid()}
|
||||||
onClick={() => setIsSideNavOpen(false)}
|
onClick={() => setIsSideNavOpen(false)}
|
||||||
@@ -50,23 +50,23 @@ export const NavBar = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
<Link
|
<Link
|
||||||
className="cursor-pointer mx-2 rounded-full p-1 text-3xl text-black hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
|
className="mx-2 cursor-pointer rounded-full p-1 text-3xl text-black hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
|
||||||
href={"/search"}
|
href={"/search"}
|
||||||
title="Search posts by keywords"
|
title="Search posts by keywords"
|
||||||
>
|
>
|
||||||
<MdSearch />
|
<MdSearch />
|
||||||
</Link>
|
</Link>
|
||||||
<div
|
<div
|
||||||
className="cursor-pointer mx-1 rounded-full p-1 text-3xl text-black hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
|
className="mx-1 cursor-pointer rounded-full p-1 text-3xl text-black hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
|
||||||
onClick={handleSwitchTheme}
|
onClick={handleSwitchTheme}
|
||||||
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
|
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
|
||||||
>
|
>
|
||||||
{theme === "light" ? <MdOutlineDarkMode /> : <MdOutlineLightMode />}
|
{theme === "light" ? <MdOutlineDarkMode /> : <MdOutlineLightMode />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-3xl sm:hidden my-auto">
|
<div className="my-auto text-3xl sm:hidden">
|
||||||
<SheetTrigger
|
<SheetTrigger
|
||||||
className="text-black rounded-full p-1 hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
|
className="rounded-full p-1 text-black hover:bg-gray-200 dark:text-gray-50 dark:hover:bg-gray-800"
|
||||||
title="Spread the navigation menu"
|
title="Spread the navigation menu"
|
||||||
>
|
>
|
||||||
<MdMenu
|
<MdMenu
|
||||||
@@ -77,7 +77,7 @@ export const NavBar = () => {
|
|||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SheetContent className="bg:white border-none py-16 shadow-md dark:bg-black flex flex-col text-end">
|
<SheetContent className="bg:white flex flex-col border-none py-16 text-end shadow-md dark:bg-black">
|
||||||
{MenuItems.map((menuItem) => (
|
{MenuItems.map((menuItem) => (
|
||||||
<Link
|
<Link
|
||||||
className="border-b border-dashed p-3 text-xl hover:text-sky-500"
|
className="border-b border-dashed p-3 text-xl hover:text-sky-500"
|
||||||
@@ -97,11 +97,11 @@ export const NavBar = () => {
|
|||||||
{"SEARCH"}
|
{"SEARCH"}
|
||||||
</Link>
|
</Link>
|
||||||
<div
|
<div
|
||||||
className="flex text-xl p-3 cursor-pointer border-b border-dashed justify-end hover:text-sky-500"
|
className="flex cursor-pointer justify-end border-b border-dashed p-3 text-xl hover:text-sky-500"
|
||||||
onClick={handleSwitchTheme}
|
onClick={handleSwitchTheme}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="cursor-pointer mx-1 my-auto rounded-full text-2xl"
|
className="mx-1 my-auto cursor-pointer rounded-full text-2xl"
|
||||||
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
|
title={theme === "light" ? "Switch to dark mode" : "Switch to light mode"}
|
||||||
>
|
>
|
||||||
{theme === "light" ? <MdOutlineDarkMode /> : <MdOutlineLightMode />}
|
{theme === "light" ? <MdOutlineDarkMode /> : <MdOutlineLightMode />}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { normalizeDate } from "@/lib/date";
|
import { normalizeDate } from "@/lib/date";
|
||||||
import { TPostListItem } from "@/types/post-list";
|
import type { TPostListItem } from "@/types/post-list";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Badge } from "../ui/badge";
|
import { Badge } from "../ui/badge";
|
||||||
@@ -12,34 +12,34 @@ export const PostList = (props: { data: TPostListItem[] }) => {
|
|||||||
<div
|
<div
|
||||||
className={`flex flex-col justify-center ${
|
className={`flex flex-col justify-center ${
|
||||||
index !== props.data.length - 1 && "border-b"
|
index !== props.data.length - 1 && "border-b"
|
||||||
} border-gray-200 hover:bg-gray-50 dark:hover:bg-gray-900 dark:border-gray-800 px-3 py-1`}
|
} border-gray-200 px-3 py-1 hover:bg-gray-50 dark:border-gray-800 dark:hover:bg-gray-900`}
|
||||||
>
|
>
|
||||||
<div className={"post-list-caption-font flex-col py-3"}>
|
<div className={"post-list-caption-font flex-col py-3"}>
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<h3 className="mx-auto text-lg font-extrabold capitalize">{postItem.frontMatter.title}</h3>
|
<h3 className="mx-auto font-extrabold text-lg capitalize">{postItem.frontMatter.title}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
{postItem.frontMatter.subtitle && (
|
{postItem.frontMatter.subtitle && (
|
||||||
<div className="mx-auto text-sm font-bold capitalize text-gray-700 dark:text-gray-300">
|
<div className="mx-auto font-bold text-gray-700 text-sm capitalize dark:text-gray-300">
|
||||||
{postItem.frontMatter.subtitle}
|
{postItem.frontMatter.subtitle}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{postItem.frontMatter.summary && (
|
{postItem.frontMatter.summary && (
|
||||||
<div className={"content-font flex justify-center"}>
|
<div className={"flex justify-center content-font"}>
|
||||||
<p>{postItem.frontMatter.summary}</p>
|
<p>{postItem.frontMatter.summary}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-wrap justify-between my-2">
|
<div className="my-2 flex flex-wrap justify-between">
|
||||||
<div className="text-center flex flex-col justify-center italic text-sm my-auto mr-2 h-6">
|
<div className="my-auto mr-2 flex h-6 flex-col justify-center text-center text-sm italic">
|
||||||
<div className="my-auto">{normalizeDate(postItem.frontMatter.time)}</div>
|
<div className="my-auto">{normalizeDate(postItem.frontMatter.time)}</div>
|
||||||
</div>
|
</div>
|
||||||
{postItem.frontMatter.tags && (
|
{postItem.frontMatter.tags && (
|
||||||
<div className="flex flex-wrap my-auto">
|
<div className="my-auto flex flex-wrap">
|
||||||
{postItem.frontMatter.tags.map((tagName) => (
|
{postItem.frontMatter.tags.map((tagName) => (
|
||||||
<Badge
|
<Badge
|
||||||
className="mr-1 my-1 text-gray-600 dark:text-gray-300"
|
className="my-1 mr-1 text-gray-600 dark:text-gray-300"
|
||||||
key={`tags-${nanoid()}`}
|
key={`tags-${nanoid()}`}
|
||||||
variant={"secondary"}
|
variant={"secondary"}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { TbBrandFacebook, TbBrandLinkedin, TbBrandMastodon } from "react-icons/t
|
|||||||
|
|
||||||
export const SocialIcons = () => {
|
export const SocialIcons = () => {
|
||||||
return (
|
return (
|
||||||
<div className="my-5 flex justify-center space-x-4 text-2xl font-bold">
|
<div className="my-5 flex justify-center space-x-4 font-bold text-2xl">
|
||||||
{Config.SocialLinks.twitter && (
|
{Config.SocialLinks.twitter && (
|
||||||
<Link href={`https://x.com/${Config.SocialLinks.twitter}`} target="_blank" title="Twitter">
|
<Link href={`https://x.com/${Config.SocialLinks.twitter}`} target="_blank" title="Twitter">
|
||||||
<FiTwitter className="hover:text-sky-500" />
|
<FiTwitter className="hover:text-sky-500" />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import path from "path";
|
||||||
import { Config } from "@/data/config";
|
import { Config } from "@/data/config";
|
||||||
import { getCurrentTime } from "@/lib/date";
|
import { getCurrentTime } from "@/lib/date";
|
||||||
import path from "path";
|
|
||||||
import process from "process";
|
import process from "process";
|
||||||
|
|
||||||
export const LatestPostCountInHomePage = 10;
|
export const LatestPostCountInHomePage = 10;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { TConfig } from "@/types/config.type";
|
import type { TConfig } from "@/types/config.type";
|
||||||
|
|
||||||
export const Config: TConfig = {
|
export const Config: TConfig = {
|
||||||
// Image url for avatar.
|
// Image url for avatar.
|
||||||
@@ -33,7 +33,7 @@ export const Config: TConfig = {
|
|||||||
// Giscus Configure. Please refer to the https://giscus.app for entire instruction
|
// Giscus Configure. Please refer to the https://giscus.app for entire instruction
|
||||||
Giscus: {
|
Giscus: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
repo: `PrinOrange/nextjs-lexical-blog`,
|
repo: "PrinOrange/nextjs-lexical-blog",
|
||||||
repoId: "R_kgDOK44zmw",
|
repoId: "R_kgDOK44zmw",
|
||||||
category: "Announcements",
|
category: "Announcements",
|
||||||
categoryId: "DIC_kwDOK44zm84Cb94g",
|
categoryId: "DIC_kwDOK44zm84Cb94g",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { TFriendItem } from "@/types/friend.type";
|
import type { TFriendItem } from "@/types/friend.type";
|
||||||
|
|
||||||
export const FriendsList: TFriendItem[] = [
|
export const FriendsList: TFriendItem[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export function useActiveHeading(headingList: string[], options?: IntersectionOb
|
|||||||
headingList
|
headingList
|
||||||
.map((heading) => document?.querySelector(`[id='${removeFirstHash(heading)}']`))
|
.map((heading) => document?.querySelector(`[id='${removeFirstHash(heading)}']`))
|
||||||
//Remove null elments
|
//Remove null elments
|
||||||
.flatMap((f) => (!!f ? [f] : []))
|
.flatMap((f) => (f ? [f] : []))
|
||||||
.forEach((element) => observer.observe(element));
|
.forEach((element) => observer.observe(element));
|
||||||
|
|
||||||
return () => observer.disconnect();
|
return () => observer.disconnect();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export function checkAndCreateDirectory(dirPath: string) {
|
|||||||
fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK);
|
fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK);
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +21,7 @@ export function isDirectoryEmptySync(directory: string) {
|
|||||||
const files = fs.readdirSync(directory);
|
const files = fs.readdirSync(directory);
|
||||||
return files.length === 0;
|
return files.length === 0;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { PostFilesDirectory } from "@/consts/consts";
|
|
||||||
import { TFrontmatter } from "@/types/frontmatter.type";
|
|
||||||
import { TPostListItem, TPostsByTag } from "@/types/post-list";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { serialize } from "next-mdx-remote/serialize";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import { PostFilesDirectory } from "@/consts/consts";
|
||||||
|
import type { TFrontmatter } from "@/types/frontmatter.type";
|
||||||
|
import type { TPostListItem, TPostsByTag } from "@/types/post-list";
|
||||||
|
import { serialize } from "next-mdx-remote/serialize";
|
||||||
import { titleCase } from "title-case";
|
import { titleCase } from "title-case";
|
||||||
import { isEmptyString, nullifyEmptyArray, nullifyEmptyString } from "./utils";
|
import { isEmptyString, nullifyEmptyArray, nullifyEmptyString } from "./utils";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import fs from "fs";
|
||||||
import { CopyrightAnnouncement, LatestPostCountInHomePage, WebsiteURL } from "@/consts/consts";
|
import { CopyrightAnnouncement, LatestPostCountInHomePage, WebsiteURL } from "@/consts/consts";
|
||||||
import { Config } from "@/data/config";
|
import { Config } from "@/data/config";
|
||||||
import { Feed } from "feed";
|
import { Feed } from "feed";
|
||||||
import fs from "fs";
|
|
||||||
import { JSDOM } from "jsdom";
|
import { JSDOM } from "jsdom";
|
||||||
import { MDXRemote } from "next-mdx-remote";
|
import { MDXRemote } from "next-mdx-remote";
|
||||||
import { serialize } from "next-mdx-remote/serialize";
|
import { serialize } from "next-mdx-remote/serialize";
|
||||||
@@ -17,7 +17,8 @@ import remarkMath from "remark-math";
|
|||||||
import remarkPrism from "remark-prism";
|
import remarkPrism from "remark-prism";
|
||||||
import { getPostFileContent, sortedPosts } from "./post-process";
|
import { getPostFileContent, sortedPosts } from "./post-process";
|
||||||
|
|
||||||
const NoticeForRSSReaders = `\n---\n**NOTE:** Different RSS reader may have deficient even no support for svg formulations rendering. If it happens, please read the origin page to have better experience.`;
|
const NoticeForRSSReaders =
|
||||||
|
"\n---\n**NOTE:** Different RSS reader may have deficient even no support for svg formulations rendering. If it happens, please read the origin page to have better experience.";
|
||||||
|
|
||||||
function minifyHTMLCode(htmlString: string): string {
|
function minifyHTMLCode(htmlString: string): string {
|
||||||
const dom = new JSDOM(htmlString);
|
const dom = new JSDOM(htmlString);
|
||||||
@@ -61,7 +62,7 @@ export const generateRSSFeed = async () => {
|
|||||||
for (let i = 0; i < Math.min(LatestPostCountInHomePage, sortedPosts.allPostList.length); i++) {
|
for (let i = 0; i < Math.min(LatestPostCountInHomePage, sortedPosts.allPostList.length); i++) {
|
||||||
const post = sortedPosts.allPostList[i];
|
const post = sortedPosts.allPostList[i];
|
||||||
const postFileContent = `${getPostFileContent(post.id)}${NoticeForRSSReaders}}`;
|
const postFileContent = `${getPostFileContent(post.id)}${NoticeForRSSReaders}}`;
|
||||||
const dateNumber = post.frontMatter.time.split("-").map((num) => parseInt(num));
|
const dateNumber = post.frontMatter.time.split("-").map((num) => Number.parseInt(num));
|
||||||
const mdxSource = await serialize(postFileContent ?? "", {
|
const mdxSource = await serialize(postFileContent ?? "", {
|
||||||
parseFrontmatter: true,
|
parseFrontmatter: true,
|
||||||
mdxOptions: {
|
mdxOptions: {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ function tokenizer(str: string) {
|
|||||||
|
|
||||||
function makeSearchIndex() {
|
function makeSearchIndex() {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
let miniSearch = new minisearch({
|
const miniSearch = new minisearch({
|
||||||
fields: ["id", "title", "tags", "subtitle", "summary", "content"],
|
fields: ["id", "title", "tags", "subtitle", "summary", "content"],
|
||||||
storeFields: ["id", "title", "tags", "summary"],
|
storeFields: ["id", "title", "tags", "summary"],
|
||||||
tokenize: tokenizer,
|
tokenize: tokenizer,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { TTOCItem } from "@/types/toc.type";
|
import type { TTOCItem } from "@/types/toc.type";
|
||||||
import { JSDOM } from "jsdom";
|
import { JSDOM } from "jsdom";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,7 +12,7 @@ export const makeTOCTree = (htmlCode: string) => {
|
|||||||
const all_headers = doc_dom.window.document.querySelectorAll("h1,h2,h3,h4,h5,h6");
|
const all_headers = doc_dom.window.document.querySelectorAll("h1,h2,h3,h4,h5,h6");
|
||||||
const result: TTOCItem[] = [];
|
const result: TTOCItem[] = [];
|
||||||
for (let i = 0; i < all_headers.length; i++) {
|
for (let i = 0; i < all_headers.length; i++) {
|
||||||
const level = parseInt(all_headers[i].tagName.replace("H", ""));
|
const level = Number.parseInt(all_headers[i].tagName.replace("H", ""));
|
||||||
result.push({
|
result.push({
|
||||||
level: level,
|
level: level,
|
||||||
anchorId: all_headers[i].id,
|
anchorId: all_headers[i].id,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { NonEmptyArray } from "@/types/utils.type";
|
import type { NonEmptyArray } from "@/types/utils.type";
|
||||||
import { clsx, type ClassValue } from "clsx";
|
import { type ClassValue, clsx } from "clsx";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
var WebpackObfuscator = require("webpack-obfuscator");
|
const WebpackObfuscator = require("webpack-obfuscator");
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
||||||
|
|||||||
3842
package-lock.json
generated
3842
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@@ -14,12 +14,11 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"dev:turbo": "npx turbo dev",
|
"dev:turbo": "npx turbo dev",
|
||||||
"build:turbo": "npx turbo build lint",
|
"build:turbo": "npx turbo build",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"format": "npx prettier . --write && npx autocorrect --fix",
|
"format": "npx biome format --write . && npx autocorrect --fix",
|
||||||
"lint": "next lint",
|
"lint:fix": "npx biome check --fix",
|
||||||
"lint:fix": "npx eslint --fix .",
|
|
||||||
"newpost": "bun ./scripts/newpost.ts",
|
"newpost": "bun ./scripts/newpost.ts",
|
||||||
"archive": "bun ./scripts/archive.ts"
|
"archive": "bun ./scripts/archive.ts"
|
||||||
},
|
},
|
||||||
@@ -43,8 +42,6 @@
|
|||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"eslint-config-next": "^14.1.4",
|
|
||||||
"eslint-config-plugin": "^1.0.11",
|
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^24.0.0",
|
||||||
"katex": "^0.16.9",
|
"katex": "^0.16.9",
|
||||||
@@ -89,6 +86,7 @@
|
|||||||
"zustand": "^4.4.7"
|
"zustand": "^4.4.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@biomejs/biome": "1.8.3",
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
"@types/archiver": "^6.0.2",
|
"@types/archiver": "^6.0.2",
|
||||||
"@types/inquirer": "^9.0.7",
|
"@types/inquirer": "^9.0.7",
|
||||||
@@ -105,13 +103,8 @@
|
|||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"autocorrect-node": "^2.11.1",
|
"autocorrect-node": "^2.11.1",
|
||||||
"bun": "^1.1.22",
|
"bun": "^1.1.22",
|
||||||
"eslint": "^8.57.0",
|
|
||||||
"eslint-plugin-react": "^7.34.1",
|
|
||||||
"feed": "^4.2.2",
|
"feed": "^4.2.2",
|
||||||
"inquirer": "^9.2.12",
|
"inquirer": "^9.2.12",
|
||||||
"prettier": "^3.0.3",
|
|
||||||
"prettier-plugin-organize-imports": "^3.2.4",
|
|
||||||
"prettier-plugin-tailwindcss": "^0.5.7",
|
|
||||||
"tar": "^7.0.1",
|
"tar": "^7.0.1",
|
||||||
"turbo": "^2.0.12",
|
"turbo": "^2.0.12",
|
||||||
"webpack-obfuscator": "^3.5.1"
|
"webpack-obfuscator": "^3.5.1"
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ export default function NotFoundPage() {
|
|||||||
<Page>
|
<Page>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<h2 className={`my-5 flex justify-center text-2xl font-bold caption-font`}>{"404 NOT FOUND"}</h2>
|
<h2 className={"caption-font my-5 flex justify-center font-bold text-2xl"}>{"404 NOT FOUND"}</h2>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="my-5 flex flex-col justify-center">
|
<div className="my-5 flex flex-col justify-center">
|
||||||
<TfiFaceSad className="mx-auto my-4" size={"6em"} />
|
<TfiFaceSad className="mx-auto my-4" size={"6em"} />
|
||||||
<p className={`content-font mx-auto my-3 text-center text-xl`}>
|
<p className={"mx-auto my-3 text-center text-xl content-font"}>
|
||||||
{"This page does not exist for it might be removed or closed."}
|
{"This page does not exist for it might be removed or closed."}
|
||||||
</p>
|
</p>
|
||||||
<div className="my-5 flex justify-center">
|
<div className="my-5 flex justify-center">
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ export default function ServerErrorPage() {
|
|||||||
<Page>
|
<Page>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<h2 className={`my-5 flex justify-center text-2xl font-bold caption-font`}>{"INVALID OPERATION"}</h2>
|
<h2 className={"caption-font my-5 flex justify-center font-bold text-2xl"}>{"INVALID OPERATION"}</h2>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="my-5 flex flex-col justify-center">
|
<div className="my-5 flex flex-col justify-center">
|
||||||
<MdOutlineDangerous className="mx-auto my-4" size={"6em"} />
|
<MdOutlineDangerous className="mx-auto my-4" size={"6em"} />
|
||||||
<p className={`content-font mx-auto my-3 text-center text-xl`}>
|
<p className={"mx-auto my-3 text-center text-xl content-font"}>
|
||||||
{"Something went wrong. Please try again later."}
|
{"Something went wrong. Please try again later."}
|
||||||
</p>
|
</p>
|
||||||
<div className="my-5 flex justify-center">
|
<div className="my-5 flex justify-center">
|
||||||
|
|||||||
@@ -18,16 +18,15 @@ export default function AboutPage() {
|
|||||||
/>
|
/>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<h2 className={`my-5 flex justify-around text-2xl font-bold caption-font`}>{"ABOUT ME"}</h2>
|
<h2 className={"caption-font my-5 flex justify-around font-bold text-2xl"}>{"ABOUT ME"}</h2>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className={`content-font my-5 justify-center md:flex md:space-x-10`}>
|
<div className={"my-5 justify-center content-font md:flex md:space-x-10"}>
|
||||||
<div className="my-auto flex md:w-1/3">
|
<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" />
|
<img alt="my-profile" className="mx-auto my-auto max-h-[23rem] rounded-lg" src="/images/profile.webp" />
|
||||||
</div>
|
</div>
|
||||||
<div className="my-auto md:w-1/3">
|
<div className="my-auto md:w-1/3">
|
||||||
<div className="mt-5 mb-3 text-3xl font-bold">Hi, there👋</div>
|
<div className="mt-5 mb-3 font-bold text-3xl">Hi, there👋</div>I am a student / entrepreneur / engineer
|
||||||
I am a student / entrepreneur / engineer (Your profession) majoring in (Your Research Field) born in XXXX
|
(Your profession) majoring in (Your Research Field) born in XXXX (Your birth year)
|
||||||
(Your birth year)
|
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
My main research interests includes XXXX
|
My main research interests includes XXXX
|
||||||
@@ -40,7 +39,7 @@ export default function AboutPage() {
|
|||||||
<SocialIcons />
|
<SocialIcons />
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
<ul className="mx-auto my-10 px-5 md:w-2/3 list-disc">
|
<ul className="mx-auto my-10 list-disc px-5 md:w-2/3">
|
||||||
{Config.SocialLinks.github && (
|
{Config.SocialLinks.github && (
|
||||||
<li className="my-2">
|
<li className="my-2">
|
||||||
{"📕 Check out my github profile at "}
|
{"📕 Check out my github profile at "}
|
||||||
@@ -64,7 +63,7 @@ export default function AboutPage() {
|
|||||||
<li className="my-2">From : Your Country, State / Province</li>
|
<li className="my-2">From : Your Country, State / Province</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div className="mx-auto my-10 md:w-2/3 font-bold">
|
<div className="mx-auto my-10 font-bold md:w-2/3">
|
||||||
{
|
{
|
||||||
"** In addition to the above content, you can also add other customized components, content, etc. to this page. **"
|
"** In addition to the above content, you can also add other customized components, content, etc. to this page. **"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { SearchIndex } from "@/lib/search";
|
import { SearchIndex } from "@/lib/search";
|
||||||
import { isEmptyString } from "@/lib/utils";
|
import { isEmptyString } from "@/lib/utils";
|
||||||
import { TSearchResultItem } from "@/types/search-result";
|
import type { TSearchResultItem } from "@/types/search-result";
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
type ResponseData = TSearchResultItem[];
|
type ResponseData = TSearchResultItem[];
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ import { normalizeDate } from "@/lib/date";
|
|||||||
import { getPostFileContent, sortedPosts } from "@/lib/post-process";
|
import { getPostFileContent, sortedPosts } from "@/lib/post-process";
|
||||||
import { makeTOCTree } from "@/lib/toc";
|
import { makeTOCTree } from "@/lib/toc";
|
||||||
import useDrawerTOCState from "@/stores/useDrawerTOCState";
|
import useDrawerTOCState from "@/stores/useDrawerTOCState";
|
||||||
import { TFrontmatter } from "@/types/frontmatter.type";
|
import type { TFrontmatter } from "@/types/frontmatter.type";
|
||||||
import { TPostListItem } from "@/types/post-list";
|
import type { TPostListItem } from "@/types/post-list";
|
||||||
import { TTOCItem } from "@/types/toc.type";
|
import type { TTOCItem } from "@/types/toc.type";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { GetStaticPaths, GetStaticProps } from "next";
|
import type { GetStaticPaths, GetStaticProps } from "next";
|
||||||
import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote";
|
import { MDXRemote, type MDXRemoteSerializeResult } from "next-mdx-remote";
|
||||||
import { serialize } from "next-mdx-remote/serialize";
|
import { serialize } from "next-mdx-remote/serialize";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { renderToString } from "react-dom/server";
|
import { renderToString } from "react-dom/server";
|
||||||
@@ -70,34 +70,36 @@ const ReaderPage = (props: ReaderPageProps) => {
|
|||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<div
|
<div
|
||||||
className={`py-1 ${isTOCLongEnough ? "justify-between" : "justify-center"} lg:flex space-x-5`}
|
className={`py-1 ${isTOCLongEnough ? "justify-between" : "justify-center"} space-x-5 lg:flex`}
|
||||||
style={{ borderRadius: "5px" }}
|
style={{ borderRadius: "5px" }}
|
||||||
>
|
>
|
||||||
<div className={`${isTOCLongEnough ? "lg:w-2/3" : "lg:w-5/6"} py-5`}>
|
<div className={`${isTOCLongEnough ? "lg:w-2/3" : "lg:w-5/6"} py-5`}>
|
||||||
<div className="typesetting">
|
<div className="typesetting">
|
||||||
{props.frontMatter.coverURL && <PostCover coverURL={props.frontMatter.coverURL} />}
|
{props.frontMatter.coverURL && <PostCover coverURL={props.frontMatter.coverURL} />}
|
||||||
<div className="pb-1 border-b-2 border-black dark:border-gray-300">
|
<div className="border-black border-b-2 pb-1 dark:border-gray-300">
|
||||||
<div
|
<div
|
||||||
className={`caption-font my-2 text-black dark:text-white flex justify-center whitespace-normal break-words text-3xl font-bold capitalize`}
|
className={
|
||||||
|
"caption-font my-2 flex justify-center whitespace-normal break-words font-bold text-3xl text-black capitalize dark:text-white"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{props.frontMatter?.title}
|
{props.frontMatter?.title}
|
||||||
</div>
|
</div>
|
||||||
{props.frontMatter?.subtitle && (
|
{props.frontMatter?.subtitle && (
|
||||||
<div className={`caption-font my-1 flex justify-center text-xl font-bold capitalize`}>
|
<div className={"caption-font my-1 flex justify-center font-bold text-xl capitalize"}>
|
||||||
{props.frontMatter.subtitle}
|
{props.frontMatter.subtitle}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="my-1 flex justify-center text-sm italic">{normalizeDate(props.frontMatter?.time)}</div>
|
<div className="my-1 flex justify-center text-sm italic">{normalizeDate(props.frontMatter?.time)}</div>
|
||||||
{props.frontMatter?.summary && (
|
{props.frontMatter?.summary && (
|
||||||
<p className={"content-font my-4 indent-8 text-gray-800 dark:text-gray-300"}>
|
<p className={"my-4 indent-8 text-gray-800 content-font dark:text-gray-300"}>
|
||||||
{props.frontMatter?.summary}
|
{props.frontMatter?.summary}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{props.frontMatter.tags && (
|
{props.frontMatter.tags && (
|
||||||
<div className={"pt-1 flex flex-wrap border-t-2 border-black dark:border-gray-300"}>
|
<div className={"flex flex-wrap border-black border-t-2 pt-1 dark:border-gray-300"}>
|
||||||
{props.frontMatter.tags.map((tagName) => (
|
{props.frontMatter.tags.map((tagName) => (
|
||||||
<Link
|
<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"
|
className="not-prose my-1 mr-2 border-2 border-black px-2 py-1 font-bold text-gray-700 text-xs hover:text-black dark:border-gray-300 dark:text-gray-300 dark:hover:text-gray-200"
|
||||||
href={`/tags/${tagName}`}
|
href={`/tags/${tagName}`}
|
||||||
key={`tags-${nanoid()}`}
|
key={`tags-${nanoid()}`}
|
||||||
>
|
>
|
||||||
@@ -135,7 +137,7 @@ const ReaderPage = (props: ReaderPageProps) => {
|
|||||||
title={props.frontMatter.title}
|
title={props.frontMatter.title}
|
||||||
/>
|
/>
|
||||||
<Separator />
|
<Separator />
|
||||||
<ul className="my-5 px-5 flex flex-col justify-center list-disc">
|
<ul className="my-5 flex list-disc flex-col justify-center px-5">
|
||||||
{props.prevPostListItem && (
|
{props.prevPostListItem && (
|
||||||
<li className="my-1">
|
<li className="my-1">
|
||||||
<Link
|
<Link
|
||||||
@@ -160,7 +162,7 @@ const ReaderPage = (props: ReaderPageProps) => {
|
|||||||
{Config.Giscus?.enabled && <PostComments postId={props.postId} />}
|
{Config.Giscus?.enabled && <PostComments postId={props.postId} />}
|
||||||
</div>
|
</div>
|
||||||
{isTOCLongEnough && (
|
{isTOCLongEnough && (
|
||||||
<div className="hidden lg:block md:w-1/3 py-5">
|
<div className="hidden py-5 md:w-1/3 lg:block">
|
||||||
<div className="sticky top-[5em]">
|
<div className="sticky top-[5em]">
|
||||||
<TOC data={props.tocList} />
|
<TOC data={props.tocList} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ export default function FriendsPage() {
|
|||||||
<SEO description={"My Friend Links"} title={`${Config.SiteTitle} - Friends`} />
|
<SEO description={"My Friend Links"} title={`${Config.SiteTitle} - Friends`} />
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<h2 className={`my-5 flex justify-center text-2xl font-bold caption-font`}>{"FRIENDS"}</h2>
|
<h2 className={"caption-font my-5 flex justify-center font-bold text-2xl"}>{"FRIENDS"}</h2>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className={`my-5 flex flex-wrap justify-center text-2xl content-font`}>
|
<div className={"my-5 flex flex-wrap justify-center text-2xl content-font"}>
|
||||||
{FriendsList.map((item) => (
|
{FriendsList.map((item) => (
|
||||||
<Link className="mx-2 p-2 underline" href={item.url} key={nanoid()}>
|
<Link className="mx-2 p-2 underline" href={item.url} key={nanoid()}>
|
||||||
{item.title}
|
{item.title}
|
||||||
@@ -24,7 +24,7 @@ export default function FriendsPage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="my-2 text-base flex-col flex justify-start">
|
<div className="my-2 flex flex-col justify-start text-base">
|
||||||
<div className="mx-auto">
|
<div className="mx-auto">
|
||||||
{"Welcome to exchange our friend links and every high-quality blog websites are welcomed. "}
|
{"Welcome to exchange our friend links and every high-quality blog websites are welcomed. "}
|
||||||
<Link className="underline" href={`mailto:${Config.SocialLinks.email}`}>
|
<Link className="underline" href={`mailto:${Config.SocialLinks.email}`}>
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { LatestPostCountInHomePage } from "@/consts/consts";
|
|||||||
import { Config } from "@/data/config";
|
import { Config } from "@/data/config";
|
||||||
import { sortedPosts } from "@/lib/post-process";
|
import { sortedPosts } from "@/lib/post-process";
|
||||||
import { generateRSSFeed } from "@/lib/rss";
|
import { generateRSSFeed } from "@/lib/rss";
|
||||||
import { TPostListItem } from "@/types/post-list";
|
import type { TPostListItem } from "@/types/post-list";
|
||||||
import { GetStaticProps } from "next";
|
import type { GetStaticProps } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { LuPenTool } from "react-icons/lu";
|
import { LuPenTool } from "react-icons/lu";
|
||||||
import { RiStarFill } from "react-icons/ri";
|
import { RiStarFill } from "react-icons/ri";
|
||||||
@@ -35,7 +35,7 @@ export default function Home(props: HomePageProps) {
|
|||||||
{props.pinnedPostList.length !== 0 && (
|
{props.pinnedPostList.length !== 0 && (
|
||||||
<div>
|
<div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<h2 className={`my-5 flex justify-center text-2xl font-bold caption-font`}>
|
<h2 className={"caption-font my-5 flex justify-center font-bold text-2xl"}>
|
||||||
<RiStarFill className="mx-2 my-auto" />
|
<RiStarFill className="mx-2 my-auto" />
|
||||||
{"PINNED POSTS"}
|
{"PINNED POSTS"}
|
||||||
</h2>
|
</h2>
|
||||||
@@ -46,7 +46,7 @@ export default function Home(props: HomePageProps) {
|
|||||||
{props.latestPostList.length !== 0 && (
|
{props.latestPostList.length !== 0 && (
|
||||||
<div>
|
<div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<h2 className={`my-5 flex justify-center text-2xl font-bold caption-font`}>
|
<h2 className={"caption-font my-5 flex justify-center font-bold text-2xl"}>
|
||||||
<LuPenTool className="mx-2 my-auto" />
|
<LuPenTool className="mx-2 my-auto" />
|
||||||
{"LATEST POSTS"}
|
{"LATEST POSTS"}
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ import { PostCountPerPagination } from "@/consts/consts";
|
|||||||
import { Config } from "@/data/config";
|
import { Config } from "@/data/config";
|
||||||
import { sortedPosts } from "@/lib/post-process";
|
import { sortedPosts } from "@/lib/post-process";
|
||||||
import { isEmptyArray, paginateArray } from "@/lib/utils";
|
import { isEmptyArray, paginateArray } from "@/lib/utils";
|
||||||
import { TPostListItem } from "@/types/post-list";
|
import type { TPostListItem } from "@/types/post-list";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { GetStaticPaths, GetStaticProps } from "next";
|
import type { GetStaticPaths, GetStaticProps } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { ChangeEvent, KeyboardEvent, useEffect, useState } from "react";
|
import { type ChangeEvent, type KeyboardEvent, useEffect, useState } from "react";
|
||||||
import { LuPenTool } from "react-icons/lu";
|
import { LuPenTool } from "react-icons/lu";
|
||||||
|
|
||||||
type PostsPageProps = {
|
type PostsPageProps = {
|
||||||
@@ -32,7 +32,7 @@ export default function PostsPage(props: PostsPageProps) {
|
|||||||
|
|
||||||
const handleEnterKeyJump = (event: KeyboardEvent<HTMLInputElement>) => {
|
const handleEnterKeyJump = (event: KeyboardEvent<HTMLInputElement>) => {
|
||||||
setPageNumber(pageNumber.replace(/[^\d]/g, ""));
|
setPageNumber(pageNumber.replace(/[^\d]/g, ""));
|
||||||
if (parseInt(pageNumber) > 0 && parseInt(pageNumber) < props.pageAmount + 1) {
|
if (Number.parseInt(pageNumber) > 0 && Number.parseInt(pageNumber) < props.pageAmount + 1) {
|
||||||
(event.key === "Go" || event.key === "Enter") && router.push(`/posts/${pageNumber}`);
|
(event.key === "Go" || event.key === "Enter") && router.push(`/posts/${pageNumber}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -55,20 +55,20 @@ export default function PostsPage(props: PostsPageProps) {
|
|||||||
/>
|
/>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<h2 className={`my-5 flex justify-center text-2xl caption-font font-bold`}>
|
<h2 className={"caption-font my-5 flex justify-center font-bold text-2xl"}>
|
||||||
<LuPenTool className="mx-2 my-auto" />
|
<LuPenTool className="mx-2 my-auto" />
|
||||||
{"ALL POSTS"}
|
{"ALL POSTS"}
|
||||||
</h2>
|
</h2>
|
||||||
{!isEmptyArray(props.tagList) && (
|
{!isEmptyArray(props.tagList) && (
|
||||||
<Accordion collapsible type="single">
|
<Accordion collapsible type="single">
|
||||||
<AccordionItem className="border-t" value="item-1">
|
<AccordionItem className="border-t" value="item-1">
|
||||||
<AccordionTrigger className="hover:no-underline font-bold">{"TAG FILTER"}</AccordionTrigger>
|
<AccordionTrigger className="font-bold hover:no-underline">{"TAG FILTER"}</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className={`my-5 flex flex-wrap text-wrap text-sm justify-center px-2`}>
|
<div className={"my-5 flex flex-wrap justify-center text-wrap px-2 text-sm"}>
|
||||||
{props.tagList.map((item) => (
|
{props.tagList.map((item) => (
|
||||||
<Link
|
<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"
|
className="m-1 my-auto p-1 font-bold text-gray-700 underline decoration-2 underline-offset-[5px] hover:text-black dark:text-gray-300 dark:hover:text-white"
|
||||||
href={`/tags/${item.name}`}
|
href={`/tags/${item.name}`}
|
||||||
key={`tags-${nanoid()}`}
|
key={`tags-${nanoid()}`}
|
||||||
>
|
>
|
||||||
@@ -83,7 +83,7 @@ export default function PostsPage(props: PostsPageProps) {
|
|||||||
<Separator />
|
<Separator />
|
||||||
<PostList data={props.postList} />
|
<PostList data={props.postList} />
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="my-5 flex justify-between text-base font-bold">
|
<div className="my-5 flex justify-between font-bold text-base">
|
||||||
{props.pageNumber !== 1 && (
|
{props.pageNumber !== 1 && (
|
||||||
<Button asChild>
|
<Button asChild>
|
||||||
<Link className="font-bold" href={`/posts/${props.pageNumber - 1}/`}>
|
<Link className="font-bold" href={`/posts/${props.pageNumber - 1}/`}>
|
||||||
@@ -91,9 +91,9 @@ export default function PostsPage(props: PostsPageProps) {
|
|||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<div className="my-auto font-bold flex justify-center">
|
<div className="my-auto flex justify-center font-bold">
|
||||||
<Input
|
<Input
|
||||||
className="my-auto mx-2 w-11 h-6"
|
className="mx-2 my-auto h-6 w-11"
|
||||||
onChange={handleInputPageNumber}
|
onChange={handleInputPageNumber}
|
||||||
onKeyDown={handleEnterKeyJump}
|
onKeyDown={handleEnterKeyJump}
|
||||||
title="Type the specified page number and press Enter to jump."
|
title="Type the specified page number and press Enter to jump."
|
||||||
@@ -130,9 +130,9 @@ export const getStaticPaths: GetStaticPaths = () => {
|
|||||||
export const getStaticProps: GetStaticProps<PostsPageProps> = async (context) => {
|
export const getStaticProps: GetStaticProps<PostsPageProps> = async (context) => {
|
||||||
const params = (context.params?.slug as string[]) ?? [];
|
const params = (context.params?.slug as string[]) ?? [];
|
||||||
|
|
||||||
const pageNumber = params[0] ? parseInt(params[0]) : 1;
|
const pageNumber = params[0] ? Number.parseInt(params[0]) : 1;
|
||||||
|
|
||||||
let postList: TPostListItem[] = paginateArray(sortedPosts.allPostList, PostCountPerPagination, pageNumber);
|
const postList: TPostListItem[] = paginateArray(sortedPosts.allPostList, PostCountPerPagination, pageNumber);
|
||||||
|
|
||||||
const pageAmount = Math.ceil(sortedPosts.allPostList.length / PostCountPerPagination);
|
const pageAmount = Math.ceil(sortedPosts.allPostList.length / PostCountPerPagination);
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import { NavBar } from "@/components/utils/NavBar";
|
|||||||
import { SEO } from "@/components/utils/SEO";
|
import { SEO } from "@/components/utils/SEO";
|
||||||
import { Config } from "@/data/config";
|
import { Config } from "@/data/config";
|
||||||
import { isEmptyString } from "@/lib/utils";
|
import { isEmptyString } from "@/lib/utils";
|
||||||
import { TSearchResultItem } from "@/types/search-result";
|
import type { TSearchResultItem } from "@/types/search-result";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { isArray } from "lodash";
|
import { isArray } from "lodash";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { GetServerSideProps } from "next";
|
import type { GetServerSideProps } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { ChangeEvent, KeyboardEvent, useEffect, useState } from "react";
|
import { type ChangeEvent, type KeyboardEvent, useEffect, useState } from "react";
|
||||||
|
|
||||||
type SearchPageProps = { query: string | null };
|
type SearchPageProps = { query: string | null };
|
||||||
|
|
||||||
@@ -88,8 +88,8 @@ export default function SearchPage(props: SearchPageProps) {
|
|||||||
<Toaster />
|
<Toaster />
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<h2 className={`my-10 flex justify-center text-2xl font-bold caption-font`}>{"SEARCH POSTS"}</h2>
|
<h2 className={"caption-font my-10 flex justify-center font-bold text-2xl"}>{"SEARCH POSTS"}</h2>
|
||||||
<div className="flex my-10">
|
<div className="my-10 flex">
|
||||||
<Input
|
<Input
|
||||||
className="my-auto py-0"
|
className="my-auto py-0"
|
||||||
onChange={handleInputSearchText}
|
onChange={handleInputSearchText}
|
||||||
@@ -97,26 +97,26 @@ export default function SearchPage(props: SearchPageProps) {
|
|||||||
placeholder="Input the keyword"
|
placeholder="Input the keyword"
|
||||||
value={searchText}
|
value={searchText}
|
||||||
/>
|
/>
|
||||||
<Button className="mx-3 w-32 my-auto" disabled={isLoading} onClick={handleMakeSearch}>
|
<Button className="mx-3 my-auto w-32" disabled={isLoading} onClick={handleMakeSearch}>
|
||||||
{isLoading ? "Loading" : "Search"}
|
{isLoading ? "Loading" : "Search"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center">
|
<div className="flex flex-col justify-center">
|
||||||
<div className={`min-h-full flex flex-col content-font`}>
|
<div className={"flex min-h-full flex-col content-font"}>
|
||||||
{searchResult.map((item, index) => (
|
{searchResult.map((item, index) => (
|
||||||
<Link
|
<Link
|
||||||
className={`p-2 border-t ${index === searchResult.length - 1 && "border-b"} hover:bg-gray-50 dark:hover:bg-gray-900 flex flex-col`}
|
className={`border-t p-2 ${index === searchResult.length - 1 && "border-b"} flex flex-col hover:bg-gray-50 dark:hover:bg-gray-900`}
|
||||||
href={`/blog/${item.id}`}
|
href={`/blog/${item.id}`}
|
||||||
key={nanoid()}
|
key={nanoid()}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<div className="my-1">
|
<div className="my-1">
|
||||||
<div className="capitalize post-list-caption-font text-md font-bold">{item.title}</div>
|
<div className="post-list-caption-font font-bold text-md capitalize">{item.title}</div>
|
||||||
{item.summary && <div>{item.summary}</div>}
|
{item.summary && <div>{item.summary}</div>}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-2 flex-wrap">
|
<div className="flex flex-wrap space-x-2">
|
||||||
{item.tags?.map((tagitem) => (
|
{item.tags?.map((tagitem) => (
|
||||||
<div className="text-sm text-gray-500 dark:text-gray-400" key={nanoid()}>
|
<div className="text-gray-500 text-sm dark:text-gray-400" key={nanoid()}>
|
||||||
{tagitem}
|
{tagitem}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -125,7 +125,7 @@ export default function SearchPage(props: SearchPageProps) {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center my-3 text-gray-500 dark:text-gray-400">
|
<div className="my-3 text-center text-gray-500 dark:text-gray-400">
|
||||||
<p className="mx-auto text-sm">{"For search efficiency, only the first 20 results are displayed."}</p>
|
<p className="mx-auto text-sm">{"For search efficiency, only the first 20 results are displayed."}</p>
|
||||||
</div>
|
</div>
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
|
|||||||
@@ -20,15 +20,15 @@ export default function SponsorPage() {
|
|||||||
<Toaster />
|
<Toaster />
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<div className="md:flex mt-10">
|
<div className="mt-10 md:flex">
|
||||||
<div className="flex flex-col justify-center md:w-1/2">
|
<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 caption-font`}>
|
<h2 className={"caption-font my-5 flex justify-center font-bold text-2xl text-red-500"}>
|
||||||
<GoHeartFill className="mx-2 my-auto" />
|
<GoHeartFill className="mx-2 my-auto" />
|
||||||
{"SPONSOR"}
|
{"SPONSOR"}
|
||||||
</h2>
|
</h2>
|
||||||
<SponsorDescription />
|
<SponsorDescription />
|
||||||
</div>
|
</div>
|
||||||
<div className="md:px-15 md:w-1/2">
|
<div className="md:w-1/2 md:px-15">
|
||||||
<SponsorBoard />
|
<SponsorBoard />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import { PostCountPerPagination } from "@/consts/consts";
|
|||||||
import { Config } from "@/data/config";
|
import { Config } from "@/data/config";
|
||||||
import { sortedPosts } from "@/lib/post-process";
|
import { sortedPosts } from "@/lib/post-process";
|
||||||
import { paginateArray } from "@/lib/utils";
|
import { paginateArray } from "@/lib/utils";
|
||||||
import { TPostListItem } from "@/types/post-list";
|
import type { TPostListItem } from "@/types/post-list";
|
||||||
import { GetStaticPaths, GetStaticProps } from "next";
|
import type { GetStaticPaths, GetStaticProps } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { ChangeEvent, KeyboardEvent, useEffect, useState } from "react";
|
import { type ChangeEvent, type KeyboardEvent, useEffect, useState } from "react";
|
||||||
|
|
||||||
type TagsContentPageProps = {
|
type TagsContentPageProps = {
|
||||||
tagName: string | null;
|
tagName: string | null;
|
||||||
@@ -29,7 +29,7 @@ export default function TagsContentPage(props: TagsContentPageProps) {
|
|||||||
|
|
||||||
const handleEnterKeyJump = (event: KeyboardEvent<HTMLInputElement>) => {
|
const handleEnterKeyJump = (event: KeyboardEvent<HTMLInputElement>) => {
|
||||||
setPageNumber(pageNumber.replace(/[^\d]/g, ""));
|
setPageNumber(pageNumber.replace(/[^\d]/g, ""));
|
||||||
if (parseInt(pageNumber) > 0 && parseInt(pageNumber) < props.pageAmount + 1) {
|
if (Number.parseInt(pageNumber) > 0 && Number.parseInt(pageNumber) < props.pageAmount + 1) {
|
||||||
(event.key === "Go" || event.key === "Enter") && router.push(`/tags/${props.tagName}/${pageNumber}`);
|
(event.key === "Go" || event.key === "Enter") && router.push(`/tags/${props.tagName}/${pageNumber}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -52,13 +52,13 @@ export default function TagsContentPage(props: TagsContentPageProps) {
|
|||||||
/>
|
/>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<h2 className={"my-5 flex flex-col justify-center text-center font-bold caption-font"}>
|
<h2 className={"caption-font my-5 flex flex-col justify-center text-center font-bold"}>
|
||||||
<div className="mx-auto text-2xl">{`Posts of ${props.tagName}`}</div>
|
<div className="mx-auto text-2xl">{`Posts of ${props.tagName}`}</div>
|
||||||
</h2>
|
</h2>
|
||||||
<Separator />
|
<Separator />
|
||||||
<PostList data={props.postList} />
|
<PostList data={props.postList} />
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="my-5 flex justify-between text-base font-bold">
|
<div className="my-5 flex justify-between font-bold text-base">
|
||||||
{props.pageNumber !== 1 && (
|
{props.pageNumber !== 1 && (
|
||||||
<Button asChild>
|
<Button asChild>
|
||||||
<Link className="font-bold" href={`/tags/${props.tagName}/${props.pageNumber - 1}/`}>
|
<Link className="font-bold" href={`/tags/${props.tagName}/${props.pageNumber - 1}/`}>
|
||||||
@@ -66,9 +66,9 @@ export default function TagsContentPage(props: TagsContentPageProps) {
|
|||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<div className="my-auto font-bold flex justify-center">
|
<div className="my-auto flex justify-center font-bold">
|
||||||
<Input
|
<Input
|
||||||
className="my-auto mx-2 w-11 h-6"
|
className="mx-2 my-auto h-6 w-11"
|
||||||
onChange={handleInputPageNumber}
|
onChange={handleInputPageNumber}
|
||||||
onKeyDown={handleEnterKeyJump}
|
onKeyDown={handleEnterKeyJump}
|
||||||
title="Type the specified page number and press Enter to jump."
|
title="Type the specified page number and press Enter to jump."
|
||||||
@@ -112,7 +112,7 @@ export const getStaticProps: GetStaticProps<TagsContentPageProps> = async (conte
|
|||||||
const params = (context.params?.slug as string[]) ?? [];
|
const params = (context.params?.slug as string[]) ?? [];
|
||||||
|
|
||||||
const tagName = params[0] ?? null;
|
const tagName = params[0] ?? null;
|
||||||
const pageNumber = params[1] ? parseInt(params[1]) : 1;
|
const pageNumber = params[1] ? Number.parseInt(params[1]) : 1;
|
||||||
let postList: TPostListItem[] = [];
|
let postList: TPostListItem[] = [];
|
||||||
|
|
||||||
postList = paginateArray(sortedPosts.postsByTag[tagName], PostCountPerPagination, pageNumber);
|
postList = paginateArray(sortedPosts.postsByTag[tagName], PostCountPerPagination, pageNumber);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
import { UserDataDirectory } from "@/consts/consts";
|
import { UserDataDirectory } from "@/consts/consts";
|
||||||
import { getCurrentTime } from "@/lib/date";
|
import { getCurrentTime } from "@/lib/date";
|
||||||
import { checkAndCreateDirectory, isDirectoryEmptySync } from "@/lib/file";
|
import { checkAndCreateDirectory, isDirectoryEmptySync } from "@/lib/file";
|
||||||
import archiver from "archiver";
|
import archiver from "archiver";
|
||||||
import Color from "colors";
|
import Color from "colors";
|
||||||
import * as fs from "fs";
|
|
||||||
import inquirer from "inquirer";
|
import inquirer from "inquirer";
|
||||||
import * as path from "path";
|
|
||||||
import * as tar from "tar";
|
import * as tar from "tar";
|
||||||
|
|
||||||
function packageDirectory(sourceDir: string, outputFilePath: string) {
|
function packageDirectory(sourceDir: string, outputFilePath: string) {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import { type ChildProcessWithoutNullStreams, type SpawnSyncReturns, spawn, spawnSync } from "child_process";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
import { PostFilesDirectory } from "@/consts/consts";
|
import { PostFilesDirectory } from "@/consts/consts";
|
||||||
import { getCurrentTime } from "@/lib/date";
|
import { getCurrentTime } from "@/lib/date";
|
||||||
import { ChildProcessWithoutNullStreams, SpawnSyncReturns, spawn, spawnSync } from "child_process";
|
|
||||||
import colors from "colors";
|
import colors from "colors";
|
||||||
import fs from "fs";
|
import inquirer, { type QuestionCollection } from "inquirer";
|
||||||
import inquirer, { QuestionCollection } from "inquirer";
|
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import path from "path";
|
|
||||||
import { titleCase } from "title-case";
|
import { titleCase } from "title-case";
|
||||||
|
|
||||||
type TAnswer = {
|
type TAnswer = {
|
||||||
|
|||||||
@@ -19,20 +19,6 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
keyframes: {
|
|
||||||
"accordion-down": {
|
|
||||||
from: { height: "0" },
|
|
||||||
to: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
},
|
|
||||||
"accordion-up": {
|
|
||||||
from: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
to: { height: "0" },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
"accordion-down": "accordion-down 0.2s ease-out",
|
|
||||||
"accordion-up": "accordion-up 0.2s ease-out",
|
|
||||||
},
|
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
fangzhengxiaobiaosong: "--font-fangzhengxiaobiaosong",
|
fangzhengxiaobiaosong: "--font-fangzhengxiaobiaosong",
|
||||||
sourceSerifScreenCN: "--content-font-cn",
|
sourceSerifScreenCN: "--content-font-cn",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { NonEmptyArray } from "./utils.type";
|
import type { NonEmptyArray } from "./utils.type";
|
||||||
|
|
||||||
export type TFrontmatter = {
|
export type TFrontmatter = {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { TFrontmatter } from "./frontmatter.type";
|
import type { TFrontmatter } from "./frontmatter.type";
|
||||||
|
|
||||||
export type TPostListItem = {
|
export type TPostListItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user