import { useCallback } from 'react'; import { BlogOutlineSection } from '../services/blogWriterApi'; export const useMarkdownProcessor = ( outline: BlogOutlineSection[], sections: Record ) => { const buildFullMarkdown = useCallback(() => { if (!outline.length) return ''; return outline.map(s => `## ${s.heading}\n\n${sections[s.id] || ''}`).join('\n\n'); }, [outline, sections]); const convertMarkdownToHTML = useCallback((md: string) => { if (!md) return ''; let html = md; // Headings (must be first, before other replacements) html = html.replace(/^### (.*$)/gim, '

$1

'); html = html.replace(/^## (.*$)/gim, '

$1

'); html = html.replace(/^# (.*$)/gim, '

$1

'); // Bold and Italic html = html.replace(/\*\*(.+?)\*\*/g, '$1'); html = html.replace(/\*(.+?)\*/g, '$1'); // Links [text](url) - handle both http and data:image URLs html = html.replace(/\[(.+?)\]\((.+?)\)/g, (match, text, url) => { const safeUrl = url.replace(/"/g, '"'); if (url.startsWith('data:image') || url.startsWith('http')) { return `${text}`; } return `${text}`; }); // Images ![alt](url) - explicit image syntax html = html.replace(/!\[(.+?)\]\((.+?)\)/g, '$1'); // Blockquotes html = html.replace(/^> (.+)$/gm, '
$1
'); // Inline code html = html.replace(/`(.+?)`/g, '$1'); // Horizontal rules html = html.replace(/^-{3,}$/gm, '
'); // Unordered lists (- item or * item) html = html.replace(/^[-*] (.+)$/gm, '
  • $1
  • '); // Wrap consecutive
  • tags in