Files
pse.dev/components/ui/markdown.tsx
2024-10-21 01:11:27 +01:00

110 lines
2.8 KiB
TypeScript

import React from "react"
import ReactMarkdown, { Components } from "react-markdown"
import remarkGfm from "remark-gfm"
const generateSectionId = (text: string) => {
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-")
}
export const createMarkdownElement = (
tag: keyof JSX.IntrinsicElements,
props: any
) =>
React.createElement(tag, {
...props,
ref: (node: HTMLElement | null) => {
if (node && node.textContent) {
node.setAttribute(
"data-section-id",
generateSectionId(node.textContent)
)
}
},
})
const Table = (props: any) => {
return (
<div className="border rounded-lg border-tuatara-300">
<table data-component="table">{props.children}</table>
</div>
)
}
// Styling for HTML attributes for markdown component
const REACT_MARKDOWN_CONFIG: Components = {
a: ({ node, ...props }) =>
createMarkdownElement("a", {
className: "text-anakiwa-500 hover:text-orange duration-200",
target: "_blank",
...props,
}),
h1: ({ node, ...props }) =>
createMarkdownElement("h1", {
className: "text-neutral-800 text-4xl md:text-5xl font-bold",
...props,
}),
h2: ({ node, ...props }) =>
createMarkdownElement("h2", {
className: "text-neutral-800 text-4xl",
...props,
}),
h3: ({ node, ...props }) =>
createMarkdownElement("h3", {
className: "text-neutral-800 text-3xl",
...props,
}),
h4: ({ node, ...props }) =>
createMarkdownElement("h4", {
className: "text-neutral-800 text-xl",
...props,
}),
h5: ({ node, ...props }) =>
createMarkdownElement("h5", {
className: "text-neutral-800 text-lg font-bold",
...props,
}),
h6: ({ node, ...props }) =>
createMarkdownElement("h6", {
className: "text-neutral-800 text-md font-bold",
...props,
}),
p: ({ node, ...props }) =>
createMarkdownElement("p", {
className: "text-tuatara-700 font-sans text-base font-normal",
...props,
}),
ul: ({ node, ordered, ...props }) =>
createMarkdownElement(ordered ? "ol" : "ul", {
className:
"ml-6 list-disc text-tuatara-700 font-sans text-base font-normal",
...props,
}),
ol: ({ node, ordered, ...props }) =>
createMarkdownElement(ordered ? "ol" : "ul", {
className:
"ml-6 list-disc text-tuatara-700 font-sans text-base font-normal",
...props,
}),
table: Table,
}
interface MarkdownProps {
children: string
components?: Components // components overrides the default components
}
export const Markdown = ({ children, components }: MarkdownProps) => {
return (
<ReactMarkdown
skipHtml={false}
components={{
...REACT_MARKDOWN_CONFIG,
...components,
}}
remarkPlugins={[remarkGfm]}
>
{children}
</ReactMarkdown>
)
}