diff --git a/src/components/nostr/MarkdownContent.tsx b/src/components/nostr/MarkdownContent.tsx index f967a2d..d18a14c 100644 --- a/src/components/nostr/MarkdownContent.tsx +++ b/src/components/nostr/MarkdownContent.tsx @@ -154,6 +154,8 @@ export function MarkdownContent({ content, canonicalUrl = null, }: MarkdownContentProps) { + const { addWindow } = useGrimoire(); + // Helper to resolve relative URLs using canonical URL as base const resolveUrl = useMemo( () => @@ -214,7 +216,7 @@ export function MarkdownContent({ /> ); }, - // Handle nostr: links + // Handle links: nostr mentions, NIP links, and regular URLs a: ({ href, children, ...props }) => { if (!href) return null; @@ -223,11 +225,42 @@ export function MarkdownContent({ return ; } - // Regular links + // Check if it's a relative NIP link (e.g., "./01.md" or "01.md") + const isRelativeLink = + !href.startsWith("http://") && !href.startsWith("https://"); + if ( + isRelativeLink && + (href.endsWith(".md") || href.includes(".md#")) + ) { + // Extract NIP number from various formats (numeric 1-3 digits or hex A0-FF) + const nipMatch = href.match(/([0-9A-F]{1,3})\.md/i); + if (nipMatch) { + const nipNumber = nipMatch[1].toUpperCase(); + return ( + { + e.preventDefault(); + e.stopPropagation(); + addWindow( + "nip", + { number: nipNumber }, + `NIP ${nipNumber}`, + ); + }} + className="text-accent underline decoration-dotted cursor-crosshair hover:text-accent/80" + > + {children} + + ); + } + } + + // Regular links with break-all for long URLs return ( > = { 7: Kind7Renderer, // Reaction 9: Kind9Renderer, // Chat Message (NIP-C7) 16: RepostRenderer, // Generic Repost + 17: Kind7Renderer, // Reaction (NIP-25) 20: Kind20Renderer, // Picture (NIP-68) 21: Kind21Renderer, // Video Event (NIP-71) 22: Kind22Renderer, // Short Video (NIP-71)