You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.4 KiB
TypeScript

import { Metadata } from "next"
import { Code } from "bright"
import { getPostSlugs, loadPageMetada, loadSinglePage } from "~/utils/post"
import MarkdownToJSX from 'markdown-to-jsx'
import styles from "~/styles/post.module.css"
import { ReactElement } from "react"
import PageScript from "./PageScript"
export async function generateMetadata({ params: { slug } }: { params: { slug: string } }): Promise<Metadata> {
const post = await loadPageMetada(slug)
return {
title: post?.title
}
}
export async function generateStaticParams(): Promise<{ slug: string }[]> {
const slugs = await getPostSlugs()
return slugs.map(slug => ({ slug }))
}
export default async function Post({ params: { slug } }: { params: { slug: string } }) {
const post = await loadSinglePage(slug)
if (!post)
return null
return (
<>
<article className={styles.post}>
<span>{post.date.toLocaleDateString('en-US', { timeZone: 'UTC' })}</span>
<h1>{post.title}</h1>
<p className={styles.subtitle}>{post.subtitle}</p>
<Markdown>{post.body}</Markdown>
{post.script && <PageScript script={post.script.path} wasm={post.wasm?.contents} />}
{(post.script || post.wasm) && (
<>
<hr className={styles.postFooter} />
<h2 id="resources">Post Resources:</h2>
<ul>
{post.script && (
<li><a target="_blank" href={post.script.path}>{post.script.name}</a></li>
)}
{post.wasm && (
<li><a target="_blank" href={post.wasm.path}>{post.wasm.name}</a></li>
)}
</ul>
</>
)}
</article>
</>
);
}
function Markdown({ children }: { children: string }) {
const options = {
overrides: {
pre: {
component: CodeBlock,
props: {}
}
}
}
return <MarkdownToJSX children={children} options={options} />
}
Code.theme = {
dark: "github-dark",
light: "github-light",
lightSelector: ':root.light'
}
function CodeBlock({ children }: { children: ReactElement }) {
// extract props normally passed to pre element
const { className: langKey, children: sourceText, ...rest } = children?.props ?? {}
const language = langKey?.replace(/^lang-/i, '')
{/* @ts-expect-error Async Server Component */ }
return <Code lang={language} children={sourceText} {...rest} />
}