ttcmd: adds hr element

help pages: adds a way to extract the table of contents to the parent,
smoothes out the rough loading on help pages
This commit is contained in:
2024-03-13 02:52:59 -06:00
parent 009e988a38
commit d0cb74bea8
12 changed files with 199 additions and 70 deletions

View File

@@ -4,36 +4,89 @@ import { Accordion, AccordionContent } from "@/lib/accordion";
import { Poppable } from "@/lib/poppables/components/poppable";
import { createElements } from "@/lib/tcmd";
import Link from "next/link";
import React, { FC, Fragment, ReactNode, use, useMemo } from "react";
import React, {
FC,
Fragment,
Suspense,
use,
useEffect,
useMemo,
useState,
} from "react";
import { sanitize } from "isomorphic-dompurify";
import StaticGenerationSearchParamsBailoutProvider from "next/dist/client/components/static-generation-searchparams-bailout-provider";
import { Loader } from "../loader";
export const TTCMD: FC<
{ body: string; escapeTOC?: (tokens: Token[]) => boolean }
> = ({ body, escapeTOC = () => false }) => {
const elements = useMemo(() => createElements(body), [body]);
const [toc, start, end] = useMemo(() => {
const tocHead = elements.findIndex((t) =>
t.content.includes("Table of Contents")
);
if (tocHead > -1) {
const hr = elements.slice(tocHead).findIndex((t) => t.type === "hr");
if (hr > -1) {
const end = hr + 1;
return [elements.slice(tocHead, end), tocHead, end - tocHead];
}
}
return [[], 0, 0];
}, [elements]);
// const hasEscapedTOC = useMemo(() => toc && escapeTOC(toc), [escapeTOC, toc])
const [hasEscapedTOC, setHasEscapedTOC] = useState<boolean>();
useEffect(() => {
setHasEscapedTOC(escapeTOC(toc));
}, [escapeTOC, toc]);
export const TTCMD: FC<{ body: Promise<string> }> = ({ body }) => {
"use client";
const text = use(body);
const [elements, tabSpacing] = useMemo(() => createElements(text), [text]);
const tada = useMemo(
() => <>{renderer(elements.map((e) => e.token))}</>,
[elements],
);
return (
<div className="text-lg col-span-2">
<div>
<button
className="btn-primary"
onClick={() =>
navigator.clipboard.writeText(JSON.stringify(elements, null, 2))}
>
copy ast
</button>
</div>
{/* {elements.map((e, i) => <Fragment key={e.uuid}>{render(e)}</Fragment>)} */}
<Suspense fallback={<Loader />}>
{
/* <button
className="btn-primary"
onClick={() =>
navigator.clipboard.writeText(JSON.stringify(elements, null, 2))}
>
copy ast
</button> */
}
{hasEscapedTOC !== undefined &&
(
<TTCMDRenderer
tokens={hasEscapedTOC
? [...elements].toSpliced(start, end)
: elements}
/>
)}
</Suspense>
);
};
export const TTCMDRenderer: FC<{ tokens: Token[] }> = ({ tokens }) => {
const tada = useMemo(
() => (
<>
{renderer(tokens)}
</>
),
[tokens],
);
if (!tokens.length) {
const audio = new Audio(
"https://assets.mixkit.co/active_storage/sfx/221/221-preview.mp3",
);
audio.onload = () => {
audio.play();
};
}
return (
<div className="text-lg">
{tada}
</div>
// <div className="grid grid-cols-3">
// {/* <pre suppressHydrationWarning>{JSON.stringify(elements,null,2)}</pre> */}
// </div>
);
};
@@ -214,6 +267,8 @@ function render(token: Token, usedIds: string[]) {
{token.children?.map((c) => render(c, usedIds))}
</li>
);
case "hr":
return <div className="w-full border-b border-mixed-500 my-3"></div>;
default:
return (
<div className="p bg-red-600 text-white">