Mrrrr's Forum (VIEW ONLY)
Un forum care ofera solutii pentru unele probleme legate in general de PC. Pe langa solutii, aici puteti gasi si alte lucruri interesante // A forum that offers solutions to some PC related issues. Besides these, here you can find more interesting stuff.
Lista Forumurilor Pe Tematici
Mrrrr's Forum (VIEW ONLY) | Reguli | Inregistrare | Login

POZE MRRRR'S FORUM (VIEW ONLY)

Nu sunteti logat.
Nou pe simpatie:
Ank_beleaua din Bucuresti
Femeie
25 ani
Bucuresti
cauta Barbat
35 - 51 ani
Mrrrr's Forum (VIEW ONLY) / Tutoriale si Ghiduri Utile // Tutorials and useful guides / [CHROME, TAMPERMONKEY] Save Current ChatGPT Chat as PDF File Properly Moderat de TRaP, TonyTzu
Autor
Mesaj Pagini: 1
Mrrrr
AdMiN

Inregistrat: acum 19 ani
Postari: 2387
Made the following Tampermonkey script with ChatGPT that creates 2 buttons in the bottom right side of the ChatGPT chat allowing Export PDF or Export DOCX.

When previously trying to print page, it would not get everything - some text would be missing, chat would be shortened.

You can add @match for gemini as well, maybe other AIs.

This way you get everything:

// ==UserScript==
// @name         Local ChatGPT Exporter (PDF & DOCX)
// @namespace   
// @version      1.1
// @description  Export ChatGPT chats to PDF or DOCX cleanly without third-party servers.
// @author       Mrrrr
// @match       
// @match       
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

function createUI() {
        if (document.getElementById('local-exporter-container')) return;

        const container = document.createElement('div');
        container.id = 'local-exporter-container';
        container.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            z-index: 99999;
            display: flex;
            gap: 8px;
            background: rgba(0, 0, 0, 0.85);
            padding: 8px 12px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.4);
            backdrop-filter: blur(4px);
        `;

        const btnPdf = createButton('📄 Export PDF', '#10a37f', function () { exportChat('pdf'); });
        const btnDocx = createButton('📝 Export DOCX', '#2b579a', function () { exportChat('docx'); });

        container.appendChild(btnPdf);
        container.appendChild(btnDocx);

        if (document.body) {
            document.body.appendChild(container);
        }
    }

    function createButton(text, color, onClick) {
        const btn = document.createElement('button');
        btn.innerText = text;
        btn.style.cssText = `
            background-color: ${color};
            color: white;
            border: none;
            padding: 8px 14px;
            border-radius: 6px;
            font-size: 13px;
            font-weight: bold;
            cursor: pointer;
            transition: opacity 0.2s;
        `;
        btn.onmouseover = function () {
            btn.style.opacity = '0.85';
        };
        btn.onmouseout = function () {
            btn.style.opacity = '1';
        };
        btn.onclick = onClick;
        return btn;
    }

function extractTurns() {
        const turns = [];
        const seenTexts = new Set();

        // Find all message groups/blocks
        const turnNodes = document.querySelectorAll('[data-message-author-role], article, div[class*="agent-turn"], div[class*="user-turn"]');

        if (turnNodes.length > 0) {
            turnNodes.forEach(function (node) {
                // Skip hidden duplicate containers generated for internal model state/drafts
                if (node.offsetParent === null && !node.classList.contains('markdown')) return;

                const roleAttr = node.getAttribute('data-message-author-role');
                let author = 'ChatGPT';

                if (roleAttr === 'user' || node.querySelector('[data-message-author-role="user"]') || node.innerText.includes('You said:')) {
                    author = 'User';
                }

                // Get inner markdown content
                const contentNode = node.querySelector('.markdown, [class*="markdown"]') || node;
                const htmlContent = contentNode.innerHTML;
                const textContent = contentNode.innerText.trim();

// #### update v1.1 - Loading image added page break in print preview

// Create a temporary element to clean up internal ChatGPT UI clutter
const cleanEl = document.createElement('div');
cleanEl.innerHTML = htmlContent;

// 1. Remove loading containers, spinners, and SVG wrappers entirely
cleanEl.querySelectorAll('[title="Loading..."], svg, .motion-safe\\:animate-spin').forEach(el => el.remove());

// 2. Remove giant inline width/height attributes from image placeholders
cleanEl.querySelectorAll('[style*="2048px"], [style*="aspect-ratio"]').forEach(el => {
    el.style.width = 'auto';
    el.style.height = 'auto';
    el.style.aspectRatio = 'auto';
});

const cleanedHtml = cleanEl.innerHTML;
// ####

                // Deduplicate consecutive or identical responses and skip empty blocks
                if (textContent.length > 0 && !seenTexts.has(textContent)) {
                    seenTexts.add(textContent);
                    turns.push({
                        author: author,
html: cleanedHtml // ####
                        // html: htmlContent // #### commented this line (the above one replaces it)
                    });
                }
            });
        }

        return turns;
    }

    function exportChat(type) {
        const turns = extractTurns();

        if (turns.length === 0) {
            alert('No chat content could be extracted. Please make sure the conversation is open.');
            return;
        }

        const rawTitle = document.title.replace(/[^a-zA-Z0-9 _-]/g, '').trim() || 'ChatGPT_Export';

        let contentHtml = `<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>${rawTitle}</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; color: #111; padding: 30px; max-width: 800px; margin: 0 auto; }
        .turn { margin-bottom: 24px; padding-bottom: 16px; border-bottom: 1px solid #e5e5e5; page-break-inside: auto; }
        .author { font-weight: 700; font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 8px; }
        .User .author { color: #0066cc; }
        .ChatGPT .author { color: #10a37f; }
        pre { background: #f4f4f5; padding: 12px; border-radius: 6px; overflow-x: auto; white-space: pre-wrap; word-break: break-all; font-family: monospace; font-size: 13px; }
        code { background: #f4f4f5; padding: 2px 5px; border-radius: 4px; font-family: monospace; font-size: 13px; }
        table { border-collapse: collapse; width: 100%; margin: 14px 0; }
        th, td { border: 1px solid #e5e5e5; padding: 8px 12px; text-align: left; }
        th { background-color: #f8f9fa; }
        .content img { max-height: 16px; object-fit: contain; }
        button { display: none !important; }
        svg { display: none !important; }
        .sr-only { display: none !important; }
        @media print {
            body { max-width: 100%; padding: 0; }
            .turn { page-break-inside: auto; }
        }
    </style>
</head>
<body>
    <h2>${rawTitle}</h2>
    <hr style="border: none; border-top: 1px solid #ccc; margin-bottom: 20px;">
`;

        turns.forEach(function (turn) {
            contentHtml += `
    <div class="turn ${turn.author}">
        <div class="author">${turn.author}</div>
        <div class="content">${turn.html}</div>
    </div>`;
        });

        contentHtml += `\n</body>\n</html>`;

        if (type === 'docx') {
            const blob = new Blob(['\ufeff' + contentHtml], { type: 'application/msword' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = rawTitle + '.doc';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        } else if (type === 'pdf') {
            const blob = new Blob([contentHtml], { type: 'text/html' });
            const url = URL.createObjectURL(blob);
            const printWin = window.open(url, '_blank');

            if (!printWin) {
                alert('Pop-up blocked! Please allow pop-ups for ChatGPT to render the printable tab.');
                return;
            }

            printWin.onload = function () {
                printWin.print();
            };
        }
    }

    setInterval(createUI, 1500);

})();


_______________________________________


pus acum 2 zile
   
Pagini: 1  

Mergi la