import { HorizontalLine } from "components/HorizontalLine"; import { Img } from "components/Img"; import { InsetBox } from "components/InsetBox"; import { ToolTip } from "components/ToolTip"; import { useAppLayout } from "contexts/AppLayoutContext"; import { slugify } from "helpers/formatters"; import { getAssetURL, ImageQuality } from "helpers/img"; import { Immutable } from "helpers/types"; import { useLightBox } from "hooks/useLightBox"; import Markdown from "markdown-to-jsx"; import { useRouter } from "next/router"; import React from "react"; import ReactDOMServer from "react-dom/server"; interface Props { className?: string; text: string; } export function Markdawn(props: Immutable): JSX.Element { const appLayout = useAppLayout(); const text = preprocessMarkDawn(props.text); const router = useRouter(); const [openLightBox, LightBox] = useLightBox(); if (text) { return ( <> { if (compProps.href.startsWith("/")) { return ( router.push(compProps.href)}> {compProps.children} ); } return ( {compProps.children} ); }, }, h1: { component: (compProps: { id: string; style: React.CSSProperties; children: React.ReactNode; }) => (

{compProps.children}

), }, h2: { component: (compProps: { id: string; style: React.CSSProperties; children: React.ReactNode; }) => (

{compProps.children}

), }, h3: { component: (compProps: { id: string; style: React.CSSProperties; children: React.ReactNode; }) => (

{compProps.children}

), }, h4: { component: (compProps: { id: string; style: React.CSSProperties; children: React.ReactNode; }) => (

{compProps.children}

), }, h5: { component: (compProps: { id: string; style: React.CSSProperties; children: React.ReactNode; }) => (
{compProps.children}
), }, h6: { component: (compProps: { id: string; style: React.CSSProperties; children: React.ReactNode; }) => (
{compProps.children}
), }, Sep: { component: () =>
, }, SceneBreak: { component: (compProps: { id: string }) => (
* * *
), }, IntraLink: { component: (compProps: { children: React.ReactNode; target?: string; page?: string; }) => { const slug = compProps.target ? slugify(compProps.target) : slugify(compProps.children?.toString()); return ( router.replace( `${compProps.page ? compProps.page : ""}#${slug}` ) } > {compProps.children} ); }, }, player: { component: () => ( {appLayout.playerName ? appLayout.playerName : ""} ), }, Transcript: { component: (compProps) => (
{compProps.children}
), }, Line: { component: (compProps) => ( <> {compProps.name}

{compProps.children}

), }, InsetBox: { component: (compProps) => ( {compProps.children} ), }, li: { component: (compProps: { children: React.ReactNode }) => (
  • {compProps.children} ).length > 100 ? "my-4" : "" } > {compProps.children}
  • ), }, Highlight: { component: (compProps: { children: React.ReactNode }) => ( {compProps.children} ), }, footer: { component: (compProps: { children: React.ReactNode }) => ( <>
    {compProps.children}
    ), }, blockquote: { component: (compProps: { children: React.ReactNode; cite?: string; }) => (
    {compProps.cite ? ( <> “{compProps.children}” — {compProps.cite} ) : ( compProps.children )}
    ), }, img: { component: (compProps: { alt: string; src: string; width?: number; height?: number; caption?: string; name?: string; }) => (
    { openLightBox([ compProps.src.startsWith("/uploads/") ? getAssetURL(compProps.src, ImageQuality.Large) : compProps.src, ]); }} >
    ), }, }, }} > {text}
    ); } return <>; } function HeaderToolTip(props: { id: string }) { return ( { navigator.clipboard.writeText( `${process.env.NEXT_PUBLIC_URL_SELF + window.location.pathname}#${ props.id }` ); }} > link ); } export function preprocessMarkDawn(text: string): string { if (!text) return ""; let scenebreakIndex = 0; const visitedSlugs: string[] = []; const result = text.split("\n").map((line) => { if (line === "* * *" || line === "---") { scenebreakIndex += 1; return ``; } if (line.startsWith("# ")) { return markdawnHeadersParser(headerLevels.h1, line, visitedSlugs); } if (line.startsWith("## ")) { return markdawnHeadersParser(headerLevels.h2, line, visitedSlugs); } if (line.startsWith("### ")) { return markdawnHeadersParser(headerLevels.h3, line, visitedSlugs); } if (line.startsWith("#### ")) { return markdawnHeadersParser(headerLevels.h4, line, visitedSlugs); } if (line.startsWith("##### ")) { return markdawnHeadersParser(headerLevels.h5, line, visitedSlugs); } if (line.startsWith("###### ")) { return markdawnHeadersParser(headerLevels.h6, line, visitedSlugs); } return line; }); return result.join("\n"); } enum headerLevels { h1 = 1, h2 = 2, h3 = 3, h4 = 4, h5 = 5, h6 = 6, } function markdawnHeadersParser( headerLevel: headerLevels, line: string, visitedSlugs: string[] ): string { const lineText = line.slice(headerLevel + 1); const slug = slugify(lineText); let newSlug = slug; let index = 2; while (visitedSlugs.includes(newSlug)) { newSlug = `${slug}-${index}`; index += 1; } visitedSlugs.push(newSlug); return `<${headerLevels[headerLevel]} id="${newSlug}">${lineText}`; }