markdown
An opinionated markdown component that can be used to display markdown content. It was a conscious choice to not include syntax highlighting for code blocks as I wanted to give users freedom to use their preferred syntax highlighter.
Lorem Ipsum
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Installation
npx shadcn add "https://registry.niels.foo/markdown.json"
With Code
You can use the Code
component within the Markdown
component to
display syntax highlighted code properly within a Markdown document.
To do this edit the components/ui/markdown.tsx
component and uncomment
the code that is there.
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
import ReactMarkdown, { Options } from "react-markdown"; import remarkGfm from "remark-gfm"; import { cn } from "@/lib/utils"; export type MarkdownProps = Options; export function Markdown({ children, className, ...props }: MarkdownProps) { return ( <ReactMarkdown className={cn( "prose prose-neutral break-words dark:prose-invert prose-p:leading-relaxed prose-pre:overflow-visible prose-pre:bg-inherit prose-pre:p-0 prose-p:m-0", className )} remarkPlugins={[remarkGfm]} components={{ p({ children }) { return <p className="mb-2 last:mb-0">{children}</p>; }, code({ children, className, ...rest }) { const match = /language-(\w+)/.exec(className || ""); if (!match) { return ( <code {...rest} className={cn("font-semibold text-primary", className)} > {children} </code> ); } const code = String(children).replace(/\n$/, ""); const language = match[1]; return ( <Code language={language}> <CodeHeader> <CodeLanguage /> <CodeCopyButton /> </CodeHeader> <CodeContent showLineNumbers>{code}</CodeContent> </Code> ); }, }} {...props} > {children} </ReactMarkdown> ); }
Source
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
import ReactMarkdown, { Options } from "react-markdown";
import remarkGfm from "remark-gfm";
import { cn } from "@/lib/utils";
export type MarkdownProps = Options;
export function Markdown({ children, className, ...props }: MarkdownProps) {
return (
<ReactMarkdown
className={cn(
"prose prose-neutral break-words dark:prose-invert prose-p:leading-relaxed prose-pre:overflow-visible prose-pre:bg-inherit prose-pre:p-0",
className
)}
remarkPlugins={[remarkGfm]}
components={{
p({ children }) {
return <p className="mb-2 last:mb-0">{children}</p>;
},
code({ children, className, ...rest }) {
// const match = /language-(\w+)/.exec(className || "");
// if (!match) {
// return (
// <code
// {...rest}
// className={cn("font-semibold text-primary", className)}
// >
// {children}
// </code>
// );
// }
// const code = String(children).replace(/\n$/, "");
// const language = match[1];
// return (
// <Code language={language}>
// <CodeHeader>
// <CodeLanguage />
// <CodeCopyButton />
// </CodeHeader>
// <CodeContent showLineNumbers>
// {code}
// </CodeContent>
// </Code>
// );
return (
<code
{...rest}
className={cn("font-semibold text-primary", className)}
>
{children}
</code>
);
},
}}
{...props}
>
{children}
</ReactMarkdown>
);
}