import { useMemo } from 'react'; import { type NostrEvent } from '@nostrify/nostrify'; import { Link } from 'react-router-dom'; import { nip19 } from 'nostr-tools'; import { useAuthor } from '@/hooks/useAuthor'; import { genUserName } from '@/lib/genUserName'; import { cn } from '@/lib/utils'; interface NoteContentProps { event: NostrEvent; className?: string; } /** Parses content of text note events so that URLs and hashtags are linkified. */ export function NoteContent({ event, className, }: NoteContentProps) { // Process the content to render mentions, links, etc. const content = useMemo(() => { const text = event.content; // Regex to find URLs, Nostr references, and hashtags const regex = /(https?:\/\/[^\s]+)|nostr:(npub1|note1|nprofile1|nevent1)([023456789acdefghjklmnpqrstuvwxyz]+)|(#\w+)/g; const parts: React.ReactNode[] = []; let lastIndex = 0; let match: RegExpExecArray | null; let keyCounter = 0; while ((match = regex.exec(text)) !== null) { const [fullMatch, url, nostrPrefix, nostrData, hashtag] = match; const index = match.index; // Add text before this match if (index > lastIndex) { parts.push(text.substring(lastIndex, index)); } if (url) { // Handle URLs parts.push( {url} ); } else if (nostrPrefix && nostrData) { // Handle Nostr references try { const nostrId = `${nostrPrefix}${nostrData}`; const decoded = nip19.decode(nostrId); if (decoded.type === 'npub') { const pubkey = decoded.data; parts.push( ); } else { // For other types, just show as a link parts.push( {fullMatch} ); } } catch { // If decoding fails, just render as text parts.push(fullMatch); } } else if (hashtag) { // Handle hashtags const tag = hashtag.slice(1); // Remove the # parts.push( {hashtag} ); } lastIndex = index + fullMatch.length; } // Add any remaining text if (lastIndex < text.length) { parts.push(text.substring(lastIndex)); } // If no special content was found, just use the plain text if (parts.length === 0) { parts.push(text); } return parts; }, [event]); return (
{content.length > 0 ? content : event.content}
); } // Helper component to display user mentions function NostrMention({ pubkey }: { pubkey: string }) { const author = useAuthor(pubkey); const npub = nip19.npubEncode(pubkey); const hasRealName = !!author.data?.metadata?.name; const displayName = author.data?.metadata?.name ?? genUserName(pubkey); return ( @{displayName} ); }