您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Export your ChatGPT conversations as clean Markdown files
- // ==UserScript==
- // @name ChatGPT Chat Exporter - Markdown
- // @namespace https://github.com/rashidazarang/chatgpt-chat-exporter
- // @version 1.0.0
- // @description Export your ChatGPT conversations as clean Markdown files
- // @author Rashid Azarang
- // @match https://chat.openai.com/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=openai.com
- // @grant none
- // @license MIT
- // @homepageURL https://github.com/rashidazarang/chatgpt-chat-exporter
- // @supportURL https://github.com/rashidazarang/chatgpt-chat-exporter/issues
- // ==/UserScript==
- (function() {
- 'use strict';
- // Add a button to the ChatGPT interface
- function addExportButton() {
- // Check if our button already exists
- if (document.getElementById('export-markdown-button')) return;
- // Find a suitable location to add the button
- const targetElement = document.querySelector('nav');
- if (!targetElement) return;
- // Create the button
- const button = document.createElement('button');
- button.id = 'export-markdown-button';
- button.innerHTML = 'Export as Markdown';
- button.style.cssText = `
- margin: 10px;
- padding: 10px;
- border-radius: 5px;
- background-color: #10a37f;
- color: white;
- border: none;
- cursor: pointer;
- font-size: 14px;
- width: calc(100% - 20px);
- `;
- // Add click event listener
- button.addEventListener('click', exportMarkdown);
- // Add button to the page
- targetElement.appendChild(button);
- }
- function formatDate(date = new Date()) {
- return date.toISOString().split('T')[0];
- }
- function escapeMarkdown(text) {
- return text
- .replace(/\\/g, '\\\\')
- .replace(/\*/g, '\\*')
- .replace(/_/g, '\\_')
- .replace(/`/g, '\\`')
- .replace(/\n{3,}/g, '\n\n');
- }
- function processMessageContent(element) {
- const clone = element.cloneNode(true);
- // Replace <pre><code> blocks
- clone.querySelectorAll('pre').forEach(pre => {
- const code = pre.innerText.trim();
- const langMatch = pre.querySelector('code')?.className?.match(/language-([a-zA-Z0-9]+)/);
- const lang = langMatch ? langMatch[1] : '';
- pre.replaceWith(`\n\n\`\`\`${lang}\n${code}\n\`\`\`\n`);
- });
- // Replace images and canvas with placeholders
- clone.querySelectorAll('img, canvas').forEach(el => {
- el.replaceWith('[Image or Canvas]');
- });
- // Convert remaining HTML to plain markdown-style text
- return escapeMarkdown(clone.innerText.trim());
- }
- function exportMarkdown() {
- const messages = document.querySelectorAll('div[class*="group"]');
- const lines = [];
- const title = 'Conversation with ChatGPT';
- const date = formatDate();
- const url = window.location.href;
- lines.push(`# ${title}\n`);
- lines.push(`**Date:** ${date}`);
- lines.push(`**Source:** [chat.openai.com](${url})\n`);
- lines.push(`---\n`);
- messages.forEach(group => {
- const isUser = !!group.querySelector('img');
- const sender = isUser ? 'You' : 'ChatGPT';
- const block = group.querySelector('.markdown, .prose, .whitespace-pre-wrap');
- if (block) {
- const content = processMessageContent(block);
- if (content) {
- lines.push(`### **${sender}**\n`);
- lines.push(content);
- lines.push('\n---\n');
- }
- }
- });
- const markdown = lines.join('\n').trim();
- const blob = new Blob([markdown], { type: 'text/markdown' });
- const a = document.createElement('a');
- a.download = `ChatGPT_Conversation_${date}.md`;
- a.href = URL.createObjectURL(blob);
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- }
- // Add the export button when the DOM is fully loaded
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', addExportButton);
- } else {
- addExportButton();
- }
- // Check periodically if the button needs to be added (for SPAs like ChatGPT)
- setInterval(addExportButton, 3000);
- })();