import { Event, kinds } from 'nostr-tools' import { Highlighter } from 'lucide-react' import { nip19 } from 'nostr-tools' import logger from '@/lib/logger' import HighlightSourcePreview from '@/components/UniversalContent/HighlightSourcePreview' import UserAvatar from '@/components/UserAvatar' import Username from '@/components/Username' import { useSmartNoteNavigationOptional } from '@/PageManager' import { toNote } from '@/lib/link' import { isPseudoNostrHttpsUrl } from '@/lib/url' import { useFetchEvent } from '@/hooks' import { useEffect, useState, useMemo } from 'react' import { ExtendedKind } from '@/constants' import { resolveNip84HighlightDisplay } from '@/lib/nip84-highlight-display' function stripOuterQuotes(s: string): string { let t = s.trim() if (t.startsWith('"') && t.endsWith('"')) { t = t.slice(1, -1).trim() } return t } /** * Check if a string is a URL or Nostr address */ function isUrlOrNostrAddress(value: string | undefined): boolean { if (!value || typeof value !== 'string') { return false } // Check if it's a URL (http://, https://, or starts with common URL patterns) try { if (value.startsWith('http://') || value.startsWith('https://') || value.startsWith('ws://') || value.startsWith('wss://')) { new URL(value) // Validate it's a proper URL return true } } catch { // Not a valid URL } // Check if it's a Nostr address (nostr: prefix or bech32 encoded) if (value.startsWith('nostr:')) { return true } // Check if it's a bech32 encoded Nostr address try { const decoded = nip19.decode(value) if (['npub', 'nprofile', 'nevent', 'naddr', 'note', 'nrelay'].includes(decoded.type)) { return true } } catch { // Not a valid Nostr address } return false } /** * Simple author card for highlights with Nostr sources (e-tags, r-tags) * Shows just "A note from: [user badge]" instead of the full embedded note * The word "note" is a hyperlink to the referenced event */ function HighlightAuthorCard({ authorPubkey, eventId, onClick }: { authorPubkey: string eventId?: string onClick?: () => void }) { const { navigateToNote } = useSmartNoteNavigationOptional() const handleNoteClick = (e: React.MouseEvent) => { e.stopPropagation() if (onClick) { onClick() } else if (eventId) { navigateToNote(toNote(eventId)) } } return (