您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
导出MiniMax网站上的对话为Markdown格式,思考过程使用引用格式
// ==UserScript== // @name MiniMax对话Markdown导出 // @name:en MiniMax to Markdown Exporter // @version 1.2 // @description 导出MiniMax网站上的对话为Markdown格式,思考过程使用引用格式 // @description:en Export chat history from MiniMax website to Markdown format with thinking process in quote format // @author dennischancs // @license MIT // @match https://chat.minimax.io/* // @match https://*.minimax.io/* // @grant none // @namespace https://greasyfork.org/users/1486487-dennischancs // ==/UserScript== (function() { 'use strict'; // 获取对话元素 function getConversationElements() { return document.querySelectorAll('.chat-card-item-wrapper'); } // 提取用户消息 function extractUserMessage(element) { const userCard = element.querySelector('.user-card-wrapper'); if (userCard) { const contentDiv = userCard.querySelector('[id^="content-"]'); return contentDiv ? contentDiv.textContent.trim() : ''; } return ''; } // 提取系统消息和思考过程 function extractSystemMessage(element, removeThinking = true) { const systemCard = element.querySelector('.system-card-wrapper'); if (systemCard) { const contentDiv = systemCard.querySelector('[id^="content-"]'); if (contentDiv) { // 克隆元素以避免修改原始DOM const clonedContent = contentDiv.cloneNode(true); let thinkingContent = ''; let mainContent = ''; // 提取思考过程部分 const thinkingProcess = clonedContent.querySelector('.mb-3'); if (thinkingProcess) { thinkingContent = thinkingProcess.textContent.trim(); thinkingProcess.remove(); } // 提取主要回答内容 mainContent = clonedContent.textContent.trim(); if (removeThinking) { return mainContent; } else { // 将思考过程格式化为引用格式 let result = ''; if (thinkingContent) { const thinkingLines = thinkingContent.split('\n'); const quotedThinking = thinkingLines.map(line => line.trim() ? `> ${line.trim()}` : '>' ).join('\n'); result += quotedThinking + '\n\n'; } result += mainContent; return result; } } } return ''; } // 转换HTML为Markdown function htmlToMarkdown(html) { if (!html) return ''; const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); // 处理数学公式 doc.querySelectorAll('span.katex-html').forEach(element => element.remove()); doc.querySelectorAll('mrow').forEach(mrow => mrow.remove()); doc.querySelectorAll('annotation[encoding="application/x-tex"]').forEach(element => { if (element.closest('.katex-display')) { const latex = element.textContent; element.replaceWith(`\n$$\n${latex}\n$$\n`); } else { const latex = element.textContent; element.replaceWith(`$${latex}$`); } }); // 粗体文本 doc.querySelectorAll('strong, b').forEach(bold => { bold.parentNode.replaceChild(document.createTextNode(`**${bold.textContent}**`), bold); }); // 斜体文本 doc.querySelectorAll('em, i').forEach(italic => { italic.parentNode.replaceChild(document.createTextNode(`*${italic.textContent}*`), italic); }); // 行内代码 doc.querySelectorAll('p code').forEach(code => { code.parentNode.replaceChild(document.createTextNode(`\`${code.textContent}\``), code); }); // 链接 doc.querySelectorAll('a').forEach(link => { link.parentNode.replaceChild(document.createTextNode(`[${link.textContent}](${link.href})`), link); }); // 图片 doc.querySelectorAll('img').forEach(img => { img.parentNode.replaceChild(document.createTextNode(``), img); }); // 代码块 doc.querySelectorAll('pre').forEach(pre => { const codeType = pre.querySelector('div > div:first-child')?.textContent || ''; const markdownCode = pre.querySelector('code')?.textContent || pre.textContent; pre.innerHTML = `\n\`\`\`${codeType}\n${markdownCode}\n\`\`\`\n`; }); // 无序列表 doc.querySelectorAll('ul').forEach(ul => { let markdown = ''; ul.querySelectorAll(':scope > li').forEach(li => { markdown += `- ${li.textContent.trim()}\n`; }); ul.parentNode.replaceChild(document.createTextNode('\n' + markdown.trim()), ul); }); // 有序列表 doc.querySelectorAll('ol').forEach(ol => { let markdown = ''; ol.querySelectorAll(':scope > li').forEach((li, index) => { markdown += `${index + 1}. ${li.textContent.trim()}\n`; }); ol.parentNode.replaceChild(document.createTextNode('\n' + markdown.trim()), ol); }); // 标题 for (let i = 1; i <= 6; i++) { doc.querySelectorAll(`h${i}`).forEach(header => { header.parentNode.replaceChild(document.createTextNode('\n' + `${'#'.repeat(i)} ${header.textContent}\n`), header); }); } // 段落 doc.querySelectorAll('p').forEach(p => { p.parentNode.replaceChild(document.createTextNode('\n' + p.textContent + '\n'), p); }); // 表格 doc.querySelectorAll('table').forEach(table => { let markdown = ''; table.querySelectorAll('thead tr').forEach(tr => { tr.querySelectorAll('th').forEach(th => { markdown += `| ${th.textContent} `; }); markdown += '|\n'; tr.querySelectorAll('th').forEach(() => { markdown += '| ---- '; }); markdown += '|\n'; }); table.querySelectorAll('tbody tr').forEach(tr => { tr.querySelectorAll('td').forEach(td => { markdown += `| ${td.textContent} `; }); markdown += '|\n'; }); table.parentNode.replaceChild(document.createTextNode('\n' + markdown.trim() + '\n'), table); }); let markdown = doc.body.innerHTML.replace(/<[^>]*>/g, ''); markdown = markdown.replaceAll('>', '>') .replaceAll('<', '<') .replaceAll('&', '&') .replaceAll('≥', '>=') .replaceAll('≤', '<=') .replaceAll('≠', '\\neq'); return markdown.trim(); } // 下载文件 function download(data, filename, type) { const file = new Blob([data], { type: type }); const a = document.createElement('a'); const url = URL.createObjectURL(file); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 0); } // 生成Markdown内容 function generateMarkdown(removeThinking = true) { let markdownContent = ""; const conversationElements = getConversationElements(); conversationElements.forEach(element => { const userMessage = extractUserMessage(element); const systemMessage = extractSystemMessage(element, removeThinking); if (userMessage) { const userMarkdown = htmlToMarkdown(userMessage); markdownContent += `\n# User Question\n${userMarkdown}\n`; } if (systemMessage) { const systemMarkdown = htmlToMarkdown(systemMessage); markdownContent += `# MiniMax AI\n${systemMarkdown}\n`; } }); return markdownContent.trim(); } // 显示导出模态框 function showExportModal() { const conversationElements = getConversationElements(); if (conversationElements.length === 0) { alert("未找到对话内容。"); return; } // 创建模态框 const modal = document.createElement('div'); modal.id = 'minimax-markdown-modal'; Object.assign(modal.style, { position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: '10000' }); const modalContent = document.createElement('div'); Object.assign(modalContent.style, { backgroundColor: '#fff', color: '#000', padding: '20px', borderRadius: '8px', width: '60%', height: '80%', display: 'flex', flexDirection: 'column', boxShadow: '0 2px 10px rgba(0,0,0,0.1)', overflow: 'hidden' }); const title = document.createElement('h3'); title.textContent = 'MiniMax 对话导出'; title.style.marginTop = '0'; title.style.marginBottom = '15px'; title.style.color = '#333'; // 创建选项区域 const optionsContainer = document.createElement('div'); Object.assign(optionsContainer.style, { marginBottom: '15px', padding: '10px', backgroundColor: '#f5f5f5', borderRadius: '4px', border: '1px solid #ddd' }); const checkboxContainer = document.createElement('div'); Object.assign(checkboxContainer.style, { display: 'flex', alignItems: 'center', gap: '8px' }); const removeThinkingCheckbox = document.createElement('input'); removeThinkingCheckbox.type = 'checkbox'; removeThinkingCheckbox.id = 'remove-thinking-checkbox'; removeThinkingCheckbox.checked = false; // 默认不勾选 Object.assign(removeThinkingCheckbox.style, { margin: '0', cursor: 'pointer' }); const checkboxLabel = document.createElement('label'); checkboxLabel.textContent = '移除思考过程(取消勾选将以引用格式显示思考过程)'; checkboxLabel.setAttribute('for', 'remove-thinking-checkbox'); Object.assign(checkboxLabel.style, { cursor: 'pointer', fontSize: '14px', color: '#333' }); checkboxContainer.appendChild(removeThinkingCheckbox); checkboxContainer.appendChild(checkboxLabel); optionsContainer.appendChild(checkboxContainer); const textarea = document.createElement('textarea'); // 初始化内容 textarea.value = generateMarkdown(removeThinkingCheckbox.checked); Object.assign(textarea.style, { flex: '1', resize: 'none', width: '100%', padding: '10px', fontSize: '14px', fontFamily: 'monospace', marginBottom: '10px', boxSizing: 'border-box', color: '#000', backgroundColor: '#f9f9f9', border: '1px solid #ccc', borderRadius: '4px' }); textarea.setAttribute('readonly', true); // 监听复选框变化 removeThinkingCheckbox.addEventListener('change', () => { const newContent = generateMarkdown(removeThinkingCheckbox.checked); textarea.value = newContent; }); const buttonContainer = document.createElement('div'); Object.assign(buttonContainer.style, { display: 'flex', justifyContent: 'flex-end', gap: '10px' }); const copyButton = document.createElement('button'); copyButton.textContent = '复制'; Object.assign(copyButton.style, { padding: '8px 16px', fontSize: '14px', cursor: 'pointer', backgroundColor: '#28A745', color: '#fff', border: 'none', borderRadius: '4px' }); const downloadButton = document.createElement('button'); downloadButton.textContent = '下载'; Object.assign(downloadButton.style, { padding: '8px 16px', fontSize: '14px', cursor: 'pointer', backgroundColor: '#007BFF', color: '#fff', border: 'none', borderRadius: '4px' }); const closeButton = document.createElement('button'); closeButton.textContent = '关闭'; Object.assign(closeButton.style, { padding: '8px 16px', fontSize: '14px', cursor: 'pointer', backgroundColor: '#DC3545', color: '#fff', border: 'none', borderRadius: '4px' }); buttonContainer.appendChild(copyButton); buttonContainer.appendChild(downloadButton); buttonContainer.appendChild(closeButton); modalContent.appendChild(title); modalContent.appendChild(optionsContainer); modalContent.appendChild(textarea); modalContent.appendChild(buttonContainer); modal.appendChild(modalContent); document.body.appendChild(modal); // 按钮事件监听器 copyButton.addEventListener('click', () => { textarea.select(); navigator.clipboard.writeText(textarea.value) .then(() => { copyButton.textContent = '已复制'; setTimeout(() => copyButton.textContent = '复制', 2000); }) .catch(err => { console.error('复制失败', err); // 备用复制方法 try { document.execCommand('copy'); copyButton.textContent = '已复制'; setTimeout(() => copyButton.textContent = '复制', 2000); } catch (e) { alert('复制失败,请手动复制'); } }); }); downloadButton.addEventListener('click', () => { const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-'); const suffix = removeThinkingCheckbox.checked ? '' : '-with-thinking'; download(textarea.value, `minimax-chat-${timestamp}${suffix}.md`, 'text/markdown'); }); closeButton.addEventListener('click', () => { document.body.removeChild(modal); }); // ESC键和点击外部关闭模态框 const escListener = (e) => { if (e.key === 'Escape' && document.getElementById('minimax-markdown-modal')) { document.body.removeChild(modal); document.removeEventListener('keydown', escListener); } }; document.addEventListener('keydown', escListener); modal.addEventListener('click', (e) => { if (e.target === modal) { document.body.removeChild(modal); document.removeEventListener('keydown', escListener); } }); } // 创建导出按钮 function createExportButton() { // 移除已存在的按钮 const existingButton = document.getElementById('minimax-export-chat'); if (existingButton) { existingButton.remove(); } const exportButton = document.createElement('button'); exportButton.textContent = '导出对话'; exportButton.id = 'minimax-export-chat'; const styles = { position: 'fixed', top: '70px', right: '20px', zIndex: '9999', padding: '10px 15px', backgroundColor: '#4F46E5', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '14px', fontWeight: '500', boxShadow: '0 2px 10px rgba(79, 70, 229, 0.3)', transition: 'all 0.2s ease' }; Object.assign(exportButton.style, styles); // 鼠标悬停效果 exportButton.addEventListener('mouseenter', () => { exportButton.style.backgroundColor = '#4338CA'; exportButton.style.transform = 'translateY(-1px)'; }); exportButton.addEventListener('mouseleave', () => { exportButton.style.backgroundColor = '#4F46E5'; exportButton.style.transform = 'translateY(0)'; }); exportButton.addEventListener('click', showExportModal); document.body.appendChild(exportButton); } // 等待页面加载完成后初始化 function init() { // 等待对话内容加载 const checkContent = () => { const conversations = getConversationElements(); if (conversations.length > 0) { createExportButton(); } }; // 立即检查一次 checkContent(); // 定期检查并创建按钮(处理动态加载的内容) setInterval(() => { checkContent(); }, 2000); } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();