Markdown
more-shadcn-noair/markdownFreeComponent
Render user-generated content, blog posts, or comments with optimized typography and safety.
Live preview
live · rendered by the registry
Rendered by more-shadcn-noair on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://more-shadcn.noair.fun/r/markdown.jsonSource
1<script lang="ts">2 import { cn } from '$UTILS$';34 let {5 content = '',6 class: className7 }: {8 content: string;9 class?: string;10 } = $props();1112 function parseMarkdown(md: string) {13 let html = md.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');1415 html = html.replace(/^---$/gm, '<hr class="my-4 border-t border-border" />');1617 html = html.replace(/^### (.*$)/gm, '<h3 class="text-lg font-bold mt-4 mb-1">$1</h3>');18 html = html.replace(/^## (.*$)/gm, '<h2 class="text-xl font-bold mt-5 mb-2">$1</h2>');19 html = html.replace(/^# (.*$)/gm, '<h1 class="text-2xl font-black mt-6 mb-3">$1</h1>');2021 html = html.replace(22 /^(?:>|>) (.*$)/gm,23 '<blockquote class="border-l-4 border-primary/30 pl-4 py-1 italic text-muted-foreground my-3">$1</blockquote>'24 );2526 html = html.replace(/\*\*\*(.*?)\*\*\*/g, '<strong><em>$1</em></strong>');27 html = html.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');28 html = html.replace(/\*(.*?)\*/g, '<em>$1</em>');29 html = html.replace(/__(.*?)__/g, '<strong>$1</strong>');30 html = html.replace(/_(.*?)_/g, '<em>$1</em>');3132 html = html.replace(33 /\[([^\]]+)\]\(([^)]+)\)/g,34 '<a href="$2" class="text-primary font-medium underline underline-offset-4 hover:opacity-80 transition-opacity" target="_blank" rel="noopener noreferrer">$1</a>'35 );3637 html = html.replace(38 /`(.*?)`/g,39 '<code class="bg-muted px-1.5 py-0.5 rounded text-[0.85em] font-mono border border-border/50">$1</code>'40 );4142 html = html.replace(/^[\*\+-] (.*$)/gm, '<li class="ml-4 list-disc pl-1">$1</li>');43 html = html.replace(/^\d+\. (.*$)/gm, '<li class="ml-4 list-decimal pl-1">$1</li>');4445 const lines = html.split('\n');46 let processed = [];47 let inList = false;4849 for (let line of lines) {50 const l = line.trim();51 const isLi = l.startsWith('<li');5253 if (isLi && !inList) {54 processed.push('<ul class="my-3 space-y-1">');55 inList = true;56 } else if (!isLi && inList) {57 processed.push('</ul>');58 inList = false;59 }6061 if (62 l &&63 !l.startsWith('<h') &&64 !l.startsWith('<li') &&65 !l.startsWith('<hr') &&66 !l.startsWith('<blockquote') &&67 !l.startsWith('<ul') &&68 !l.startsWith('</ul')69 ) {70 processed.push(`<p class="mb-3 last:mb-0">${line}</p>`);71 } else {72 processed.push(line);73 }74 }7576 if (inList) processed.push('</ul>');7778 return processed.join('\n').trim();79 }8081// … truncated
More from more-shadcn-noair
All 43 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Audioaudio | more-shadcn-noair | Components | Free | no deps | |
| Audio Waveaudio-wave | more-shadcn-noair | Components | Free | no deps | |
| Autocompleteautocomplete | more-shadcn-noair | Components | Free | no deps | |
| Bannerbanner | more-shadcn-noair | Components | Free | no deps | |
| Big Calendarbig-calendar | more-shadcn-noair | Components | Free | no deps | |
| Bottom Navigationbottom-nav | more-shadcn-noair | Components | Free | no deps | |
| Canvascanvas | more-shadcn-noair | Components | Free | no deps | |
| Chipchip | more-shadcn-noair | Components | Free | no deps |
