keep my ai conversations with formulas

keep conversations with formulas , generated by deepseek, chatgpt , mistral or claude

// ==UserScript==
// @name         keep my ai conversations with formulas
// @name:fr      conserver mes conversations ia avec formules
// @description  keep conversations with formulas , generated by deepseek, chatgpt , mistral or claude
// @description:fr  conserver mes conversations ia avec formules , générées par deepseek, chatgpt , mistral ou claude
// @license MIT
// @namespace    http://tampermonkey.net/
// @version      2025-04-04
// @author       Guerard F
// @match        https://*/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    function processNode(node) {
        if (node.nodeType === Node.TEXT_NODE) {
            return node.textContent;
        }
        if (node.nodeType === Node.ELEMENT_NODE) {

            return node.outerHTML;
        }
        return '';
    }
    function extractMessages() {
        let htmlContent = `
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document avec KaTeX</title>
    <!-- KaTeX CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css">
    <!-- KaTeX JavaScript -->
    <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js"></script>
    <!-- Auto-render Extension -->
    <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js"
        onload="renderMathInElement(document.body);"></script>
    <style>
    body {
      font-family: Arial, sans-serif;
      line-height: 1.6;
      padding: 20px;
    }
    .message {
      margin-bottom: 20px;
      padding: 10px;
      border-radius: 5px;
    }
    .question {
      background-color: #e0f7fa;
    }
    .reponse {
      background-color: #f1f8e9;
    }
    .role {
      font-weight: bold;
      margin-bottom: 5px;
    }
    </style>
</head>
<body>
        `;
        let clonedbody=document.body.cloneNode(true);
        clonedbody.querySelectorAll('svg').forEach(svg => svg.remove());
        if (ia=="deepseek" || ia=="gpt" || ia=="mistral" || ia=="claude") {
            if (ia=="deepseek" || ia=="gpt" || ia=="mistral") {
                clonedbody.querySelectorAll('span.katex').forEach(katexspan => {
                    const annotations = katexspan.querySelectorAll('annotation');
                    if (annotations.length === 1) {
                        const annotcontexttext = annotations[0].textContent;
                        const newSpan = document.createElement('span');
                        newSpan.textContent = `\\( ${annotcontexttext} \\)`;
                        katexspan.replaceWith(newSpan);
                    } else {
                        anomalies +='annotations non 1 trouvée;';
                    }
                });
            }

            switch (ia) {
                case "deepseek": {
                    let messages = clonedbody.querySelectorAll("div.fbb737a4, div.ds-markdown--block");
                    for (let i = 0; i < messages.length; i++) {
                        if (messages[i].classList.contains("fbb737a4")) {
                            const question = messages[i].textContent.trim();
                            let answer = "";
                            if (messages[i + 1] && messages[i + 1].classList.contains("ds-markdown--block")) {
                                answer = processNode(messages[i + 1]).trim();
                                i++;
                            }
                            htmlContent += `\n<div class="message question"><p><strong>Question:</strong></p>${question}</div>`;
                            htmlContent += `\n<div class="message reponse"><p><strong>Answer:</strong></p>${answer}</div>`;
                        }
                    }
                    break;
                }
                case "gpt": {
                    let messages = clonedbody.querySelectorAll("article.w-full");
                    for (let i = 0; i < messages.length; i++) {
                        const question = messages[i].textContent.trim();
                        const answer = processNode(messages[i + 1]).trim();
                        htmlContent += `\n<div class="message question"><p><strong>Question:</strong></p>${question}</div>`;
                        htmlContent += `\n<div class="message reponse"><p><strong>Answer:</strong></p>${answer}</div>`;
                        i++;
                    }
                    break;
                }
                case "mistral": {
                    let messages = clonedbody.querySelectorAll("div.group.gap-3");
                    for (let i = 0; i < messages.length; i++) {
                        const question = messages[i].textContent.trim();
                        const answer = processNode(messages[i + 1]).trim();
                        htmlContent += `\n<div class="message question"><p><strong>Question:</strong></p>${question}</div>`;
                        htmlContent += `\n<div class="message reponse"><p><strong>Answer:</strong></p>${answer}</div>`;
                        i++;
                    }
                    break;
                }
                case "claude": {
                    let messages = clonedbody.querySelectorAll("div[data-test-render-count]");
                    for (let i = 0; i < messages.length; i++) {
                        const question = messages[i].textContent.trim();
                        const answer = messages[i+1].outerHTML;
                        htmlContent += `\n<div class="message question"><p><strong>Question:</strong></p>${question}</div>`;
                        htmlContent += `\n<div class="message reponse"><p><strong>Answer:</strong></p>${answer}</div>`;
                        i++;
                    }
                    break;
                }
            }

            htmlContent += '\n</body></html>';
            const blob = new Blob([htmlContent], {type: 'text/html'});
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `export(${ia}).html`;
            a.click();
        }
    }
    let anomalies="anomalies?";
    var currentUrl = window.location.href;
    let ia="";
    switch (true) {
        case currentUrl.startsWith("https://chat.deepseek.com/"):
            ia="deepseek";
            break;
        case currentUrl.startsWith("https://chatgpt.com/"):
            ia="gpt";
            break;
        case currentUrl.startsWith("https://chat.mistral.ai/"):
            ia="mistral";
            break;
        case currentUrl.startsWith("https://claude.ai/"):
            ia="claude";
            break;
    }
    document.addEventListener('contextmenu', function(event) {
        const btn = document.createElement('button');
        btn.textContent = 'Export HTML';
        btn.style.zIndex = '9999';
        btn.style.position = 'fixed';
        btn.onclick = extractMessages;
        if (ia!="") {
            document.body.insertBefore(btn, document.body.firstChild);
        }
    }, true);
})();