This commit is contained in:
parent
0f855d19e1
commit
fe7c107c0e
1 changed files with 94 additions and 99 deletions
|
|
@ -7,115 +7,110 @@ import "katex/dist/katex.min.css"
|
||||||
import BodyLink from "./BodyLink"
|
import BodyLink from "./BodyLink"
|
||||||
import EntryLoadingSkeleton from "./EntryLoadingSkeleton"
|
import EntryLoadingSkeleton from "./EntryLoadingSkeleton"
|
||||||
import { useSearchParams } from "react-router"
|
import { useSearchParams } from "react-router"
|
||||||
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./ui/table"
|
||||||
const ImagePreprocessor = (src) => {
|
const ImagePreprocessor = (src) => {
|
||||||
const filename = src.src.split("/").pop()
|
const filename = src.src.split("/").pop()
|
||||||
const s3RootUrl = "https://eolas.s3.systemsobscure.net/"
|
const s3RootUrl = "https://eolas.s3.systemsobscure.net/"
|
||||||
return <img src={s3RootUrl + filename} />
|
return <img src={s3RootUrl + filename} />
|
||||||
}
|
}
|
||||||
|
|
||||||
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
||||||
|
|
||||||
const highlighter = (children, highlight) => {
|
const highlighter = (children, highlight) => {
|
||||||
if (!highlight || typeof children !== "string") return children
|
if (!highlight || typeof children !== "string") return children
|
||||||
const words = highlight.trim().split(/\s+/)
|
const words = highlight.trim().split(/\s+/)
|
||||||
const pattern = words.length > 1 ? escapeRegex(highlight) : escapeRegex(words[0])
|
const pattern = words.length > 1 ? escapeRegex(highlight) : escapeRegex(words[0])
|
||||||
const regex = new RegExp(`\\b(${pattern})\\b`, "gi")
|
const regex = new RegExp(`\\b(${pattern})\\b`, "gi")
|
||||||
const parts = children.split(regex)
|
const parts = children.split(regex)
|
||||||
|
|
||||||
return parts.map((part, i) =>
|
return parts.map((part, i) =>
|
||||||
regex.test(part) ? (
|
regex.test(part) ? (
|
||||||
<mark key={i} className="dark:bg-[#4c1d95] dark:text-white bg-[#ddd6fe]">
|
<mark key={i} className="dark:bg-[#4c1d95] dark:text-white bg-[#ddd6fe]">
|
||||||
{part}
|
{part}
|
||||||
</mark>
|
</mark>
|
||||||
) : (
|
) : (
|
||||||
part
|
part
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EntryBody({ body, isLoading }) {
|
export default function EntryBody({ body, isLoading }) {
|
||||||
const [searchParams] = useSearchParams()
|
const [searchParams] = useSearchParams()
|
||||||
|
|
||||||
const highlight = searchParams.get("highlight")
|
const highlight = searchParams.get("highlight")
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <EntryLoadingSkeleton />
|
return <EntryLoadingSkeleton />
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="max-w-2xl p-4 lg:p-6">
|
<div className="max-w-2xl p-4 lg:p-6">
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
remarkPlugins={[remarkGfm, remarkMath]}
|
remarkPlugins={[remarkGfm, remarkMath]}
|
||||||
rehypePlugins={[rehypeKatex]}
|
rehypePlugins={[rehypeKatex]}
|
||||||
components={{
|
components={{
|
||||||
h1: () => null,
|
h1: () => null,
|
||||||
h2: ({ children }) => (
|
h2: ({ children }) => (
|
||||||
<h2 className="scroll-m-20 font-semibold mt-8 mb-4 first:mt-0">
|
<h2 className="scroll-m-20 font-semibold mt-8 mb-4 first:mt-0">
|
||||||
{highlighter(children, highlight)}
|
{highlighter(children, highlight)}
|
||||||
</h2>
|
</h2>
|
||||||
),
|
),
|
||||||
h3: ({ children }) => (
|
h3: ({ children }) => (
|
||||||
<h3 className="scroll-m-20 font-semibold mt-8 mb-4 first:mt-0">
|
<h3 className="scroll-m-20 font-semibold mt-8 mb-4 first:mt-0">
|
||||||
{highlighter(children, highlight)}
|
{highlighter(children, highlight)}
|
||||||
</h3>
|
</h3>
|
||||||
),
|
),
|
||||||
h4: ({ children }) => (
|
h4: ({ children }) => (
|
||||||
<h4 className="scroll-m-20 font-semibold mt-8 mb-4 first:mt-0">
|
<h4 className="scroll-m-20 font-semibold mt-8 mb-4 first:mt-0">
|
||||||
{highlighter(children, highlight)}
|
{highlighter(children, highlight)}
|
||||||
</h4>
|
</h4>
|
||||||
),
|
),
|
||||||
p: ({ children }) => (
|
p: ({ children }) => (
|
||||||
<p className="leading-[1.5] mb-4 not-first:mt-4">
|
<p className="leading-[1.5] mb-4 not-first:mt-4">
|
||||||
{highlighter(children, highlight)}
|
{highlighter(children, highlight)}
|
||||||
</p>
|
</p>
|
||||||
),
|
),
|
||||||
ul: ({ children }) => <ul className="list-disc ml-10 mb-4 space-y-1">{children}</ul>,
|
ul: ({ children }) => <ul className="list-disc ml-10 mb-4 space-y-1">{children}</ul>,
|
||||||
ol: ({ children }) => (
|
ol: ({ children }) => (
|
||||||
<ol className="list-decimal ml-10 mb-4 space-y-1">{children}</ol>
|
<ol className="list-decimal ml-10 mb-4 space-y-1">{children}</ol>
|
||||||
),
|
),
|
||||||
li: ({ children }) => (
|
li: ({ children }) => (
|
||||||
<li className="list-disc ml-10 mb-4 space-y-1">
|
<li className="list-disc ml-10 mb-4 space-y-1">
|
||||||
{highlighter(children, highlight)}
|
{highlighter(children, highlight)}
|
||||||
</li>
|
</li>
|
||||||
),
|
),
|
||||||
table: ({ children }) => <table className="w-full mb-4 text-sm">{children}</table>,
|
table: ({ children }) => (
|
||||||
tr: ({ children }) => (
|
<Table className="w-full mb-4 text-sm overflow-x-auto">{children}</Table>
|
||||||
<tr className="even:bg-muted m-0 border-t p-0">
|
),
|
||||||
{highlighter(children, highlight)}
|
thead: ({ children }) => <TableHeader>{children}</TableHeader>,
|
||||||
</tr>
|
|
||||||
),
|
tr: ({ children }) => <TableRow>{highlighter(children, highlight)}</TableRow>,
|
||||||
th: ({ children }) => (
|
|
||||||
<th className="border px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right">
|
th: ({ children }) => <TableHead>{highlighter(children, highlight)}</TableHead>,
|
||||||
{highlighter(children, highlight)}
|
td: ({ children }) => <TableCell>{highlighter(children, highlight)}</TableCell>,
|
||||||
</th>
|
tbody: ({ children }) => <TableBody>{children}</TableBody>,
|
||||||
),
|
|
||||||
td: ({ children }) => (
|
blockquote: ({ children }) => (
|
||||||
<td className="border px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right">
|
<blockquote className="mt-4 border-l-2 pl-6 text-muted-foreground">
|
||||||
{highlighter(children, highlight)}
|
{highlighter(children, highlight)}
|
||||||
</td>
|
</blockquote>
|
||||||
),
|
),
|
||||||
blockquote: ({ children }) => (
|
pre: ({ children }) => {
|
||||||
<blockquote className="mt-4 border-l-2 pl-6 text-muted-foreground">
|
const child = children.props
|
||||||
{highlighter(children, highlight)}
|
return <CodeBlock className={child.className}>{child.children}</CodeBlock>
|
||||||
</blockquote>
|
},
|
||||||
),
|
code: ({ children }) => (
|
||||||
pre: ({ children }) => {
|
<code className="rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm">
|
||||||
const child = children.props
|
{children}
|
||||||
return <CodeBlock className={child.className}>{child.children}</CodeBlock>
|
</code>
|
||||||
},
|
),
|
||||||
code: ({ children }) => (
|
img: ({ src }) => <ImagePreprocessor src={src} />,
|
||||||
<code className="rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm">
|
a: ({ href, children }) => {
|
||||||
{children}
|
return <BodyLink link={href} children={children} />
|
||||||
</code>
|
},
|
||||||
),
|
}}
|
||||||
img: ({ src }) => <ImagePreprocessor src={src} />,
|
>
|
||||||
a: ({ href, children }) => {
|
{body}
|
||||||
return <BodyLink link={href} children={children} />
|
</ReactMarkdown>
|
||||||
},
|
</div>
|
||||||
}}
|
)
|
||||||
>
|
|
||||||
{body}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue