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)