// ==UserScript== // @name Grok Code Style with Collapse // @namespace http://tampermonkey.net/ // @version 2.1 // @description Shrink, collapse, compact, and download pre/code blocks on Grok pages with manual language switch // @author You // @match https://x.com/i/grok* // @match https://grok.com/* // @match https://grok.x.ai/* // @match https://x.ai/* // @exclude https://greasyfork.org/* // @exclude https://*.org/* // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // Language options const translations = { 'en': { expand: 'Expand', collapse: 'Collapse', download: 'Download' }, // English (default) 'zh-TW': { expand: '展開', collapse: '收起', download: '下載' }, // Traditional Chinese 'zh-CN': { expand: '展开', collapse: '收起', download: '下载' }, // Simplified Chinese 'ja': { expand: '展開', collapse: '折り畳む', download: 'ダウンロード' }, // Japanese 'ko': { expand: '펼치기', collapse: '접기', download: '다운로드' }, // Korean 'fr': { expand: 'Développer', collapse: 'Réduire', download: 'Télécharger' }, // French 'es': { expand: 'Expandir', collapse: 'Colapsar', download: 'Descargar' } // Spanish }; // Load saved language or default to 'en' let currentLang = GM_getValue('selectedLang', 'en'); let lang = translations[currentLang]; // Register language switch menu in Tampermonkey for (let langCode in translations) { GM_registerMenuCommand(`Switch to ${langCode.toUpperCase()}`, () => { currentLang = langCode; GM_setValue('selectedLang', langCode); lang = translations[langCode]; wrapCodeBlocks(); // Reapply with new language }); } // Add styles (from 1.5) GM_addStyle(` .grok-code-wrapper { position: relative; margin: 0; } .grok-code-wrapper pre, .grok-code-wrapper code { max-height: 100px; overflow-y: hidden; font-size: 10px; line-height: 1.1; background-color: #f5f5f5; padding: 3px; border: 1px solid #ddd; display: block; transition: max-height 0.3s ease; } .grok-code-wrapper.expanded pre, .grok-code-wrapper.expanded code { max-height: 300px; overflow-y: auto; } .grok-toggle-btn { position: absolute; top: 2px; right: 2px; font-size: 10px; padding: 1px 4px; cursor: pointer; background: #ddd; border: none; border-radius: 2px; } .grok-download-btn { position: absolute; top: 2px; right: 40px; font-size: 9px; padding: 1px 4px; cursor: pointer; background: #4CAF50; color: white; border: none; border-radius: 2px; } .grok-download-btn:hover { background: #45a049; } `); // Process code blocks (from 1.5) function wrapCodeBlocks() { const codeBlocks = document.querySelectorAll(':not([class*="highlight"]:not([id*="highlight"])) > pre, :not([class*="highlight"]:not[id*="highlight"])) > code'); codeBlocks.forEach((block, index) => { const parent = block.parentElement; if (!parent.classList.contains('grok-code-wrapper')) { const wrapper = document.createElement('div'); wrapper.className = 'grok-code-wrapper'; parent.insertBefore(wrapper, block); wrapper.appendChild(block); const toggleBtn = document.createElement('button'); toggleBtn.className = 'grok-toggle-btn'; toggleBtn.textContent = lang.expand; wrapper.appendChild(toggleBtn); const downloadBtn = document.createElement('button'); downloadBtn.className = 'grok-download-btn'; downloadBtn.textContent = lang.download; wrapper.appendChild(downloadBtn); toggleBtn.addEventListener('click', () => { wrapper.classList.toggle('expanded'); toggleBtn.textContent = wrapper.classList.contains('expanded') ? lang.collapse : lang.expand; }); downloadBtn.addEventListener('click', () => { const blob = new Blob([block.textContent], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `code_block_${index + 1}.txt`; a.click(); URL.revokeObjectURL(url); }); } else { // Update existing buttons with new language const toggleBtn = parent.querySelector('.grok-toggle-btn'); if (toggleBtn) { toggleBtn.textContent = parent.classList.contains('expanded') ? lang.collapse : lang.expand; } const downloadBtn = parent.querySelector('.grok-download-btn'); if (downloadBtn) { downloadBtn.textContent = lang.download; } } }); } // Periodic check (from 1.5) wrapCodeBlocks(); setInterval(wrapCodeBlocks, 2000); })();