From b945fe0659cae301a41034f21b31e78e88ef5302 Mon Sep 17 00:00:00 2001 From: alikia2x Date: Mon, 9 Jun 2025 19:35:47 +0800 Subject: [PATCH] add: foundation for MDX content rendering, bio section in user profile page --- .../next/app/[locale]/about/AboutContent.tsx | 8 - packages/next/app/[locale]/about/page.tsx | 7 +- packages/next/app/[locale]/global.css | 6 +- packages/next/app/[locale]/layout.tsx | 8 +- .../user/[uid]/profile/LogoutButton.tsx | 10 +- .../app/[locale]/user/[uid]/profile/page.tsx | 13 +- packages/next/bun.lock | 196 +++- packages/next/components/shell/Background.tsx | 26 + packages/next/components/shell/Content.tsx | 83 ++ .../next/components/shell/ContentClient.tsx | 73 ++ .../about => components/shell}/content.css | 4 + packages/next/components/ui/Dialog.tsx | 2 +- packages/next/content/about.mdx | 60 -- packages/next/lib/mdx/SafeMDX.tsx | 982 ++++++++++++++++++ packages/next/lib/mdx/footnoteHelper.tsx | 63 ++ packages/next/lib/state/background.ts | 3 + packages/next/next.config.ts | 7 +- packages/next/package.json | 10 + packages/next/source.config.ts | 5 - 19 files changed, 1468 insertions(+), 98 deletions(-) delete mode 100644 packages/next/app/[locale]/about/AboutContent.tsx create mode 100644 packages/next/components/shell/Background.tsx create mode 100644 packages/next/components/shell/Content.tsx create mode 100644 packages/next/components/shell/ContentClient.tsx rename packages/next/{app/[locale]/about => components/shell}/content.css (89%) delete mode 100644 packages/next/content/about.mdx create mode 100644 packages/next/lib/mdx/SafeMDX.tsx create mode 100644 packages/next/lib/mdx/footnoteHelper.tsx create mode 100644 packages/next/lib/state/background.ts delete mode 100644 packages/next/source.config.ts diff --git a/packages/next/app/[locale]/about/AboutContent.tsx b/packages/next/app/[locale]/about/AboutContent.tsx deleted file mode 100644 index 3078076..0000000 --- a/packages/next/app/[locale]/about/AboutContent.tsx +++ /dev/null @@ -1,8 +0,0 @@ -"use client"; - -import About from "@/content/about.mdx"; -import "./content.css"; - -export default function AboutContent() { - return ; -} diff --git a/packages/next/app/[locale]/about/page.tsx b/packages/next/app/[locale]/about/page.tsx index c352a67..b0e967f 100644 --- a/packages/next/app/[locale]/about/page.tsx +++ b/packages/next/app/[locale]/about/page.tsx @@ -1,15 +1,16 @@ import { Header } from "@/components/shell/Header"; import { getCurrentUser } from "@/lib/userAuth"; -import AboutContent from "./AboutContent"; +import { Content } from "@/components/shell/Content"; export default async function AboutPage() { const user = await getCurrentUser(); + return ( <>
-
- +
+
diff --git a/packages/next/app/[locale]/global.css b/packages/next/app/[locale]/global.css index 57d07a6..6657449 100644 --- a/packages/next/app/[locale]/global.css +++ b/packages/next/app/[locale]/global.css @@ -101,6 +101,10 @@ a { :root { font-family: "Inter Variable", "MiSans VF", sans-serif; font-optical-sizing: auto; - font-weight: 330; + font-weight: 280; } } + +.content-box { + @apply bg-background/80 dark:bg-dark-background/80 rounded-lg; +} diff --git a/packages/next/app/[locale]/layout.tsx b/packages/next/app/[locale]/layout.tsx index 5e6d24b..005d1e4 100644 --- a/packages/next/app/[locale]/layout.tsx +++ b/packages/next/app/[locale]/layout.tsx @@ -4,6 +4,7 @@ import React from "react"; import { routing } from "@/i18n/routing"; import { hasLocale } from "next-intl"; import { notFound } from "next/navigation"; +import { Background } from "@/components/shell/Background"; export const metadata: Metadata = { title: "中 V 档案馆" @@ -20,5 +21,10 @@ export default async function RootLayout({ if (!hasLocale(routing.locales, locale)) { notFound(); } - return <>{children}; + return ( + <> + + {children} + + ); } diff --git a/packages/next/app/[locale]/user/[uid]/profile/LogoutButton.tsx b/packages/next/app/[locale]/user/[uid]/profile/LogoutButton.tsx index cab7781..1c33bb2 100644 --- a/packages/next/app/[locale]/user/[uid]/profile/LogoutButton.tsx +++ b/packages/next/app/[locale]/user/[uid]/profile/LogoutButton.tsx @@ -1,6 +1,6 @@ "use client"; -import { FilledButton } from "@/components/ui/Buttons/FilledButton"; +import { TextButton } from "@/components/ui/Buttons/TextButton"; import { Dialog, DialogButton, DialogButtonGroup, DialogHeadline, DialogSupportingText } from "@/components/ui/Dialog"; import { Portal } from "@/components/utils/Portal"; import { useRouter } from "@/i18n/navigation"; @@ -11,13 +11,9 @@ export const LogoutButton: React.FC = () => { const router = useRouter(); return ( <> - setShowDialog(true)} - > + setShowDialog(true)}> 登出 - + 确认登出 diff --git a/packages/next/app/[locale]/user/[uid]/profile/page.tsx b/packages/next/app/[locale]/user/[uid]/profile/page.tsx index 727f2f4..2ec7b27 100644 --- a/packages/next/app/[locale]/user/[uid]/profile/page.tsx +++ b/packages/next/app/[locale]/user/[uid]/profile/page.tsx @@ -6,6 +6,8 @@ import { LogoutButton } from "./LogoutButton"; import { numeric } from "yup-numeric"; import { getTranslations } from "next-intl/server"; import HeaderServer from "@/components/shell/HeaderServer"; +import { Content } from "@/components/shell/Content"; +import { ContentClient } from "@/components/shell/ContentClient"; const uidSchema = numeric().integer().min(0); @@ -49,16 +51,19 @@ export default async function ProfilePage({ params }: { params: Promise<{ uid: s return ( <> -
-

+
+

{displayName} UID{user.uid} +
{loggedIn && }

-

权限组:{t(`role.${user.role}`)}

- {loggedIn && } +

权限组:{t(`role.${user.role}`)}

+ +

个人简介

+
); diff --git a/packages/next/bun.lock b/packages/next/bun.lock index 12ef429..3662371 100644 --- a/packages/next/bun.lock +++ b/packages/next/bun.lock @@ -18,11 +18,21 @@ "jotai": "^2.12.5", "next": "^15.3.3", "next-intl": "^4.1.0", + "next-mdx-remote": "^5.0.0", "raw-loader": "^4.0.2", "react": "^19.1.0", "react-dom": "^19.1.0", + "rehype-sanitize": "^6.0.0", + "rehype-stringify": "^10.0.1", + "remark-comment": "^1.0.0", + "remark-comments": "^1.2.10", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-remove-comments": "^1.1.1", + "safe-mdx": "^0.1.0", "swr": "^2.3.3", "ua-parser-js": "^2.0.3", + "unified": "^11.0.5", "yup": "^1.6.1", "yup-numeric": "^0.5.0", }, @@ -41,8 +51,20 @@ "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + + "@babel/generator": ["@babel/generator@7.27.5", "", { "dependencies": { "@babel/parser": "^7.27.5", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], + "@babel/runtime": ["@babel/runtime@7.27.4", "", {}, "sha512-t3yaEOuGu9NlIZ+hIeGbBjFtZT7j2cb2tg0fuaJKeGotchRjjLfrBA9Kwf8quhpP1EUuxModQg04q/mBwyg8uA=="], + "@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], + "@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="], "@cvsa/backend": ["@cvsa/backend@0.5.3", "", { "dependencies": { "@rabbit-company/argon2id": "^2.1.0", "hono": "^4.7.8", "hono-rate-limiter": "^0.4.2", "ioredis": "^5.6.1", "limiter": "^3.0.0", "postgres": "^3.4.5", "rate-limit-redis": "^4.2.0", "yup": "^1.6.1", "zod": "^3.24.3" } }, "sha512-RzGjarU2TOzD6/d6qikE4xd/ZqNQl3jOYtgfJg5kbWFuiXnOgEC9QBTi+adzjmaWFrcpuYck6ooWpg4eT3s43g=="], @@ -501,6 +523,8 @@ "enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="], + "entities": ["entities@6.0.0", "", {}, "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw=="], + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], @@ -565,6 +589,8 @@ "fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="], + "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], + "fdir": ["fdir@6.4.5", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw=="], "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="], @@ -583,6 +609,8 @@ "form-data": ["form-data@4.0.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w=="], + "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], "framer-motion": ["framer-motion@12.15.0", "", { "dependencies": { "motion-dom": "^12.15.0", "motion-utils": "^12.12.1", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-XKg/LnKExdLGugZrDILV7jZjI599785lDIJZLxMiiIFidCsy0a4R2ZEf+Izm67zyOuJgQYTHOmodi7igQsw3vg=="], @@ -631,6 +659,8 @@ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "hast-util-sanitize": ["hast-util-sanitize@5.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "unist-util-position": "^5.0.0" } }, "sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg=="], + "hast-util-to-estree": ["hast-util-to-estree@3.1.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-attach-comments": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w=="], "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], @@ -647,6 +677,12 @@ "hono-rate-limiter": ["hono-rate-limiter@0.4.2", "", { "peerDependencies": { "hono": "^4.1.1" } }, "sha512-AAtFqgADyrmbDijcRTT/HJfwqfvhalya2Zo+MgfdrMPas3zSMD8SU03cv+ZsYwRU1swv7zgVt0shwN059yzhjw=="], + "html-comment-regex": ["html-comment-regex@1.1.2", "", {}, "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ=="], + + "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="], + + "html-to-jsx-transform": ["html-to-jsx-transform@1.2.1", "", { "dependencies": { "@babel/generator": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1", "html-entities": "^2.6.0", "parse5": "^7.3.0", "style-to-object": "^1.0.8" } }, "sha512-R+pCOjwD+5UKd1624vjKCVhkeluxs7Nat70zTxMWKY1LKMN9Zwl+leQmbnFBO5Z3b1sQ1At2CK47+zDRGeo/1A=="], + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], @@ -707,8 +743,12 @@ "jotai": ["jotai@2.12.5", "", { "peerDependencies": { "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@types/react", "react"] }, "sha512-G8m32HW3lSmcz/4mbqx0hgJIQ0ekndKWiYP7kWVKi0p6saLXdSoye+FZiOFyonnd7Q482LCzm8sMDl7Ar1NWDw=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], @@ -775,6 +815,8 @@ "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="], + "mdast-util-frontmatter": ["mdast-util-frontmatter@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "escape-string-regexp": "^5.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0" } }, "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA=="], + "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "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.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="], "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="], @@ -813,6 +855,8 @@ "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], + "micromark-extension-frontmatter": ["micromark-extension-frontmatter@2.0.0", "", { "dependencies": { "fault": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg=="], + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "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.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], @@ -843,13 +887,13 @@ "micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ=="], - "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + "micromark-factory-space": ["micromark-factory-space@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ=="], "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="], - "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + "micromark-util-character": ["micromark-util-character@1.2.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg=="], "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="], @@ -875,7 +919,7 @@ "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="], - "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + "micromark-util-symbol": ["micromark-util-symbol@1.1.0", "", {}, "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag=="], "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], @@ -909,6 +953,8 @@ "next-intl": ["next-intl@4.1.0", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.5.4", "negotiator": "^1.0.0", "use-intl": "^4.1.0" }, "peerDependencies": { "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0", "typescript": "^5.0.0" }, "optionalPeers": ["typescript"] }, "sha512-JNJRjc7sdnfUxhZmGcvzDszZ60tQKrygV/VLsgzXhnJDxQPn1cN2rVpc53adA1SvBJwPK2O6Sc6b4gYSILjCzw=="], + "next-mdx-remote": ["next-mdx-remote@5.0.0", "", { "dependencies": { "@babel/code-frame": "^7.23.5", "@mdx-js/mdx": "^3.0.1", "@mdx-js/react": "^3.0.1", "unist-util-remove": "^3.1.0", "vfile": "^6.0.1", "vfile-matter": "^5.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ=="], + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], @@ -933,6 +979,8 @@ "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], + "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], @@ -1005,8 +1053,18 @@ "rehype-recma": ["rehype-recma@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "hast-util-to-estree": "^3.0.0" } }, "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw=="], + "rehype-sanitize": ["rehype-sanitize@6.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-sanitize": "^5.0.0" } }, "sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg=="], + + "rehype-stringify": ["rehype-stringify@10.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-html": "^9.0.0", "unified": "^11.0.0" } }, "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA=="], + "remark": ["remark@15.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A=="], + "remark-comment": ["remark-comment@1.0.0", "", { "dependencies": { "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.1.0", "micromark-util-symbol": "^1.0.1" } }, "sha512-k8YPo5MGvl8l4gGxOH6Zk4Fa2AhDACN5eqKnKZcHDORZQS15hlnezlBHj2lqyDiqzApNmYOMTibkEJbMSKU25w=="], + + "remark-comments": ["remark-comments@1.2.10", "", {}, "sha512-huQW1qMsVLT4bJP1bOUBXtZH9U9L9jN5gaqKRLWyHB5vFm55F1YZ25mqk6RcBIgdrklPYnVCJD6CcaLS9w/jwQ=="], + + "remark-frontmatter": ["remark-frontmatter@5.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-frontmatter": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0", "unified": "^11.0.0" } }, "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ=="], + "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "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.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], "remark-mdx": ["remark-mdx@3.1.0", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA=="], @@ -1015,6 +1073,8 @@ "remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="], + "remark-remove-comments": ["remark-remove-comments@1.1.1", "", { "dependencies": { "html-comment-regex": "^1.1.2", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" } }, "sha512-Z0OONcdhf3I7lKJcR3TRCKqpgGnhugtn/xBWdPZuEpLm67y5hf7Z0CI4p8j6zq1uX2koyUxo2O6y2MNZyPA0JA=="], + "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], @@ -1025,6 +1085,8 @@ "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "safe-mdx": ["safe-mdx@0.1.0", "", { "dependencies": { "collapse-white-space": "^2.1.0", "html-to-jsx-transform": "^1.0.0", "remark": "^15.0.1", "remark-frontmatter": "^5.0.0", "remark-gfm": "^4.0.0", "remark-mdx": "^3.0.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "react": "*" } }, "sha512-U0BW0kGNuVj69Lsj8LpqSaLQ9uNaD+jAM/JPY9HGUsapunL8dr+0tnS0wQPpj+dkNScAL4GJ3/ICQ2sigmnunw=="], + "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], @@ -1157,6 +1219,8 @@ "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="], + "unist-util-remove": ["unist-util-remove@3.1.1", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.0.0" } }, "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw=="], + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], @@ -1183,6 +1247,8 @@ "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + "vfile-matter": ["vfile-matter@5.0.1", "", { "dependencies": { "vfile": "^6.0.0", "yaml": "^2.0.0" } }, "sha512-o6roP82AiX0XfkyTHyRCMXgHfltUNlXSEqCIS80f+mbAyiQBE2fxtDVMtseyytGx75sihiJFo/zR6r/4LTs2Cw=="], + "vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="], "watchpack": ["watchpack@2.4.4", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA=="], @@ -1209,6 +1275,8 @@ "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], + "yaml": ["yaml@2.8.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ=="], + "yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], "yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], @@ -1259,6 +1327,120 @@ "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + "mdast-util-from-markdown/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "mdast-util-gfm-autolink-literal/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-core-commonmark/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-core-commonmark/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-core-commonmark/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-frontmatter/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-frontmatter/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-gfm-autolink-literal/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-gfm-autolink-literal/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-gfm-footnote/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-extension-gfm-footnote/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-gfm-footnote/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-gfm-strikethrough/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-gfm-table/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-extension-gfm-table/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-gfm-table/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-gfm-task-list-item/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-extension-gfm-task-list-item/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-gfm-task-list-item/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-mdx-expression/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-extension-mdx-expression/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-mdx-expression/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-mdx-jsx/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-extension-mdx-jsx/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-mdx-jsx/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-extension-mdxjs-esm/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-extension-mdxjs-esm/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-factory-destination/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-factory-destination/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-factory-label/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-factory-label/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-factory-mdx-expression/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-factory-mdx-expression/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-factory-mdx-expression/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-factory-space/micromark-util-types": ["micromark-util-types@1.1.0", "", {}, "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg=="], + + "micromark-factory-title/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-factory-title/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-factory-title/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-factory-whitespace/micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-factory-whitespace/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-factory-whitespace/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-character/micromark-util-types": ["micromark-util-types@1.1.0", "", {}, "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg=="], + + "micromark-util-chunked/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-classify-character/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-classify-character/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-decode-numeric-character-reference/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-decode-string/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-decode-string/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-events-to-acorn/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-normalize-identifier/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-sanitize-uri/micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-sanitize-uri/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-subtokenize/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + "mocha/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], @@ -1273,6 +1455,12 @@ "type-is/mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="], + "unist-util-remove/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "unist-util-remove/unist-util-is": ["unist-util-is@5.2.1", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw=="], + + "unist-util-remove/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], + "webpack/schema-utils": ["schema-utils@4.3.2", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ=="], "yargs-unparser/is-plain-obj": ["is-plain-obj@2.1.0", "", {}, "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="], @@ -1289,6 +1477,8 @@ "log-symbols/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "mdast-util-gfm-autolink-literal/micromark-util-character/micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + "mocha/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "send/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], diff --git a/packages/next/components/shell/Background.tsx b/packages/next/components/shell/Background.tsx new file mode 100644 index 0000000..5d0ba23 --- /dev/null +++ b/packages/next/components/shell/Background.tsx @@ -0,0 +1,26 @@ +"use client"; + +import { backgroundURLAtom } from "@/lib/state/background"; +import { useAtom, useSetAtom } from "jotai"; +import { useEffect } from "react"; +import { usePathname } from "next/navigation"; + +export function Background() { + const pathname = usePathname(); + const [url, setURL] = useAtom(backgroundURLAtom); + useEffect(() => { + setURL(null); + }, [pathname]); + if (!url) { + return <>; + } + return ; +} + +export function BackgroundDelegate({ url }: { url: string }) { + const setBG = useSetAtom(backgroundURLAtom); + useEffect(() => { + setBG(url); + }, []); + return <>; +} diff --git a/packages/next/components/shell/Content.tsx b/packages/next/components/shell/Content.tsx new file mode 100644 index 0000000..a81a2c8 --- /dev/null +++ b/packages/next/components/shell/Content.tsx @@ -0,0 +1,83 @@ +import { sql } from "@cvsa/core"; +import { SafeMdxRenderer } from "@/lib/mdx/SafeMDX"; +import "./content.css"; +import remarkMdx from "remark-mdx"; +import remarkGfm from "remark-gfm"; +import { OptionalChidrenProps } from "@/components/ui/Dialog"; +import { remark } from "remark"; +import { Root } from "mdast"; +import remarkCollectFootnoteDefinitions from "@/lib/mdx/footnoteHelper"; +import { BackgroundDelegate } from "./Background"; + +const 黑幕: React.FC> = ({ children }) => { + return ( + + {children} + + ); +}; + +const components = { + 黑幕: 黑幕, + center: ({ children }: { children: React.ReactNode }) => { + return
{children}
; + }, + 背景图片: ({ url }: { url: string }) => { + return ; + }, + poem: ({ children }: { children: React.ReactNode }) => { + if (typeof children !== "string") { + return <>{children}; + } + return
") }}>
; + } +}; + +interface ContentProps { + pageID: string; +} + +export const Content: React.FC = async ({ pageID }) => { + const result = await sql<{ page_content: string }[]>` + SELECT page_content + FROM content + WHERE page_id = ${pageID} + `; + if (result.length === 0) { + return <>; + } + const content = result[0].page_content.replace(/<\!--.*?-->/g, ""); + + try { + const parser = remark() + .use(remarkGfm) + .use(remarkMdx) + .use(remarkCollectFootnoteDefinitions) + .use(() => { + return (tree, file) => { + file.data.ast = tree; + }; + }); + + const file = parser.processSync(content); + const mdast = file.data.ast as Root; + return ( +
+ +
+ ); + } catch (e) { + return ( +
+

+ 渲染出现问题。 +
+ 错误信息: {e.message} +
+ 以下是该内容的原文: +

+
{content}
+
+ ); + } +}; diff --git a/packages/next/components/shell/ContentClient.tsx b/packages/next/components/shell/ContentClient.tsx new file mode 100644 index 0000000..b0bbbdf --- /dev/null +++ b/packages/next/components/shell/ContentClient.tsx @@ -0,0 +1,73 @@ +"use client"; +import { SafeMdxRenderer } from "@/lib/mdx/SafeMDX"; +import "./content.css"; +import remarkMdx from "remark-mdx"; +import remarkGfm from "remark-gfm"; +import { OptionalChidrenProps } from "@/components/ui/Dialog"; +import { remark } from "remark"; +import { Root } from "mdast"; +import remarkCollectFootnoteDefinitions from "@/lib/mdx/footnoteHelper"; +import { BackgroundDelegate } from "./Background"; + +const 黑幕: React.FC> = ({ children }) => { + return ( + + {children} + + ); +}; + +const components = { + 黑幕: 黑幕, + center: ({ children }: { children: React.ReactNode }) => { + return
{children}
; + }, + 背景图片: ({ url }: { url: string }) => { + return ; + }, + poem: ({ children }: { children: React.ReactNode }) => { + if (typeof children !== "string") { + return <>{children}; + } + return
") }}>
; + } +}; + +interface ContentProps { + content: string; +} + +export const ContentClient: React.FC = ({ content }) => { + try { + const parser = remark() + .use(remarkGfm) + .use(remarkMdx) + .use(remarkCollectFootnoteDefinitions) + .use(() => { + return (tree, file) => { + file.data.ast = tree; + }; + }); + + const file = parser.processSync(content); + const mdast = file.data.ast as Root; + return ( +
+ +
+ ); + } catch (e) { + return ( +
+

+ 渲染出现问题。 +
+ 错误信息: {e.message} +
+ 以下是该内容的原文: +

+
{content}
+
+ ); + } +}; diff --git a/packages/next/app/[locale]/about/content.css b/packages/next/components/shell/content.css similarity index 89% rename from packages/next/app/[locale]/about/content.css rename to packages/next/components/shell/content.css index e41a1d6..97c5cc5 100644 --- a/packages/next/app/[locale]/about/content.css +++ b/packages/next/components/shell/content.css @@ -41,3 +41,7 @@ @apply inline; } } + +.footnote-li { + @apply list-outside ml-6; +} diff --git a/packages/next/components/ui/Dialog.tsx b/packages/next/components/ui/Dialog.tsx index 24d75d4..4eac26b 100644 --- a/packages/next/components/ui/Dialog.tsx +++ b/packages/next/components/ui/Dialog.tsx @@ -18,7 +18,7 @@ export const useDisableBodyScroll = (open: boolean) => { }, [open]); }; -type OptionalChidrenProps> = T & { +export type OptionalChidrenProps> = T & { children?: React.ReactNode; }; diff --git a/packages/next/content/about.mdx b/packages/next/content/about.mdx deleted file mode 100644 index de549dd..0000000 --- a/packages/next/content/about.mdx +++ /dev/null @@ -1,60 +0,0 @@ -# 关于「中 V 档案馆」 - -「中 V 档案馆」是一个旨在收录与展示「中文歌声合成作品」及有关信息的网站。 - -## 创建背景与关联工作 - -纵观整个互联网,对于「中文歌声合成」或「中文虚拟歌手」(常简称为中 V 或 VC)相关信息进行较为系统、全面地整理收集的主要有以下几个网站: - -- [萌娘百科](https://zh.moegirl.org.cn/): - 收录了大量中 V 歌曲及歌姬的信息,呈现形式为传统维基(基于 [MediaWiki](https://www.mediawiki.org/))。 -- [VCPedia](https://vcpedia.cn/): - 由原萌娘百科中文歌声合成编辑团队的部分成员搭建,专属于中文歌声合成相关内容的信息集成站点 [^1],呈现形式为传统维基(基于 [MediaWiki](https://www.mediawiki.org/))。 -- [VocaDB](https://vocadb.net/): 一个围绕 Vocaloid、UTAU 和其他歌声合成器的协作数据库,其中包含艺术家、唱片、PV - 等 [^2],其中包含大量中文歌声合成作品。 -- [天钿 Daily](https://tdd.bunnyxt.com/):一个 VC 相关数据交流与分享的网站。致力于 VC 相关数据交流,定期抓取 VC 相关数据,选取有意义的纬度展示。[^3] - -上述网站中,或多或少存在一些不足,例如: - -- 萌娘百科、VCPedia 受限于传统维基,绝大多数内容依赖人工编辑。 -- VocaDB 基于结构化数据库构建,由此可以依赖程序生成一些信息,但 **条目收录** 仍然完全依赖人工完成。 -- VocaDB 主要专注于元数据展示,少有关于歌曲、作者等的描述性的文字,也缺乏描述性的背景信息。 -- 天钿 Daily 只展示歌曲的统计数据及历史趋势,没有关于歌曲其它信息的收集。 - -因此,**中 V 档案馆** 吸取前人经验,克服上述网站的不足,希望做到: - -- 歌曲收录(指发现歌曲并创建条目)的完全自动化 -- 歌曲元信息提取的高度自动化 -- 歌曲统计数据收集的完全自动化 -- 在程序辅助的同时欢迎并鼓励贡献者参与编辑(主要为描述性内容)或纠错 -- 在适当的许可声明下,引用来自上述源的数据,使内容更加全面、丰富。 - -## 技术架构 - -参见 [CVSA 文档](https://docs.projectcvsa.com/)。 - -## 开放许可 - -受本文以 [CC BY-NC-SA 4.0 协议](https://creativecommons.org/licenses/by-nc-sa/4.0/) 提供。 - -### 数据库 - -中 V 档案馆使用 [PostgreSQL](https://postgresql.org) 作为数据库,我们承诺定期导出数据库转储 (dump) -文件并公开,其内容遵从以下协议或条款: - -- 数据库中的事实性数据,根据适用法律,不构成受版权保护的内容。中 V 档案馆放弃一切可能的权利([CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/))。 -- 对于数据库中有原创性的内容(如贡献者编辑的描述性内容),如无例外,以 [CC BY 4.0 协议](https://creativecommons.org/licenses/by/4.0/) 提供。 -- 对于引用、摘编或改编自萌娘百科、VCPedia 的内容,以与原始协议(CC BY-NC-SA 3.0 - CN)兼容的协议 [CC BY-NC-SA 4.0 协议](https://creativecommons.org/licenses/by-nc-sa/4.0/) 提供,并注明原始协议 。 - > 根据原始协议第四条第 2 项内容,CC BY-NC-SA 4.0 协议为与原始协议具有相同授权要素的后续版本(“可适用的协议”)。 -- 中 V 档案馆文档使用 [CC BY 4.0 协议](https://creativecommons.org/licenses/by/4.0/)。 - -### 软件代码 - -用于构建中 V 档案馆的软件代码在 [AGPL 3.0](https://www.gnu.org/licenses/agpl-3.0.html) 许可证下公开,参见 [LICENSE](./LICENSE) - -[^1]: 引用自 [VCPedia](https://vcpedia.cn/%E9%A6%96%E9%A1%B5),于 [知识共享 署名-非商业性使用-相同方式共享 3.0中国大陆 (CC BY-NC-SA 3.0 CN) 许可协议](https://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 下提供。 - -[^2]: 翻译自 [VocaDB](https://vocadb.net/),于 [CC BY 4.0协议](https://creativecommons.org/licenses/by/4.0/) 下提供。 - -[^3]: 引用自 [关于 - 天钿Daily](https://tdd.bunnyxt.com/about) diff --git a/packages/next/lib/mdx/SafeMDX.tsx b/packages/next/lib/mdx/SafeMDX.tsx new file mode 100644 index 0000000..e3d9fc2 --- /dev/null +++ b/packages/next/lib/mdx/SafeMDX.tsx @@ -0,0 +1,982 @@ +import React, { cloneElement } from "react"; +import { htmlToJsx } from "html-to-jsx-transform"; +import { Node, Parent, RootContent } from "mdast"; +import remarkFrontmatter from "remark-frontmatter"; +import "./footnoteHelper"; + +import { collapseWhiteSpace } from "collapse-white-space"; +import remarkComment from "remark-comment"; +import { visit } from "unist-util-visit"; + +import { Root } from "mdast"; +import { MdxJsxFlowElement, MdxJsxTextElement } from "mdast-util-mdx-jsx"; +import { remark } from "remark"; +import remarkGfm from "remark-gfm"; +import remarkMdx from "remark-mdx"; + +import { Fragment, ReactNode } from "react"; + +type MyRootContent = RootContent | Root; + +export function mdxParse(code: string) { + const file = mdxProcessor.processSync(code); + return file.data.ast as Root; +} + +declare module "mdast" { + export interface Data { + hProperties?: { + id?: string; + className?: string; + }; + } +} + +export type CustomTransformer = ( + node: MyRootContent, + transform: (node: MyRootContent) => ReactNode +) => ReactNode | undefined; + +export function SafeMdxRenderer({ + components, + code = "", + mdast = null as any, + customTransformer +}: { + components?: ComponentsMap; + code?: string; + mdast?: MyRootContent; + customTransformer?: CustomTransformer; +}) { + const visitor = new MdastToJsx({ + code, + mdast, + components, + customTransformer + }); + const result = visitor.run(); + return result; +} + +export class MdastToJsx { + mdast: MyRootContent; + str: string; + jsxStr: string = ""; + c: ComponentsMap; + errors: { message: string }[] = []; + customTransformer?: CustomTransformer; + + constructor({ + code = "", + mdast = undefined as any, + components = {} as ComponentsMap, + customTransformer + }: { + code?: string; + mdast?: MyRootContent; + components?: ComponentsMap; + customTransformer?: ( + node: MyRootContent, + transform: (node: MyRootContent) => ReactNode + ) => ReactNode | undefined; + }) { + this.str = code; + this.mdast = mdast || mdxParse(code); + this.customTransformer = customTransformer; + + this.c = { + ...Object.fromEntries( + nativeTags.map((tag) => { + return [tag, tag]; + }) + ), + ...components + }; + } + mapMdastChildren(node: any) { + const res = node.children?.flatMap((child: MyRootContent) => this.mdastTransformer(child)).filter(Boolean); + if (Array.isArray(res)) { + if (!res.length) { + return null; + } else if (res.length === 1) { + return res[0]; + } else { + return res.map((x, i) => (React.isValidElement(x) ? cloneElement(x, { key: i }) : x)); + } + } + return res || null; + } + mapJsxChildren(node: any) { + const res = node.children?.flatMap((child: MyRootContent) => this.jsxTransformer(child)).filter(Boolean); + if (Array.isArray(res)) { + if (!res.length) { + return null; + } else if (res.length === 1) { + return res[0]; + } else { + return res.map((x, i) => (React.isValidElement(x) ? cloneElement(x, { key: i }) : x)); + } + } + return res || null; + } + jsxTransformer(node: MyRootContent): ReactNode { + if (!node) { + return []; + } + + switch (node.type) { + case "mdxJsxTextElement": + case "mdxJsxFlowElement": { + if (!node.name) { + return []; + } + + const Component = accessWithDot(this.c, node.name); + + if (!Component) { + this.errors.push({ + message: `Unsupported jsx component ${node.name}` + }); + return null; + } + + let attrsList = getJsxAttrs(node, (err) => { + this.errors.push(err); + }); + + let attrs = Object.fromEntries(attrsList); + + function cssStringToObject(css: string): Record { + const styleObj: Record = {}; + css.split(";").forEach((rule) => { + const [key, val] = rule.trim().split(":"); + if (key && val) { + styleObj[key.trim()] = val.trim(); + } + }); + return styleObj; + } + + const SafeComponent: React.FC = ({ style, ...props }) => { + const safeStyle = React.useMemo(() => { + if (typeof style === "string") { + return cssStringToObject(style); + } + return style || {}; + }, [style]); + + return ; + }; + return {this.mapJsxChildren(node)}; + } + default: { + return this.mdastTransformer(node); + } + } + } + + run() { + const res = this.mdastTransformer(this.mdast) as ReactNode; + if (Array.isArray(res) && res.length === 1) { + return res[0]; + } + return res; + } + + mdastTransformer(node: MyRootContent): ReactNode { + if (!node) { + return []; + } + + // Check for custom transformer first, giving it higher priority + if (this.customTransformer) { + const customResult = this.customTransformer(node, this.mdastTransformer.bind(this)); + if (customResult !== undefined) { + return customResult; + } + } + + switch (node.type) { + case "mdxjsEsm": { + // const start = node.position?.start?.offset; + // const end = node.position?.end?.offset; + // let text = this.str.slice(start, end); + + return []; + } + case "mdxJsxTextElement": + case "mdxJsxFlowElement": { + const start = node.position?.start?.offset; + const end = node.position?.end?.offset; + const text = this.str.slice(start, end); + + // XSS protection + if (node.name === "script") { + return []; + } + + try { + this.jsxStr = text; + const result = this.jsxTransformer(node); + if (Array.isArray(result)) { + console.log(`Unexpected array result`); + } else if (result) { + return result; + } + } finally { + this.jsxStr = ""; + } + return []; + } + + case "mdxFlowExpression": + case "mdxTextExpression": { + if (!node.value) { + return []; + } + return []; + } + case "yaml": { + if (!node.value) { + return []; + } + return []; + } + case "heading": { + const level = node.depth; + const Tag = this.c[`h${level}`] ?? `h${level}`; + + return {this.mapMdastChildren(node)}; + } + case "paragraph": { + return {this.mapMdastChildren(node)}; + } + case "blockquote": { + return {this.mapMdastChildren(node)}; + } + case "thematicBreak": { + return ; + } + case "code": { + if (!node.value) { + return []; + } + const language = node.lang || ""; + const code = node.value; + const codeBlock = (className?: string) => ( + + {code} + + ); + + if (language) { + if (supportedLanguagesSet.has(language as (typeof supportedLanguages)[number])) { + return codeBlock(`language-${language}`); + } else { + this.errors.push({ + message: `Unsupported language ${language}` + }); + return codeBlock(); + } + } + return codeBlock(); + } + + case "list": { + if (node.ordered) { + return ( + + {this.mapMdastChildren(node)} + + ); + } + return {this.mapMdastChildren(node)}; + } + case "listItem": { + // https://github.com/syntax-tree/mdast-util-gfm-task-list-item#syntax-tree + if (node?.checked != null) { + return ( + + {this.mapMdastChildren(node)} + + ); + } + return {this.mapMdastChildren(node)}; + } + case "text": { + if (!node.value) { + return []; + } + return node.value; + } + case "image": { + const src = node.url || ""; + const alt = node.alt || ""; + const title = node.title || ""; + return ; + } + case "link": { + const href = node.url || ""; + const title = node.title || ""; + return ( + + {this.mapMdastChildren(node)} + + ); + } + case "strong": { + return {this.mapMdastChildren(node)}; + } + case "emphasis": { + return {this.mapMdastChildren(node)}; + } + case "delete": { + return {this.mapMdastChildren(node)}; + } + case "inlineCode": { + if (!node.value) { + return []; + } + return {node.value}; + } + case "break": { + return ; + } + case "root": { + return {this.mapMdastChildren(node)}; + } + case "table": { + const [head, ...body] = React.Children.toArray(this.mapMdastChildren(node)); + return ( + + {head && {head}} + {!!body?.length && {body}} + + ); + } + case "tableRow": { + return ( + + {this.mapMdastChildren(node)} + + ); + } + case "tableCell": { + let content = this.mapMdastChildren(node); + return ( + + {content} + + ); + } + case "definition": { + return []; + } + case "linkReference": { + let href = ""; + mdastBfs(this.mdast, (child: any) => { + if (child.type === "definition" && child.identifier === node.identifier) { + href = child.url; + } + }); + + return ( + + {this.mapMdastChildren(node)} + + ); + } + case "footnoteReference": { + return ( + + + {node.label} + + + ); + } + + case "footnoteDefinition": { + let content = this.mapMdastChildren(node); + return ( + + {content} + + ); + } + + case "html": { + const start = node.position?.start?.offset; + const end = node.position?.end?.offset; + const text = this.str.slice(start, end); + if (!text) { + return []; + } + + const jsx = htmlToJsx(text); + try { + this.jsxStr = jsx; + const result = this.jsxTransformer(node); + if (Array.isArray(result)) { + console.log(`Unexpected array result`); + } else if (result) { + return result; + } + } finally { + this.jsxStr = ""; + } + + return []; + } + case "imageReference": { + return []; + } + + default: { + mdastBfs(node, (node) => { + delete node.position; + }); + + throw new Error(`cannot convert node` + JSON.stringify(node, null, 2)); + } + } + } +} + +export function getJsxAttrs( + node: MdxJsxFlowElement | MdxJsxTextElement, + onError: (err: { message: string }) => void = console.error +) { + let attrsList = node.attributes + .map((attr) => { + if (attr.type === "mdxJsxExpressionAttribute") { + onError({ + message: `Expressions in jsx props are not supported (${attr.value + .replace(/\n+/g, " ") + .replace(/ +/g, " ")})` + }); + return; + } + if (attr.type !== "mdxJsxAttribute") { + throw new Error(`non mdxJsxAttribute is not supported: ${attr}`); + } + + const v = attr.value; + if (typeof v === "string" || typeof v === "number") { + return [attr.name, v]; + } + if (v === null) { + return [attr.name, true]; + } + if (v?.type === "mdxJsxAttributeValueExpression") { + if (v.value === "true") { + return [attr.name, true]; + } + if (v.value === "false") { + return [attr.name, false]; + } + if (v.value === "null") { + return [attr.name, null]; + } + if (v.value === "undefined") { + return [attr.name, undefined]; + } + let quote = ['"', "'", "`"].find((q) => v.value.startsWith(q) && v.value.endsWith(q)); + if (quote) { + let value = v.value; + if (quote !== '"') { + value = v.value.replace(new RegExp(quote, "g"), '"'); + } + return [attr.name, JSON.parse(value)]; + } + + const number = Number(v.value); + if (!isNaN(number)) { + return [attr.name, number]; + } + const parsedJson = safeJsonParse(v.value); + if (parsedJson) { + return [attr.name, parsedJson]; + } + + onError({ + message: `Expressions in jsx props are not supported (${attr.name}={${v.value}})` + }); + } else { + console.log("unhandled attr", { attr }, attr.type); + } + + return; + }) + .filter(isTruthy) as [string, any][]; + return attrsList; +} + +function isTruthy(val: T | undefined | null | false): val is T { + return Boolean(val); +} + +function accessWithDot(obj: any, path: string) { + return path + .split(".") + .map((x) => x.trim()) + .filter(Boolean) + .reduce((o, i) => o[i], obj); +} + +export function mdastBfs(node: Parent | Node, cb?: (node: Node | Parent) => any) { + const queue = [node]; + const result: any[] = []; + while (queue.length) { + const node = queue.shift(); + let r = cb && node ? cb(node) : node; + if (Array.isArray(r)) { + queue.push(...r); + } else if (r) { + result.push(r); + } + if (node && "children" in node && node.children) { + queue.push(...(node.children as any)); + } + } + return result; +} + +function safeJsonParse(str: string) { + try { + return JSON.parse(str); + } catch (err) { + return null; + } +} + +const nativeTags = [ + "blockquote", + "strong", + "em", + "del", + "hr", + "a", + "b", + "br", + "button", + "div", + "form", + "h1", + "h2", + "h3", + "h4", + "head", + "iframe", + "img", + "input", + "label", + "li", + "link", + "ol", + "p", + "path", + "picture", + "script", + "section", + "source", + "span", + "sub", + "sup", + "svg", + "table", + "tbody", + "td", + "tfoot", + "th", + "thead", + "tr", + "ul", + "video", + "code", + "pre", + "figure", + "canvas", + "details", + "dl", + "dt", + "dd", + "fieldset", + "footer", + "header", + "legend", + "main", + "mark", + "nav", + "progress", + "summary", + "time" +] as const; + +const supportedLanguages = [ + "abap", + "abnf", + "actionscript", + "ada", + "agda", + "al", + "antlr4", + "apacheconf", + "apex", + "apl", + "applescript", + "aql", + "arduino", + "arff", + "asciidoc", + "asm6502", + "asmatmel", + "aspnet", + "autohotkey", + "autoit", + "avisynth", + "avro-idl", + "bash", + "basic", + "batch", + "bbcode", + "bicep", + "birb", + "bison", + "bnf", + "brainfuck", + "brightscript", + "bro", + "bsl", + "c", + "cfscript", + "chaiscript", + "cil", + "clike", + "clojure", + "cmake", + "cobol", + "coffeescript", + "concurnas", + "coq", + "cpp", + "crystal", + "csharp", + "cshtml", + "csp", + "css-extras", + "css", + "csv", + "cypher", + "d", + "dart", + "dataweave", + "dax", + "dhall", + "diff", + "django", + "dns-zone-file", + "docker", + "dot", + "ebnf", + "editorconfig", + "eiffel", + "ejs", + "elixir", + "elm", + "erb", + "erlang", + "etlua", + "excel-formula", + "factor", + "false", + "firestore-security-rules", + "flow", + "fortran", + "fsharp", + "ftl", + "gap", + "gcode", + "gdscript", + "gedcom", + "gherkin", + "git", + "glsl", + "gml", + "gn", + "go-module", + "go", + "graphql", + "groovy", + "haml", + "handlebars", + "haskell", + "haxe", + "hcl", + "hlsl", + "hoon", + "hpkp", + "hsts", + "http", + "ichigojam", + "icon", + "icu-message-format", + "idris", + "iecst", + "ignore", + "inform7", + "ini", + "io", + "j", + "java", + "javadoc", + "javadoclike", + "javascript", + "javastacktrace", + "jexl", + "jolie", + "jq", + "js-extras", + "js-templates", + "jsdoc", + "json", + "json5", + "jsonp", + "jsstacktrace", + "jsx", + "julia", + "keepalived", + "keyman", + "kotlin", + "kumir", + "kusto", + "latex", + "latte", + "less", + "lilypond", + "liquid", + "lisp", + "livescript", + "llvm", + "log", + "lolcode", + "lua", + "magma", + "makefile", + "markdown", + "markup-templating", + "markup", + "matlab", + "maxscript", + "mel", + "mermaid", + "mizar", + "mongodb", + "monkey", + "moonscript", + "n1ql", + "n4js", + "nand2tetris-hdl", + "naniscript", + "nasm", + "neon", + "nevod", + "nginx", + "nim", + "nix", + "nsis", + "objectivec", + "ocaml", + "opencl", + "openqasm", + "oz", + "parigp", + "parser", + "pascal", + "pascaligo", + "pcaxis", + "peoplecode", + "perl", + "php-extras", + "php", + "phpdoc", + "plsql", + "powerquery", + "powershell", + "processing", + "prolog", + "promql", + "properties", + "protobuf", + "psl", + "pug", + "puppet", + "pure", + "purebasic", + "purescript", + "python", + "q", + "qml", + "qore", + "qsharp", + "r", + "racket", + "reason", + "regex", + "rego", + "renpy", + "rest", + "rip", + "roboconf", + "robotframework", + "ruby", + "rust", + "sas", + "sass", + "scala", + "scheme", + "scss", + "shell-session", + "smali", + "smalltalk", + "smarty", + "sml", + "solidity", + "solution-file", + "soy", + "sparql", + "splunk-spl", + "sqf", + "sql", + "squirrel", + "stan", + "stylus", + "swift", + "systemd", + "t4-cs", + "t4-templating", + "t4-vb", + "tap", + "tcl", + "textile", + "toml", + "tremor", + "tsx", + "tt2", + "turtle", + "twig", + "typescript", + "typoscript", + "unrealscript", + "uorazor", + "uri", + "v", + "vala", + "vbnet", + "velocity", + "verilog", + "vhdl", + "vim", + "visual-basic", + "warpscript", + "wasm", + "web-idl", + "wiki", + "wolfram", + "wren", + "xeora", + "xml-doc", + "xojo", + "xquery", + "yaml", + "yang", + "zig" +] as const; +const supportedLanguagesSet = new Set(supportedLanguages); + +type ComponentsMap = { [k in (typeof nativeTags)[number]]?: any } & { + [key: string]: any; +}; + +/** + * https://github.com/mdx-js/mdx/blob/b3351fadcb6f78833a72757b7135dcfb8ab646fe/packages/mdx/lib/plugin/remark-mark-and-unravel.js + * A tiny plugin that unravels `

x

` but also + * `

` (so it has no knowledge of "HTML"). + * + * It also marks JSX as being explicitly JSX, so when a user passes a `h1` + * component, it is used for `# heading` but not for `

heading

`. + * + */ +export function remarkMarkAndUnravel() { + return function (tree: Root) { + visit(tree, function (node, index, parent) { + let offset = -1; + let all = true; + let oneOrMore = false; + + if (parent && typeof index === "number" && node.type === "paragraph") { + const children = node.children; + + while (++offset < children.length) { + const child = children[offset]; + + if (child.type === "mdxJsxTextElement" || child.type === "mdxTextExpression") { + oneOrMore = true; + } else if ( + child.type === "text" && + collapseWhiteSpace(child.value, { + style: "html", + trim: true + }) === "" + ) { + // Empty. + } else { + all = false; + break; + } + } + + if (all && oneOrMore) { + offset = -1; + + const newChildren: RootContent[] = []; + + while (++offset < children.length) { + const child = children[offset]; + + if (child.type === "mdxJsxTextElement") { + // @ts-expect-error: mutate because it is faster; content model is fine. + child.type = "mdxJsxFlowElement"; + } + + if (child.type === "mdxTextExpression") { + // @ts-expect-error: mutate because it is faster; content model is fine. + child.type = "mdxFlowExpression"; + } + + if (child.type === "text" && /^[\t\r\n ]+$/.test(String(child.value))) { + // Empty. + } else { + newChildren.push(child); + } + } + + parent.children.splice(index, 1, ...newChildren); + return index; + } + } + }); + }; +} + +const mdxProcessor = remark() + .use(remarkMdx) + .use(remarkComment) + .use(remarkFrontmatter, ["yaml", "toml"]) + .use(remarkGfm) + .use(remarkMarkAndUnravel) + .use(() => { + return (tree, file) => { + file.data.ast = tree; + }; + }); diff --git a/packages/next/lib/mdx/footnoteHelper.tsx b/packages/next/lib/mdx/footnoteHelper.tsx new file mode 100644 index 0000000..7967612 --- /dev/null +++ b/packages/next/lib/mdx/footnoteHelper.tsx @@ -0,0 +1,63 @@ +import { Root, FootnoteDefinition, Heading, List, ListItem } from "mdast"; +import { Plugin } from "unified"; +const remarkCollectFootnotes: Plugin<[], Root> = function () { + return function transformer(tree) { + const footnotes: FootnoteDefinition[] = []; + + // 收集所有 footnoteDefinition 并从树中移除它们 + tree.children = tree.children.filter((node) => { + if (node.type === "footnoteDefinition") { + footnotes.push(node as FootnoteDefinition); + return false; + } + return true; + }); + + if (footnotes.length === 0) return tree; + + const heading: Heading = { + type: "heading", + depth: 2, + children: [{ type: "text", value: "脚注" }] + }; + + const list: List = { + type: "list", + ordered: true, + start: 1, + children: footnotes.map((def, i) => { + return { + type: "listItem", + children: [ + ...(def.children || []).flatMap((child) => { + return "value" in child ? { type: "text", value: child.value } : child; + }), + { + type: "link", + url: `#user-content-fnref-${i + 1}`, + children: [ + { + type: "text", + value: " ↩" + } + ] + } + ], + data: { + hProperties: { + id: `user-content-fn-${i + 1}`, + className: "footnote-li" + } + } + } as ListItem; + }) + }; + + // 添加到文档最后 + tree.children.push(heading, list); + + return tree; + }; +}; + +export default remarkCollectFootnotes; diff --git a/packages/next/lib/state/background.ts b/packages/next/lib/state/background.ts new file mode 100644 index 0000000..8ad3599 --- /dev/null +++ b/packages/next/lib/state/background.ts @@ -0,0 +1,3 @@ +import { atom } from "jotai"; + +export const backgroundURLAtom = atom(null); diff --git a/packages/next/next.config.ts b/packages/next/next.config.ts index 4236ee8..bc3a70f 100644 --- a/packages/next/next.config.ts +++ b/packages/next/next.config.ts @@ -1,6 +1,5 @@ import type { NextConfig } from "next"; import createNextIntlPlugin from "next-intl/plugin"; -import { createMDX } from "fumadocs-mdx/next"; const nextConfig: NextConfig = { devIndicators: false, @@ -22,11 +21,9 @@ const nextConfig: NextConfig = { }); return config; }, - pageExtensions: ["js", "jsx", "md", "mdx", "ts", "tsx"] + transpilePackages: ["next-mdx-remote"] }; const withNextIntl = createNextIntlPlugin(); -const withMDX = createMDX(); - -export default withNextIntl(withMDX(nextConfig)); +export default withNextIntl(nextConfig); diff --git a/packages/next/package.json b/packages/next/package.json index 59dfc18..460a16c 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -24,11 +24,21 @@ "jotai": "^2.12.5", "next": "^15.3.3", "next-intl": "^4.1.0", + "next-mdx-remote": "^5.0.0", "raw-loader": "^4.0.2", "react": "^19.1.0", "react-dom": "^19.1.0", + "rehype-sanitize": "^6.0.0", + "rehype-stringify": "^10.0.1", + "remark-comment": "^1.0.0", + "remark-comments": "^1.2.10", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-remove-comments": "^1.1.1", + "safe-mdx": "^0.1.0", "swr": "^2.3.3", "ua-parser-js": "^2.0.3", + "unified": "^11.0.5", "yup": "^1.6.1", "yup-numeric": "^0.5.0" }, diff --git a/packages/next/source.config.ts b/packages/next/source.config.ts deleted file mode 100644 index e74c9d9..0000000 --- a/packages/next/source.config.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { defineConfig } from "fumadocs-mdx/config"; - -export default defineConfig({ - mdxOptions: {} -});