Grok Code Style with Collapse

Shrink, collapse, compact, and download pre/code blocks on Grok pages with manual language switch (fixed selector error)

Устаревшая версия за 15.03.2025. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Grok Code Style with Collapse
// @namespace    http://tampermonkey.net/
// @version      2.2
// @description  Shrink, collapse, compact, and download pre/code blocks on Grok pages with manual language switch (fixed selector error)
// @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
// ==/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 (fixed selector)
    function wrapCodeBlocks() {
        // Simplified selector to avoid nested :not syntax error
        const codeBlocks = document.querySelectorAll('pre:not([class*="highlight"]):not([id*="highlight"]), code:not([class*="highlight"]):not([id*="highlight"])');
        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);
})();