Markdown
prompt-kit/markdownFreeComponent
A component for rendering Markdown content with support for code blocks, GFM, and custom styling
Live preview
live · rendered by the registry
Rendered by prompt-kit on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://raw.githubusercontent.com/ibelick/prompt-kit/HEAD/public/c/markdown.jsonSource
1import { cn } from "@/lib/utils"2import { marked } from "marked"3import { memo, useId, useMemo } from "react"4import ReactMarkdown, { Components } from "react-markdown"5import remarkBreaks from "remark-breaks"6import remarkGfm from "remark-gfm"7import { CodeBlock, CodeBlockCode } from "./code-block"89export type MarkdownProps = {10 children: string11 id?: string12 className?: string13 components?: Partial<Components>14}1516function parseMarkdownIntoBlocks(markdown: string): string[] {17 const tokens = marked.lexer(markdown)18 return tokens.map((token) => token.raw)19}2021function extractLanguage(className?: string): string {22 if (!className) return "plaintext"23 const match = className.match(/language-(\w+)/)24 return match ? match[1] : "plaintext"25}2627const INITIAL_COMPONENTS: Partial<Components> = {28 code: function CodeComponent({ className, children, ...props }) {29 const isInline =30 !props.node?.position?.start.line ||31 props.node?.position?.start.line === props.node?.position?.end.line3233 if (isInline) {34 return (35 <span36 className={cn(37 "bg-primary-foreground rounded-sm px-1 font-mono text-sm",38 className39 )}40 {...props}41 >42 {children}43 </span>44 )45 }4647 const language = extractLanguage(className)4849 return (50 <CodeBlock className={className}>51 <CodeBlockCode code={children as string} language={language} />52 </CodeBlock>53 )54 },55 pre: function PreComponent({ children }) {56 return <>{children}</>57 },58}5960const MemoizedMarkdownBlock = memo(61 function MarkdownBlock({62 content,63 components = INITIAL_COMPONENTS,64 }: {65 content: string66 components?: Partial<Components>67 }) {68 return (69 <ReactMarkdown70 remarkPlugins={[remarkGfm, remarkBreaks]}71 components={components}72 >73 {content}74 </ReactMarkdown>75 )76 },77 function propsAreEqual(prevProps, nextProps) {78 return prevProps.content === nextProps.content79 }80)8182MemoizedMarkdownBlock.displayName = "MemoizedMarkdownBlock"8384function MarkdownComponent({85 children,86 id,87 className,88 components = INITIAL_COMPONENTS,89}: MarkdownProps) {90 const generatedId = useId()91 const blockId = id ?? generatedId92 const blocks = useMemo(() => parseMarkdownIntoBlocks(children), [children])9394 return (95 <div className={className}>96 {blocks.map((block, index) => (97 <MemoizedMarkdownBlock98// … truncated
What it pulls in
npm packages
Files it writes
More from prompt-kit
All 23 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Chain Of Thoughtchain-of-thought | prompt-kit | Components | Free | 1 dep | |
| Chat Containerchat-container | prompt-kit | Components | Free | 1 dep | |
| Code Blockcode-block | prompt-kit | Components | Free | 1 dep | |
| Feedback Barfeedback-bar | prompt-kit | Components | Free | 1 dep | |
| File Uploadfile-upload | prompt-kit | Components | Free | no deps | |
| Imageimage | prompt-kit | Components | Free | no deps | |
| Jsx Previewjsx-preview | prompt-kit | Components | Free | 1 dep | |
| Loaderloader | prompt-kit | Components | Free | no deps |
