HTMLify
blog-preview.tsx
Views: 10 | Author: biisal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | "use client"; import ReactMarkdown from 'react-markdown'; import { JetBrainsMono } from '@/fonts'; import { cn } from '@/lib/utils'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; import remarkGfm from 'remark-gfm'; import remarkBreaks from 'remark-breaks'; interface BlogPreviewProps { content: string; className?: string; } export function BlogPreview({ content, className }: BlogPreviewProps) { return ( <article className={cn("prose prose-invert prose-lg wrap-break-words max-w-none text-blog-fg", JetBrainsMono.className, className)}> <ReactMarkdown remarkPlugins={[remarkGfm, remarkBreaks]} components={{ br() { return <br className="my-4" /> }, h1({ children }) { return <h1 className="text-4xl font-bold mt-8 mb-4 text-blog-orange">{children}</h1> }, h2({ children }) { return <h2 className="text-3xl font-bold mt-8 mb-4 text-blog-orange">{children}</h2> }, h3({ children }) { return <h3 className="text-2xl font-semibold mt-6 mb-3 text-blog-green">{children}</h3> }, h4({ children }) { return <h4 className="text-xl font-semibold mt-6 mb-3 text-blog-green-light">{children}</h4> }, p({ children }) { return <p className="text-base leading-relaxed mb-6">{children}</p> }, ul({ children }) { return <ul className="list-disc list-outside ml-6 mb-6 text-blog-fg marker:text-blog-orange">{children}</ul> }, ol({ children }) { return <ol className="list-decimal list-outside ml-6 mb-6 text-blog-fg marker:text-blog-orange">{children}</ol> }, li({ children }) { return <li className="mb-2 pl-2">{children}</li> }, strong({ children }) { return <strong className="font-bold text-blog-red">{children}</strong> }, blockquote({ children }) { return <blockquote className="border-l-4 border-blog-cyan pl-4 italic text-blog-cyan my-6">{children}</blockquote> }, table({ children }) { return <table className="w-full my-6 border-collapse border border-blog-cyan">{children}</table> }, thead({ children }) { return <thead className="bg-blog-black">{children}</thead> }, tbody({ children }) { return <tbody>{children}</tbody> }, tr({ children }) { return <tr className="border-b border-blog-cyan">{children}</tr> }, th({ children }) { return <th className="border border-blog-cyan px-4 py-2 text-left font-semibold text-blog-orange">{children}</th> }, td({ children }) { return <td className="border border-blog-cyan px-4 py-2 text-blog-fg">{children}</td> }, code({ node, className, children, ...props }) { const match = /language-(\w+)/.exec(className || ''); const isInline = !match; if (isInline) { return ( <code className={cn(`bg-blog-black text-blog-orange px-1.5 py-0.5 rounded text-sm`, JetBrainsMono.className)} {...props}> {children} </code> ) } return ( <SyntaxHighlighter style={oneDark} language={match[1]} PreTag="div" className="my-4 rounded-lg border border-blog-selection-bg" customStyle={{ margin: 0, padding: '1rem', background: '#16161E', fontSize: '0.875rem', }} codeTagProps={{ className: JetBrainsMono.className }} > {String(children).replace(/\n$/, '')} </SyntaxHighlighter> ) } }} > {content} </ReactMarkdown> </article> ); } |