import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; import { HTTPError, RenderDocumentBody } from "../document"; import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; import "./index.scss"; import "./post.scss"; import { BlogImage, BlogPostData, BlogPostMetadata, BlogPostMetadataLinks, BlogPostLimitedMetadata, AuthorMetadata, } from "../../../libs/types/blog"; import { useDecorateCodeExamples, useRunSample } from "../document/hooks"; import { DEFAULT_LOCALE } from "../../../libs/constants"; import { TOC } from "../document/organisms/toc"; import { SidePlacement } from "../ui/organisms/placement"; import { PlayQueue } from "../playground/queue"; function MaybeLink({ className = "", link, children }) { return link ? ( link.startsWith("https://") ? ( {children} ) : ( {children} ) ) : ( {children} ); } export function TimeToRead({ readTime }: { readTime: number | undefined }) { if (!readTime) { return <>; } return {readTime} minute read; } export function PublishDate({ date }: { date: string }) { return ( ); } export function Author({ metadata }: { metadata: AuthorMetadata | undefined }) { return ( Author avatar {metadata?.name || "The MDN Team"} ); } export function AuthorDateReadTime({ metadata, }: { metadata: BlogPostMetadata; }) { return (
); } function BlogImageFigure({ image, width, height, }: { image: BlogImage; width?: number; height?: number; }) { const src = `./${image.file}`; return (
{image.alt {(image.creator || image.source) && (
Image{" "} {image.creator && ( <> by{" "} {image.creator.name} )} {image.source && ( <> {" "} via{" "} {image.source.name} )}
)}
); } function PreviousNext({ links: { previous, next }, }: { links: BlogPostMetadataLinks; }) { return (
{previous && ( )} {next && }
); } function PreviousNextLink({ direction, metadata: { slug, title }, }: { direction: "Previous" | "Next"; metadata: BlogPostLimitedMetadata; }) { return (

{direction} Post {title}

); } export function BlogPost(props: HydrationData) { const dataURL = `./index.json`; const { data } = useSWR( dataURL, async (url) => { const response = await fetch(url); if (!response.ok) { switch (response.status) { case 404: throw new HTTPError(response.status, url, "Page not found"); } const text = await response.text(); throw new HTTPError(response.status, url, text); } return await response.json(); }, { fallbackData: props as BlogPostData, revalidateOnFocus: WRITER_MODE, revalidateOnMount: !props.blogMeta, } ); const { doc, blogMeta } = data || props || {}; useRunSample(doc); useDecorateCodeExamples(doc); return ( <> {doc && blogMeta && (
{PLACEMENT_ENABLED && !blogMeta?.sponsored && }
{blogMeta?.sponsored && ( Sponsored )}

{doc?.title}

{blogMeta.links && }
)} ); }