import Head from "next/head"; import Image from "next/image"; import { Inter } from "@next/font/google"; import styles from "@/styles/Home.module.css"; import { QueryClientProvider, QueryClient, useQuery, useMutation, } from "@tanstack/react-query"; import { useCallback, useEffect, useState } from "react"; import ReactMarkdown from "react-markdown"; import { useKey } from "react-use"; import cn from "clsx"; // import rehypePrettyCode from "rehype-pretty-code"; // import * as shiki from "shiki"; import remarkGfm from "remark-gfm"; import styled from "styled-components"; // import rehypeHighlight from "rehype-highlight"; // @ts-ignore import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; // @ts-ignore import theme from "react-syntax-highlighter/dist/cjs/styles/prism/vs-dark"; // const CDN_BASE = "https://npm.elemecdn.com/"; // shiki.setCDN(`${CDN_BASE}/shiki@0.14.1/`); const SMD = styled(ReactMarkdown)` blockquote, hr, p { margin-block: 1rem; } h1, h2, h3, h4, h5, h6 { font-weight: bold; margin-block: 1rem; } h1 { font-size: 3rem; color: var(--h1-color); } h2 { font-size: 2.5rem; color: var(--h2-color); } h3 { font-size: 2rem; color: var(--h3-color); } h4 { font-size: 1.5rem; color: var(--h4-color); } h5 { font-size: 1rem; color: var(--h5-color); } h6 { font-size: 0.9rem; color: var(--h6-color); } img { display: block; margin-left: auto; margin-right: auto; } .img-alt { display: block; margin: 0 0 1rem 0; font-size: 16px; text-align: center; } th { font-weight: 600; } thead { border-bottom: 2px solid var(--background-modifier-border); } tr { line-height: normal; padding: 0 4px; background-color: var(--pre-code); } tr:nth-child(0) { padding-top: 4px; } th, td { padding: 0.5em 1em; } td { border-bottom: 1px solid var(--background-modifier-border); } td:not(:last-child) { border-right: 1px solid var(--background-modifier-border); } strong { font-weight: 600; } a { color: var(--text-a); text-decoration: none; } a:hover { color: var(--text-a-hover); text-decoration: none; } blockquote { margin: 1rem 0; padding-inline: 2ch; padding-block: 0.5rem; background-color: var(--pre-code); border-left: 0.5ch solid var(--interactive-accent); } blockquote:has(> blockquote) { padding-bottom: 0; } blockquote > blockquote { margin-bottom: 0; } blockquote:not(:has(> blockquote)) { margin-bottom: 1rem; } hr { background-color: var(--background-modifier-border); height: 1px; border: 0; } ul { list-style-type: revert; } ol { list-style-type: decimal; } ul:not(.contains-task-list), ol:not(.contains-task-list) { padding-left: 2em; } ul.contains-task-list, ol.contains-task-list { margin-left: 0; list-style-type: none; } `; const TextTyper = ({ // now the phrase, interval and HTML element desired will come via props and we have some default values here text = "", skip = 0, onFinish = () => {}, }) => { const [typedText, setTypedText] = useState(""); const interval = 50; const step = Math.ceil(text.length / 100); // @ts-ignore const typingRender = (text, updater, interval) => { let localTypingIndex = skip; let localTyping = text.slice(0, skip); if (text) { let printer = setInterval(() => { if (localTypingIndex < text.length) { updater( (localTyping += text.slice( localTypingIndex, localTypingIndex + step )) ); localTypingIndex += step; document.querySelector("#anchor")?.scrollIntoView(); } else { localTypingIndex = 0; localTyping = ""; clearInterval(printer); onFinish(); } }, interval); } }; useEffect(() => { typingRender(text, setTypedText, interval); }, [text, interval]); return
{children}
);
},
};
const Markdown = ({ children }: { children: string }) => {
return (