// app/components/MarkdownModal.tsx import { X, Download } from "lucide-react"; import { jsPDF } from "jspdf"; import { useState } from "react"; import { type PageObject } from "../page"; // Importer le type depuis la page principale interface HtmlModalProps { content: PageObject[] | null; // Utilise le type PageObject importé onClose: () => void; } // Moteur de rendu HTML vers PDF, robuste et récursif const renderHtmlOnPdfPage = (pdf: jsPDF, htmlContent: string) => { const pageHeight = pdf.internal.pageSize.getHeight(); const pageWidth = pdf.internal.pageSize.getWidth(); const margin = 15; let cursorY = margin; const container = document.createElement("div"); container.innerHTML = htmlContent; const processNode = ( node: ChildNode, currentStyle: { fontStyle: "normal" | "bold" | "italic"; fontSize: number } ) => { if (cursorY > pageHeight - margin) { pdf.addPage(); cursorY = margin; } const nextStyle = { ...currentStyle }; let spacingAfter = 0; switch (node.nodeName) { case "H1": nextStyle.fontSize = 22; nextStyle.fontStyle = "bold"; spacingAfter = 8; break; case "H2": nextStyle.fontSize = 18; nextStyle.fontStyle = "bold"; spacingAfter = 6; break; case "H3": nextStyle.fontSize = 14; nextStyle.fontStyle = "bold"; spacingAfter = 4; break; case "P": nextStyle.fontSize = 10; nextStyle.fontStyle = "normal"; spacingAfter = 4; break; case "UL": spacingAfter = 4; break; case "STRONG": case "B": nextStyle.fontStyle = "bold"; break; } if (node.nodeType === Node.TEXT_NODE && node.textContent?.trim()) { pdf.setFontSize(nextStyle.fontSize); pdf.setFont("Helvetica", nextStyle.fontStyle); const textLines = node.textContent.split("\n"); textLines.forEach((line) => { if (line.trim() === "") { cursorY += nextStyle.fontSize * 0.4; return; } const splitText = pdf.splitTextToSize(line, pageWidth - margin * 2); pdf.text(splitText, margin, cursorY); cursorY += splitText.length * nextStyle.fontSize * 0.4; }); } else if (node.nodeName === "UL") { Array.from((node as HTMLUListElement).children).forEach((li) => { const liText = `• ${li.textContent?.trim() || ""}`; const lines = pdf.splitTextToSize(liText, pageWidth - margin * 2 - 5); pdf.setFontSize(10); pdf.setFont("Helvetica", "normal"); pdf.text(lines, margin + 5, cursorY); cursorY += lines.length * 10 * 0.4 + 2; }); } if (node.childNodes.length > 0) { node.childNodes.forEach((child) => processNode(child, nextStyle)); } cursorY += spacingAfter; }; container.childNodes.forEach((node) => processNode(node, { fontStyle: "normal", fontSize: 10 }) ); }; export default function MarkdownModal({ content, onClose }: HtmlModalProps) { const [isDownloading, setIsDownloading] = useState(false); if (!content) return null; const handleDownloadPdf = async () => { if (!content || content.length === 0) return; setIsDownloading(true); try { const pdf = new jsPDF({ orientation: "p", unit: "mm", format: "a4" }); pdf.setFont("Helvetica", "normal"); // Mis à jour pour boucler sur les objets et passer le contenu HTML content.forEach((page, index) => { if (index > 0) pdf.addPage(); renderHtmlOnPdfPage(pdf, page.htmlContent); }); pdf.save("document_anonymise.pdf"); } catch (error) { console.error("Erreur lors de la génération du PDF:", error); } finally { setIsDownloading(false); } }; // Mis à jour pour extraire le contenu HTML de chaque page avant de l'afficher const previewHtml = content .map((page) => page.htmlContent) .join( '