import type {
// TODO ref backend fetching!!
Reference,
Block,
Inline,
Media as MediaType,
ExternalContent,
} from "@/types/trill";
import crow from "@/assets/icons/crow.svg";
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) => (
-
))}
) : (
{block.list.text.map((i, ind) => (
-
))}
)
) : 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 <>>;
}