From 0db0a0b8e539373a950f2b0b676b720867d74cce Mon Sep 17 00:00:00 2001 From: Imken Luo Date: Sun, 1 Oct 2023 11:06:17 +0800 Subject: [PATCH] fix(viewer): judgements refactor(viewer): svg -> react-icons fix(viewer): using gfm markdown render plugin (to be fixed) NOTICE THAT ESLint NOT PASSED --- packages/viewer/package.json | 2 + .../src/app/(indices)/DiscussionIndex.tsx | 30 +-- .../src/app/(indices)/index/[page]/layout.tsx | 2 +- .../src/app/(indices)/index/[page]/page.tsx | 6 +- .../viewer/src/app/(indices)/popular/page.tsx | 6 +- packages/viewer/src/app/Footer.tsx | 16 +- .../viewer/src/app/about/get-counter-data.ts | 4 +- .../viewer/src/app/explore/Discussions.tsx | 34 +-- packages/viewer/src/app/explore/Users.tsx | 18 +- packages/viewer/src/app/judgement/Ostraca.tsx | 4 +- .../viewer/src/app/judgement/[page]/page.tsx | 9 +- .../viewer/src/app/judgement/data/route.ts | 7 +- packages/viewer/src/app/not-found.tsx | 46 +--- packages/viewer/src/app/page.tsx | 34 +-- .../[uid]/discussions/UserDiscussions.tsx | 29 +-- .../app/user/[uid]/discussions/data/route.ts | 12 +- .../[uid]/participated/UserParticipated.tsx | 114 +++------- packages/viewer/src/components/Ostracon.tsx | 17 +- .../viewer/src/components/replies/Content.tsx | 9 +- .../replies/InfiniteScrollReplies.tsx | 26 +-- .../src/components/replies/PageButtons.tsx | 14 +- .../viewer/src/components/replies/Reply.tsx | 26 +-- packages/viewer/src/lib/time.ts | 2 +- pnpm-lock.yaml | 198 ++++++++++++++++++ 24 files changed, 342 insertions(+), 323 deletions(-) diff --git a/packages/viewer/package.json b/packages/viewer/package.json index 099db2f..5aedb4b 100644 --- a/packages/viewer/package.json +++ b/packages/viewer/package.json @@ -19,9 +19,11 @@ "puppeteer": "^21.3.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-icons": "^4.11.0", "react-infinite-scroll-component": "^6.1.0", "react-markdown": "^9.0.0", "rehype-katex": "^7.0.0", + "remark-gfm": "^4.0.0", "remark-math": "^6.0.0", "socket.io-client": "^4.7.2", "swr": "^2.2.2" diff --git a/packages/viewer/src/app/(indices)/DiscussionIndex.tsx b/packages/viewer/src/app/(indices)/DiscussionIndex.tsx index 5bc1f4d..8e020ea 100644 --- a/packages/viewer/src/app/(indices)/DiscussionIndex.tsx +++ b/packages/viewer/src/app/(indices)/DiscussionIndex.tsx @@ -1,36 +1,26 @@ import stringifyTime from "@/lib/time"; import type { PostWithLatestSnapshotMeta } from "@/lib/post"; import DiscussionEntry from "@/components/DiscussionEntry"; +import { BsChatDots } from "react-icons/bs"; -export default function DiscussionIndex({ - discussions, +export default function PostIndex({ + posts, }: { - discussions: PostWithLatestSnapshotMeta[]; + posts: PostWithLatestSnapshotMeta[]; }) { return ( <> - {discussions.map((discussion) => ( + {posts.map((post) => ( - - - - {" "} - {discussion.replyCount} + {" "} + {post.replyCount} - {stringifyTime(discussion.time)} + {stringifyTime(post.time)} } diff --git a/packages/viewer/src/app/(indices)/index/[page]/layout.tsx b/packages/viewer/src/app/(indices)/index/[page]/layout.tsx index e33c241..de1a76e 100644 --- a/packages/viewer/src/app/(indices)/index/[page]/layout.tsx +++ b/packages/viewer/src/app/(indices)/index/[page]/layout.tsx @@ -9,7 +9,7 @@ export default async function Layout({ }: React.PropsWithChildren<{ params: { page: string } }>) { const page = parseInt(params.page, 10); const numPages = Math.ceil( - (await prisma.discussion.count({ where: { takedown: { is: null } } })) / + (await prisma.post.count({ where: { takedown: { is: null } } })) / NUM_DISCUSSIONS_INDEX, ); const { pagesLocalAttachedFront, pagesLocalAttachedBack, pagesLocal } = diff --git a/packages/viewer/src/app/(indices)/index/[page]/page.tsx b/packages/viewer/src/app/(indices)/index/[page]/page.tsx index 7ff09dd..7f09e83 100644 --- a/packages/viewer/src/app/(indices)/index/[page]/page.tsx +++ b/packages/viewer/src/app/(indices)/index/[page]/page.tsx @@ -1,13 +1,13 @@ import prisma from "@/lib/prisma"; import { getPost } from "@/lib/post"; import { NUM_DISCUSSIONS_INDEX } from "../../constants"; -import DiscussionIndex from "../../DiscussionIndex"; +import PostIndex from "../../DiscussionIndex"; export const metadata = { title: "索引 - 洛谷帖子保存站" }; export default async function Page({ params }: { params: { page: string } }) { const page = parseInt(params.page, 10); - const discussions = await prisma.post.findMany({ + const posts = await prisma.post.findMany({ select: getPost.latestNoContent, where: { takedown: { is: null } }, orderBy: { id: "desc" }, @@ -15,5 +15,5 @@ export default async function Page({ params }: { params: { page: string } }) { take: NUM_DISCUSSIONS_INDEX, }); - return ; + return ; } diff --git a/packages/viewer/src/app/(indices)/popular/page.tsx b/packages/viewer/src/app/(indices)/popular/page.tsx index 349fcc2..34da021 100644 --- a/packages/viewer/src/app/(indices)/popular/page.tsx +++ b/packages/viewer/src/app/(indices)/popular/page.tsx @@ -1,7 +1,7 @@ import prisma from "@/lib/prisma"; import { getPost } from "@/lib/post"; import { NUM_DISCUSSIONS_INDEX } from "../constants"; -import DiscussionIndex from "../DiscussionIndex"; +import PostIndex from "../DiscussionIndex"; export const metadata = { title: "热门 - 洛谷帖子保存站" }; @@ -11,8 +11,8 @@ export default async function MostReplied() { return ( <>

最多回复

- , + params: Omit ) { return ( {" "} ·{" "} - - - {" "} - GitHub + GitHub
diff --git a/packages/viewer/src/app/about/get-counter-data.ts b/packages/viewer/src/app/about/get-counter-data.ts index 1bbee3c..3487148 100644 --- a/packages/viewer/src/app/about/get-counter-data.ts +++ b/packages/viewer/src/app/about/get-counter-data.ts @@ -2,8 +2,8 @@ import prisma from "@/lib/prisma"; export default async function getCounterData() { return { - discussions: await prisma.discussion.count(), - snapshots: await prisma.snapshot.count(), + discussions: await prisma.post.count(), + snapshots: await prisma.postSnapshot.count(), replies: await prisma.reply.count(), judgements: await prisma.judgement.count(), }; diff --git a/packages/viewer/src/app/explore/Discussions.tsx b/packages/viewer/src/app/explore/Discussions.tsx index e428b83..57fc105 100644 --- a/packages/viewer/src/app/explore/Discussions.tsx +++ b/packages/viewer/src/app/explore/Discussions.tsx @@ -2,14 +2,15 @@ import prisma from "@/lib/prisma"; import stringifyTime from "@/lib/time"; import { getPost } from "@/lib/post"; import DiscussionEntry from "@/components/DiscussionEntry"; +import { BsCalendar4Week, BsChatDots } from "react-icons/bs"; const NUM_DISCUSSIONS_HOME_PAGE = parseInt( process.env.NUM_DISCUSSIONS_HOME_PAGE ?? "50", - 10, + 10 ); const LIMIT_MILLISECONDS_HOT_DISCUSSION = parseInt( process.env.NUM_DISCUSSIONS_HOME_PAGE ?? "604800000", - 10, + 10 ); export default async function Discussions() { @@ -31,7 +32,7 @@ export default async function Discussions() { select: getPost.latestNoContent, where: { id: { in: discussionReplyCount.map((r) => r.postId) } }, }) - ).map((d) => [d.id, d]), + ).map((d) => [d.id, d]) ); discussionReplyCount.map((r) => ({ ...discussions[r.postId], @@ -51,31 +52,18 @@ export default async function Discussions() { ellipsis metaBottom={ <> - - - - {" "} + />{" "} {discussion.replyCount} - - - - {" "} + />{" "} {discussion.recentReplyCount} {stringifyTime(discussion.time)} diff --git a/packages/viewer/src/app/explore/Users.tsx b/packages/viewer/src/app/explore/Users.tsx index 665c9de..e355765 100644 --- a/packages/viewer/src/app/explore/Users.tsx +++ b/packages/viewer/src/app/explore/Users.tsx @@ -1,33 +1,37 @@ import prisma from "@/lib/prisma"; import UserInfo from "@/components/UserInfo"; +import { selectUser } from "@/lib/user"; const NUM_WATER_TANKS_HOME_PAGE = parseInt( process.env.NUM_DISCUSSIONS_HOME_PAGE ?? "100", - 10, + 10 ); const RANGE_MILLISECONDS_WATER_TANK = parseInt( process.env.RANGE_MILLISECONDS_WATER_TANK ?? "604800000", - 10, + 10 ); export default async function Users() { - const userReplyCount = await prisma.reply.groupBy({ + const userReplyCount = await prisma.replySnapshot.groupBy({ by: ["authorId"], where: { - time: { - gte: new Date(new Date().getTime() - RANGE_MILLISECONDS_WATER_TANK), + reply: { + time: { + gte: new Date(new Date().getTime() - RANGE_MILLISECONDS_WATER_TANK), + } }, }, _count: true, - orderBy: { _count: { id: "desc" } }, + orderBy: { _count: { time: "desc" } }, take: NUM_WATER_TANKS_HOME_PAGE, }); const users = Object.fromEntries( ( await prisma.user.findMany({ where: { id: { in: userReplyCount.map((r) => r.authorId) } }, + select: selectUser.withLatest, }) - ).map((u) => [u.id, u]), + ).map((u) => [u.id, u]) ); return (
    diff --git a/packages/viewer/src/app/judgement/Ostraca.tsx b/packages/viewer/src/app/judgement/Ostraca.tsx index a070a73..86cdc5e 100644 --- a/packages/viewer/src/app/judgement/Ostraca.tsx +++ b/packages/viewer/src/app/judgement/Ostraca.tsx @@ -1,14 +1,14 @@ "use client"; import useSWRInfinite from "swr/infinite"; -import type { User } from "@prisma/client"; import InfiniteScroll from "react-infinite-scroll-component"; import fetcher from "@/lib/fetcher"; import Spinner from "@/components/Spinner"; import Ostracon from "@/components/Ostracon"; +import { LatestUser } from "@/lib/user"; interface PageData { - data: { user: User; time: string; content: string }[]; + data: { user: LatestUser; time: string; content: string }[]; nextCursor: string; } diff --git a/packages/viewer/src/app/judgement/[page]/page.tsx b/packages/viewer/src/app/judgement/[page]/page.tsx index 8299573..d65cf5e 100644 --- a/packages/viewer/src/app/judgement/[page]/page.tsx +++ b/packages/viewer/src/app/judgement/[page]/page.tsx @@ -3,6 +3,7 @@ import prisma from "@/lib/prisma"; import paginate from "@/lib/pagination"; import PageButtons from "@/components/replies/PageButtons"; import Ostracon from "@/components/Ostracon"; +import { selectUser } from "@/lib/user"; const OSTRACA_PER_PAGE = parseInt(process.env.OSTRACA_PER_PAGE ?? "10", 10); @@ -10,14 +11,18 @@ export default async function Page({ params }: { params: { page: string } }) { const page = parseInt(params.page, 10); const ostraca = (await prisma.judgement.findMany({ - select: { time: true, user: true, content: true }, + select: { + time: true, + user: { select: selectUser.withLatest }, + content: true, + }, orderBy: { time: "desc" }, skip: (page - 1) * OSTRACA_PER_PAGE, take: OSTRACA_PER_PAGE, })) ?? notFound(); const numPages = Math.ceil( - (await prisma.judgement.count()) / OSTRACA_PER_PAGE, + (await prisma.judgement.count()) / OSTRACA_PER_PAGE ); const { pagesLocalAttachedFront, pagesLocalAttachedBack, pagesLocal } = diff --git a/packages/viewer/src/app/judgement/data/route.ts b/packages/viewer/src/app/judgement/data/route.ts index 384e960..b8a16d2 100644 --- a/packages/viewer/src/app/judgement/data/route.ts +++ b/packages/viewer/src/app/judgement/data/route.ts @@ -1,12 +1,17 @@ import { NextResponse, type NextRequest } from "next/server"; import prisma from "@/lib/prisma"; +import { selectUser } from "@/lib/user"; const OSTRACA_PER_PAGE = parseInt(process.env.OSTRACA_PER_PAGE ?? "10", 10); export async function GET(request: NextRequest) { const cursor = request.nextUrl.searchParams.get("cursor"); const judgements = await prisma.judgement.findMany({ - select: { user: true, time: true, content: true }, + select: { + user: { select: selectUser.withLatest }, + time: true, + content: true, + }, // TODO: Unique filter (userId & time) where: { time: { lt: cursor ? new Date(cursor) : undefined } }, take: OSTRACA_PER_PAGE, diff --git a/packages/viewer/src/app/not-found.tsx b/packages/viewer/src/app/not-found.tsx index 1cc9c3e..3b94dec 100644 --- a/packages/viewer/src/app/not-found.tsx +++ b/packages/viewer/src/app/not-found.tsx @@ -2,6 +2,7 @@ import { useParams, usePathname } from "next/navigation"; import UpdateButton from "@/components/UpdateButton"; +import { BsDatabaseX, BsJournalCode, BsThreeDots } from "react-icons/bs"; export default function Page() { const pathname = usePathname(); @@ -14,49 +15,22 @@ export default function Page() {
    {Number.isNaN(parseInt(pathname.slice(1), 10)) ? ( <> - - - {" "} - + /> 数据被 fx 酱啃食了 - - - + /> ) : ( <> - - - - {" "} - + /> 帖子还没有保存哦 )} diff --git a/packages/viewer/src/app/page.tsx b/packages/viewer/src/app/page.tsx index f35a083..cfae59d 100644 --- a/packages/viewer/src/app/page.tsx +++ b/packages/viewer/src/app/page.tsx @@ -1,3 +1,4 @@ +import { BsCursorFill, BsHddStackFill, BsStars } from "react-icons/bs"; import SaveInput from "./SaveInput"; export const metadata = { title: "保存帖子 - 洛谷帖子保存站" }; @@ -13,16 +14,7 @@ export default function Page() {
    - - - +

    更赏心悦目的界面

    @@ -32,16 +24,7 @@ export default function Page() {

    - - - +

    更稳定的爬取器

    @@ -50,16 +33,7 @@ export default function Page() {

    - - - +

    更方便的体验

    diff --git a/packages/viewer/src/app/user/[uid]/discussions/UserDiscussions.tsx b/packages/viewer/src/app/user/[uid]/discussions/UserDiscussions.tsx index 9f22904..e2e8955 100644 --- a/packages/viewer/src/app/user/[uid]/discussions/UserDiscussions.tsx +++ b/packages/viewer/src/app/user/[uid]/discussions/UserDiscussions.tsx @@ -3,18 +3,16 @@ import useSWRInfinite from "swr/infinite"; import InfiniteScroll from "react-infinite-scroll-component"; import type { PostWithLatestContent } from "@/lib/post"; -import type { UserMetioned } from "@/lib/serialize-reply"; +// import type { UserMetioned } from "@/lib/serialize-reply"; import Content from "@/components/replies/Content"; import fetcher from "@/lib/fetcher"; import Spinner from "@/components/Spinner"; import DiscussionEntry from "@/components/DiscussionEntry"; +import { BsChatDots } from "react-icons/bs"; +import stringifyTime from "@/lib/time"; interface PageData { - data: (PostWithLatestContent & { - content: string; - time: string; - usersMetioned: UserMetioned[]; - })[]; + data: PostWithLatestContent[]; nextCursor: number; } @@ -26,7 +24,7 @@ export default function UserDiscussions({ uid }: { uid: string }) { : `/user/${uid}/discussions/data${ pageIndex ? `?cursor=${previousPageData.nextCursor}` : "" }`, - fetcher, + fetcher ); return ( @@ -52,30 +50,23 @@ export default function UserDiscussions({ uid }: { uid: string }) { decoratorBreakpoint="md" metaBottom={ <> - - - - {" "} + />{" "} {discussion.replyCount} - {discussion.time} + {stringifyTime(discussion.time)} } > - )), + )) )} {isValidating && } diff --git a/packages/viewer/src/app/user/[uid]/discussions/data/route.ts b/packages/viewer/src/app/user/[uid]/discussions/data/route.ts index d4a03cb..fda6289 100644 --- a/packages/viewer/src/app/user/[uid]/discussions/data/route.ts +++ b/packages/viewer/src/app/user/[uid]/discussions/data/route.ts @@ -1,7 +1,7 @@ import { NextResponse, type NextRequest } from "next/server"; import prisma from "@/lib/prisma"; import { getPost } from "@/lib/post"; -import serializeReply from "@/lib/serialize-reply"; +// import serializeReply from "@/lib/serialize-reply"; import { NUM_PER_PAGE } from "../../constants"; export async function GET( @@ -21,15 +21,7 @@ export async function GET( take: NUM_PER_PAGE, }); return NextResponse.json({ - data: await Promise.all( - posts.map(async (post) => ({ - ...post, - ...(await serializeReply(post.id, { - content: post.snapshots[0].content, - time: post.time, - })), - })), - ), + data: posts, nextCursor: posts.length ? posts[posts.length - 1].id : null, }); } diff --git a/packages/viewer/src/app/user/[uid]/participated/UserParticipated.tsx b/packages/viewer/src/app/user/[uid]/participated/UserParticipated.tsx index 86072f0..2a6e7bf 100644 --- a/packages/viewer/src/app/user/[uid]/participated/UserParticipated.tsx +++ b/packages/viewer/src/app/user/[uid]/participated/UserParticipated.tsx @@ -14,6 +14,14 @@ import { NUM_MAX_REPLIES_SHOWED_DEFAULT } from "../constants"; import { LatestUser } from "@/lib/user"; import { ReplyWithLatestContentPostMeta } from "@/lib/reply"; import stringifyTime from "@/lib/time"; +import { + BsArchive, + BsArrowUpRight, + BsChatDots, + BsDatabaseSlash, + BsJournalBookmark, + BsThreeDots, +} from "react-icons/bs"; interface PageData { data: (PostWithLatestContent & { @@ -93,36 +101,17 @@ export default function UserParticipated({ className="link-secondary" style={{ fontSize: ".9rem" }} > - - - - {" "} - + /> 查看 隐藏 正文 - - - + /> - - - + /> 在该帖子下回复了 {discussion.replies.length} 层 - - - + />

    @@ -200,23 +175,7 @@ export default function UserParticipated({ className="ms-2 link-secondary position-relative" style={{ fontSize: ".8em", top: "-.2em" }} > - - - - +
    @@ -246,18 +205,10 @@ export default function UserParticipated({ className="text-secondary" style={{ fontSize: ".9rem" }} > - - - - + /> 未在该帖子下回复
    @@ -266,20 +217,13 @@ export default function UserParticipated({ className="text-body-tertiary mt-1" style={{ fontSize: ".8rem" }} > - - - - {" "} + />{" "} {discussion.replyCount} - {stringifyTime(discussion.time)} + + {stringifyTime(discussion.time)} +
diff --git a/packages/viewer/src/components/Ostracon.tsx b/packages/viewer/src/components/Ostracon.tsx index d4ee03b..7239526 100644 --- a/packages/viewer/src/components/Ostracon.tsx +++ b/packages/viewer/src/components/Ostracon.tsx @@ -1,6 +1,7 @@ import UserAvatar from "@/components/UserAvatar"; import UserInfo from "@/components/UserInfo"; import type { LatestUser } from "@/lib/user"; +import { BsArrowReturnRight } from "react-icons/bs"; export default function Ostracon({ ostracon, @@ -23,21 +24,7 @@ export default function Ostracon({ {/* eslint-disable-next-line react/no-danger */}
- {/* TODO: icon font instead of svg */} - - - {" "} - + + > + {content} + {/* {usersMetioned.map((user) => (
{ diff --git a/packages/viewer/src/components/replies/InfiniteScrollReplies.tsx b/packages/viewer/src/components/replies/InfiniteScrollReplies.tsx index f861b64..6689c7b 100644 --- a/packages/viewer/src/components/replies/InfiniteScrollReplies.tsx +++ b/packages/viewer/src/components/replies/InfiniteScrollReplies.tsx @@ -3,13 +3,14 @@ import { useState } from "react"; import useSWRInfinite from "swr/infinite"; import InfiniteScroll from "react-infinite-scroll-component"; -import type { User } from "@prisma/client"; -import type { UserMetioned } from "@/lib/serialize-reply"; +// import type { User } from "@prisma/client"; +// import type { UserMetioned } from "@/lib/serialize-reply"; import fetcher from "@/lib/fetcher"; import Spinner from "@/components/Spinner"; import PageButtons from "./PageButtons"; import Reply from "./Reply"; import { ReplyWithLatestContent } from "@/lib/reply"; +import { BsThreeDots } from "react-icons/bs"; interface PageData { replies: ReplyWithLatestContent[]; @@ -42,7 +43,7 @@ export default function InfiniteScrollReplies({ }) { const { data, size, setSize, isValidating } = useSWRInfinite( getKey(discussion.id), - fetcher, + fetcher ); const [showPageButtons, setShowPageButtons] = useState(true); @@ -51,7 +52,9 @@ export default function InfiniteScrollReplies({ c + a.replies.length, 0) ?? 0} next={() => showPageButtons || setSize(size + 1)} - hasMore={(data?.[data.length - 1].replies.length ?? 0) >= REPLIES_PER_PAGE} + hasMore={ + (data?.[data.length - 1].replies.length ?? 0) >= REPLIES_PER_PAGE + } loader="" style={{ overflow: "inherit" }} scrollThreshold="1024px" @@ -60,7 +63,7 @@ export default function InfiniteScrollReplies({ (data) => data.replies?.map((reply) => ( - )), + )) )} @@ -78,17 +81,10 @@ export default function InfiniteScrollReplies({ type="button" > 加载更多 - - - + />
- - - ); + const ellipsis = ; return ( <> diff --git a/packages/viewer/src/components/replies/Reply.tsx b/packages/viewer/src/components/replies/Reply.tsx index 74b825b..b553b55 100644 --- a/packages/viewer/src/components/replies/Reply.tsx +++ b/packages/viewer/src/components/replies/Reply.tsx @@ -11,6 +11,7 @@ import ContextViewer from "./ContextViewer"; import type { ReplyWithLatestContent } from "@/lib/reply"; import stringifyTime from "@/lib/time"; +import { BsBoxArrowUpRight } from "react-icons/bs"; export default function Reply({ post, @@ -21,7 +22,7 @@ export default function Reply({ reply: ReplyWithLatestContent; }>) { const [userId, setUserId] = useState(null); - const snapshot = reply.snapshots[0] + const snapshot = reply.snapshots[0]; return (
- {stringifyTime(reply.time)} + + {stringifyTime(reply.time)} + {reply.id !== -1 ? ( - {/* TODO: svg to iconfont */} - - - - + ) : undefined} diff --git a/packages/viewer/src/lib/time.ts b/packages/viewer/src/lib/time.ts index cf5b8c4..683d40e 100644 --- a/packages/viewer/src/lib/time.ts +++ b/packages/viewer/src/lib/time.ts @@ -1,3 +1,3 @@ export default function stringifyTime(time: Date) { - return time.toLocaleString("zh").split(":", 2).join(":"); + return new Date(time).toLocaleString("zh").split(":", 2).join(":"); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f56a0c..2eeeb56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,6 +128,9 @@ importers: react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + react-icons: + specifier: ^4.11.0 + version: 4.11.0(react@18.2.0) react-infinite-scroll-component: specifier: ^6.1.0 version: 6.1.0(react@18.2.0) @@ -137,6 +140,9 @@ importers: rehype-katex: specifier: ^7.0.0 version: 7.0.0 + remark-gfm: + specifier: ^4.0.0 + version: 4.0.0 remark-math: specifier: ^6.0.0 version: 6.0.0 @@ -1442,6 +1448,10 @@ packages: /caniuse-lite@1.0.30001538: resolution: {integrity: sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==} + /ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: false + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -2055,6 +2065,11 @@ packages: engines: {node: '>=10'} dev: true + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: false + /escodegen@2.1.0: resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} engines: {node: '>=6.0'} @@ -3615,6 +3630,19 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} + /markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + dev: false + + /mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + dependencies: + '@types/mdast': 4.0.1 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + /mdast-util-from-markdown@2.0.0: resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} dependencies: @@ -3634,6 +3662,75 @@ packages: - supports-color dev: false + /mdast-util-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + dependencies: + '@types/mdast': 4.0.1 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.0.1 + dev: false + + /mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + dependencies: + '@types/mdast': 4.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + dependencies: + '@types/mdast': 4.0.1 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + dependencies: + '@types/mdast': 4.0.1 + devlop: 1.1.0 + markdown-table: 3.0.3 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + dependencies: + '@types/mdast': 4.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + dependencies: + mdast-util-from-markdown: 2.0.0 + mdast-util-gfm-autolink-literal: 2.0.0 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + /mdast-util-math@3.0.0: resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} dependencies: @@ -3717,6 +3814,78 @@ packages: micromark-util-types: 2.0.0 dev: false + /micromark-extension-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-footnote@2.0.0: + resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-table@2.0.0: + resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + dependencies: + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-task-list-item@2.0.1: + resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + dependencies: + micromark-extension-gfm-autolink-literal: 2.0.0 + micromark-extension-gfm-footnote: 2.0.0 + micromark-extension-gfm-strikethrough: 2.0.0 + micromark-extension-gfm-table: 2.0.0 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.0.1 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + /micromark-extension-math@3.0.0: resolution: {integrity: sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ==} dependencies: @@ -4522,6 +4691,14 @@ packages: scheduler: 0.23.0 dev: false + /react-icons@4.11.0(react@18.2.0): + resolution: {integrity: sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA==} + peerDependencies: + react: '*' + dependencies: + react: 18.2.0 + dev: false + /react-infinite-scroll-component@6.1.0(react@18.2.0): resolution: {integrity: sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==} peerDependencies: @@ -4635,6 +4812,19 @@ packages: vfile: 6.0.1 dev: false + /remark-gfm@4.0.0: + resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + dependencies: + '@types/mdast': 4.0.1 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.3 + transitivePeerDependencies: + - supports-color + dev: false + /remark-math@6.0.0: resolution: {integrity: sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==} dependencies: @@ -4667,6 +4857,14 @@ packages: vfile: 6.0.1 dev: false + /remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + dependencies: + '@types/mdast': 4.0.1 + mdast-util-to-markdown: 2.1.0 + unified: 11.0.3 + dev: false + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'}