import React, { useState, useEffect, useRef } from 'react' import { RelayPool } from 'applesauce-relay' import { extractNaddrUris, replaceNostrUrisInMarkdown, replaceNostrUrisInMarkdownWithTitles } from '../utils/nostrUriResolver' import { fetchArticleTitles } from '../services/articleTitleResolver' /** * Hook to convert markdown to HTML using a hidden ReactMarkdown component * Also processes nostr: URIs in the markdown and resolves article titles */ export const useMarkdownToHTML = ( markdown?: string, relayPool?: RelayPool | null ): { renderedHtml: string previewRef: React.RefObject processedMarkdown: string } => { const previewRef = useRef(null) const [renderedHtml, setRenderedHtml] = useState('') const [processedMarkdown, setProcessedMarkdown] = useState('') useEffect(() => { if (!markdown) { setRenderedHtml('') setProcessedMarkdown('') return } let isCancelled = false const processMarkdown = async () => { // Extract all naddr references const naddrs = extractNaddrUris(markdown) let processed: string if (naddrs.length > 0 && relayPool) { // Fetch article titles for all naddrs try { const articleTitles = await fetchArticleTitles(relayPool, naddrs) if (isCancelled) return // Replace nostr URIs with resolved titles processed = replaceNostrUrisInMarkdownWithTitles(markdown, articleTitles) console.log(`📚 Resolved ${articleTitles.size} article titles`) } catch (error) { console.warn('Failed to fetch article titles:', error) // Fall back to basic replacement processed = replaceNostrUrisInMarkdown(markdown) } } else { // No articles to resolve, use basic replacement processed = replaceNostrUrisInMarkdown(markdown) } if (isCancelled) return setProcessedMarkdown(processed) console.log('📝 Converting markdown to HTML...') const rafId = requestAnimationFrame(() => { if (previewRef.current && !isCancelled) { const html = previewRef.current.innerHTML console.log('✅ Markdown converted to HTML:', html.length, 'chars') setRenderedHtml(html) } else if (!isCancelled) { console.warn('⚠️ markdownPreviewRef.current is null') } }) return () => cancelAnimationFrame(rafId) } processMarkdown() return () => { isCancelled = true } }, [markdown, relayPool]) return { renderedHtml, previewRef, processedMarkdown } } // Removed separate useMarkdownPreviewRef; use useMarkdownToHTML to obtain previewRef