import type { NextPage } from "next"; import { useEffect, useRef, useState, isValidElement, useCallback } from "react"; import { useRouter } from "next/router"; import styles from "../../styles/Terminal/ProjectModal.module.css"; import asciidocStyles from "../../styles/Terminal/customAsciidoc.module.scss"; import type { Project, Diary } from "../../lib/content/types"; import { useCommands } from "../../lib/commands/ContextProvider"; import { generateContent, projectEmpty } from "../../lib/content/generateBrowser"; import { useModalFunctions } from "./contexts/ModalFunctions"; import Spinner from "../Spinner"; import { renderToStaticMarkup } from "react-dom/server"; // Code Highlighting import hljs from "highlight.js"; import rust from "highlight.js/lib/languages/rust"; import bash from "highlight.js/lib/languages/shell"; hljs.registerLanguage("rust", rust); hljs.registerLanguage("bash", bash); hljs.registerLanguage("console", bash); hljs.registerLanguage("shell", bash); const ProjectModal: NextPage = () => { const [visible, _setVisible] = useState(false); const [currentContent, _setCurrentContent] = useState(undefined); const [currentPage, setCurrentPage] = useState(0); const [HTMLContent, _setHTMLContent] = useState(projectEmpty); const router = useRouter(); const { updateCallbacks: updateCmdCallbacks, cmdContext } = useCommands(); const { updateCallbacks: updateModalCallbacks } = useModalFunctions(); const setHTMLContent = (html: any) => { switch (true) { case typeof html === "string": { _setHTMLContent(html); return; } case isValidElement(html): { _setHTMLContent(renderToStaticMarkup(html)); return; } default: { try { _setHTMLContent(html.toString()); } catch {} return; } } }; const setModalContent = async (content: Project | Diary, selectedPage?: number) => { _setCurrentContent(content); router.replace("#", `#/${content.type}/${content.name}${content.type === "diary" && selectedPage ? `/${selectedPage}`: ""}`, {shallow: true}); if (content.type === "diary") setCurrentPage(selectedPage === undefined ? 0 : selectedPage); setHTMLContent(); setHTMLContent(await generateContent(content, selectedPage)); }; const setVisible = async (visible: boolean) => { if (!visible) { if (window) window.removeEventListener("hashchange", contentFromHash); router.replace("#", undefined, {shallow: true}); } else { if (window) window.addEventListener("hashchange", contentFromHash); } _setVisible(visible); }; const contentFromHash = () => { if (!window) return; const selected = window.location.hash.split("/"); if (selected.length > 2) cmdContext.executeCommand(`project ${selected[2]}${selected[3] ? ` ${selected[3]}` : ""}`); }; const onContentReady = () => { contentFromHash(); }; updateCmdCallbacks({ setModalVisible: setVisible, setModalContent, setModalHTML: setHTMLContent }); updateModalCallbacks({ setVisible, setContent: setModalContent, setHtml: setHTMLContent, onContentReady }); useEffect(() => { hljs.highlightAll(); }, [HTMLContent]); const containerRef = useRef(null); if (!visible) return <>; const nextPageSelector = (() => { if (!currentContent || currentContent?.type !== "diary" || currentContent.entries.length === 0) return null; const prev = {currentPage > 0 ? setModalContent(currentContent, currentPage - 1)}>< {currentPage - 1 > 0 ? currentContent.entries[currentPage - 2].title : "Main page"} : null}; const next = {currentPage < currentContent.entries.length ? setModalContent(currentContent, currentPage + 1)}>{currentContent.entries[currentPage].title} > : null}; const select = ( ); return
{prev} 0 ? "visible" : "hidden"}}>  |  {select}  |  {next}
; })(); return
setVisible(false)}> setVisible(false)} className={styles.fakeLink}>
X
event.stopPropagation()}> {nextPageSelector}
{nextPageSelector}
; }; export default ProjectModal;