import type { // TODO ref backend fetching!! Reference, Block, Inline, Media as MediaType, ExternalContent, } from "@/types/trill"; import Icon from "@/components/Icon"; import type { PostProps } from "./Post"; import Media from "./Media"; import JSONContent, { YoutubeSnippet } from "./External"; import { useLocation } from "wouter"; import Quote from "./Quote"; import PostData from "./Loader"; import Card from "./Card.tsx"; import type { Ship } from "@/types/urbit.ts"; function Body(props: PostProps) { const text = props.poast.contents.filter((c) => { return ( "paragraph" in c || "blockquote" in c || "heading" in c || "codeblock" in c || "list" in c ); }); const media: MediaType[] = props.poast.contents.filter( (c): c is MediaType => "media" in c, ); const refs = props.poast.contents.filter((c): c is Reference => "ref" in c); const json = props.poast.contents.filter( (c): c is ExternalContent => "json" in c, ); return (
{text.map((b, i) => ( ))}
{media.length > 0 && } {refs.map((r, i) => ( ))}
); } export default Body; function TextBlock({ block }: { block: Block }) { const key = JSON.stringify(block); return "paragraph" in block ? (
{block.paragraph.map((i, ind) => ( ))}
) : "blockquote" in block ? (
{block.blockquote.map((i, ind) => ( ))}
) : "heading" in block ? ( ) : "codeblock" in block ? (
      
        {block.codeblock.code}
      
    
) : "list" in block ? ( block.list.ordered ? (
    {block.list.text.map((i, ind) => (
  1. ))}
) : ( ) ) : null; } function Inlin({ i }: { i: Inline }) { const [_, navigate] = useLocation(); function gotoShip(e: React.MouseEvent, ship: Ship) { e.stopPropagation(); navigate(`/feed/${ship}`); } return "text" in i ? ( {i.text} ) : "italic" in i ? ( {i.italic} ) : "bold" in i ? ( {i.bold} ) : "strike" in i ? ( {i.strike} ) : "underline" in i ? ( {i.underline} ) : "sup" in i ? ( {i.sup} ) : "sub" in i ? ( {i.sub} ) : "ship" in i ? ( gotoShip(e, i.ship)} > {i.ship} ) : "codespan" in i ? ( {i.codespan} ) : "link" in i ? ( ) : "break" in i ? (
) : null; } function LinkParser({ href, show }: { href: string; show: string }) { const YOUTUBE_REGEX_1 = /(youtube\.com\/watch\?v=)(\w+)/; const YOUTUBE_REGEX_2 = /(youtu\.be\/)([a-zA-Z0-9-_]+)/; const m1 = href.match(YOUTUBE_REGEX_1); const m2 = href.match(YOUTUBE_REGEX_2); const ytb = m1 && m1[2] ? m1[2] : m2 && m2[2] ? m2[2] : ""; return ytb ? ( ) : ( {show} ); } function Heading({ string, num }: { string: string; num: number }) { return num === 1 ? (

{string}

) : num === 2 ? (

{string}

) : num === 3 ? (

{string}

) : num === 4 ? (

{string}

) : num === 5 ? (
{string}
) : num === 6 ? (
{string}
) : null; } function Ref({ r, nest }: { r: Reference; nest: number }) { if (r.ref.type === "nostril") { const comp = PostData({ host: r.ref.ship, id: r.ref.path.slice(1), nest: nest + 1, className: "quote-in-post", })(Quote); return {comp}; } return <>; }