Created
December 23, 2024 15:58
-
-
Save andersr/87079229e60469429d200ab0177f08d0 to your computer and use it in GitHub Desktop.
Main component in my previous NextJS / React app for rendering mdx blog posts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { MDXRemote, MDXRemoteSerializeResult } from "next-mdx-remote"; | |
import { CodeBlock, Link, Page } from "~/components"; | |
import { PostData, PostSummaryData } from "~/models"; | |
import Gist from "react-gist"; | |
import Emoji from "a11y-react-emoji"; | |
import { POSTS_DIR, TEST_IDS } from "~/shared"; | |
import React from "react"; | |
import { PullQuote } from "../PullQuote/PullQuote"; | |
import { CalloutBox } from "../CalloutBox/CalloutBox"; | |
import { Image } from "../Image"; | |
import { PostMetaInfo } from "../PostMetaInfo"; | |
import ghSlugger from "github-slugger"; | |
import { DiscussionEmbed } from "disqus-react"; | |
import { GiphyEmbed } from "../GiphyEmbed"; | |
import { BetterCodeBlock } from "../BetterCodeBlock"; | |
function h2Element(props: any) { | |
// toc-target is used to enable offset below the app header for TOC anchor targets | |
return ( | |
<h2 className="toc-target" {...props}> | |
{props.children} | |
</h2> | |
); | |
} | |
const components = { | |
pre: (props: any) => <BetterCodeBlock {...props} />, | |
h2: h2Element, | |
CodeBlock, | |
Gist, | |
Emoji, | |
PullQuote, | |
Image, | |
CalloutBox, | |
GiphyEmbed, | |
}; | |
interface Props { | |
post: PostData; | |
mdxContent: MDXRemoteSerializeResult; | |
previous: PostSummaryData | null; | |
next: PostSummaryData | null; | |
headings: string[]; | |
} | |
// TODO: refactor metadata info - lots of duplication between mobile and desktop | |
export function ViewPost({ | |
post, | |
mdxContent, | |
previous, | |
next, | |
headings, | |
}: Props) { | |
const origin = | |
typeof window !== "undefined" && window.location.origin | |
? window.location.origin | |
: ""; | |
if (!post) { | |
return <Page title={"Sorry, there was a problem displaying this post"} />; | |
} | |
const imageCredit = post.imageCredit ? ( | |
<a | |
href={post.imageCredit[0]} | |
className=" text-xs text-slate-400 no-underline" | |
> | |
Photo by {post.imageCredit[1]} | |
</a> | |
) : null; | |
const featuredImage = post.featuredImage | |
? `/images/${post.featuredImage[0]}` | |
: undefined; | |
return ( | |
<Page | |
title={`${post.status !== "published" ? "[D] " : ""}${post.title}`} | |
metaDescription={post.description} | |
ogImageUrl={`${origin}${featuredImage}`} | |
> | |
{featuredImage && ( | |
<figure className="my-0"> | |
<Image | |
src={featuredImage} | |
alt={post.featuredImage ? post.featuredImage[1] : undefined} | |
priority | |
/> | |
{imageCredit && ( | |
<figcaption className="text-right m-0">{imageCredit}</figcaption> | |
)} | |
</figure> | |
)} | |
<PostMetaInfo post={post} /> | |
{post.toc && headings?.length > 0 && ( | |
<div className="toc"> | |
<h2>Contents</h2> | |
<ul> | |
{headings.map((h) => { | |
const slug = ghSlugger.slug(h.trim()); | |
return ( | |
<li key={slug}> | |
<a href={`#${slug}`}>{h}</a> | |
</li> | |
); | |
})} | |
</ul> | |
<hr /> | |
</div> | |
)} | |
<MDXRemote {...mdxContent} components={components} /> | |
<div className="text-center text-slate-400 mb-6 px-4"> | |
<hr /> | |
{previous && ( | |
<div className={`${next ? "pb-2" : ""}`}> | |
<Link | |
href={`/${POSTS_DIR}/${previous.slug}`} | |
testId={TEST_IDS.previousPostLink} | |
> | |
Previous post: {previous.title} | |
</Link> | |
</div> | |
)} | |
{next && ( | |
<div> | |
<Link | |
href={`/${POSTS_DIR}/${next.slug}`} | |
testId={TEST_IDS.nextPostLink} | |
> | |
Next post: {next.title} | |
</Link> | |
</div> | |
)} | |
</div> | |
<hr /> | |
<div className="px-5 md:px-0"> | |
<DiscussionEmbed | |
shortname="https-andersco-web-vercel-app" | |
config={{ | |
url: `https://www.anders.co/${POSTS_DIR}/${post.slug}`, | |
identifier: post.slug, | |
title: post.title, | |
language: "en", | |
}} | |
/> | |
</div> | |
</Page> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment