CodeDown

为 ChatGPT、Z.Ai、Gemini、LMArena、Kimi、Le Chat、Meta AI、Copilot、Grok 和 LongCat 的代码块添加下载按钮,以便下载格式正确、可直接使用的文件

安装此脚本
作者推荐脚本

您可能也喜欢我的提示

安装此脚本
// ==UserScript==
// @name               	CodeDown
// @name:pt-BR         	CodeDown
// @name:zh-CN         	CodeDown
// @name:zh-TW			CodeDown
// @name:es            	CodeDown
// @name:en            	CodeDown
// @name:ja				CodeDown
// @name:ko				CodeDown
// @name:de				CodeDown
// @name:fr				CodeDown
// @name:ru				CodeDown
// @namespace          	https://github.com/0H4S
// @version            	1.3
// @description 		Adds download buttons to code blocks on ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok, and LongCat, downloading the file in the correct, ready-to-use format
// @description:pt-BR 	Adiciona botões de download em blocos de código do ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok e LongCat, baixando o arquivo no formato correto pronto para uso
// @description:zh-CN 	为 ChatGPT、Z.Ai、Gemini、LMArena、Kimi、Le Chat、Meta AI、Copilot、Grok 和 LongCat 的代码块添加下载按钮,以便下载格式正确、可直接使用的文件
// @description:zh-TW 	為 ChatGPT、Z.Ai、Gemini、LMArena、Kimi、Le Chat、Meta AI、Copilot、Grok 和 LongCat 的程式碼區塊新增下載按鈕,可下載為格式正確且立即可用的檔案
// @description:en 		Adds download buttons to code blocks on ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok, and LongCat, downloading the file in the correct, ready-to-use format
// @description:es 		Añade botones de descarga en los bloques de código de ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok y LongCat, descargando el archivo en el formato correcto y listo para usar
// @description:ja 		ChatGPT、Z.Ai、Gemini、LMArena、Kimi、Le Chat、Meta AI、Copilot、Grok、LongCatのコードブロックにダウンロードボタンを追加し、すぐに使用できる正しい形式でファイルをダウンロードします
// @description:ko 		ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok, LongCat의 코드 블록에 다운로드 버튼을 추가하여, 바로 사용할 수 있도록 올바른 형식의 파일로 다운로드합니다
// @description:de 		Fügt Download-Schaltflächen zu Code-Blöcken auf ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok und LongCat hinzu, um die Datei im korrekten, sofort einsatzbereiten Format herunterzuladen
// @description:fr 		Ajoute des boutons de téléchargement aux blocs de code sur ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok et LongCat, pour télécharger le fichier dans le format correct, prêt à l'emploi
// @description:ru 		Добавляет кнопки загрузки в блоки кода на ChatGPT, Z.Ai, Gemini, LMArena, Kimi, Le Chat, Meta AI, Copilot, Grok и LongCat, позволяя скачать файл в правильном, готовом к использованию формате
// @author             	OHAS
// @license            	CC-BY-NC-ND-4.0
// @copyright          	2025 OHAS. All Rights Reserved.
// @icon               	https://cdn-icons-png.flaticon.com/512/8832/8832243.png
// @require            	https://update.greasyfork.org/scripts/549920.js
// @match              	https://copilot.microsoft.com/*
// @match              	https://gemini.google.com/*
// @match              	https://chat.mistral.ai/*
// @match              	https://longcat.chat/*
// @match              	https://www.kimi.com/*
// @match              	https://www.meta.ai/*
// @match              	https://chatgpt.com/*
// @match              	https://lmarena.ai/*
// @match              	https://chat.z.ai/*
// @match              	https://grok.com/*
// @connect            	gist.github.com
// @grant              	GM_registerMenuCommand
// @grant              	GM_xmlhttpRequest
// @grant              	GM_getValue
// @grant              	GM_setValue
// @grant              	GM_addStyle
// @noframes
// @compatible         	chrome
// @compatible         	firefox
// @compatible         	edge
// @compatible         	opera
// @bgf-compatible      brave
// @bgf-colorLT         #02bc7d
// @bgf-colorDT         #02bc7d
// @bgf-copyright       [2025 OHAS. All Rights Reserved.](https://gist.github.com/0H4S/ae2fa82957a089576367e364cbf02438)
// @bgf-social          https://github.com/0H4S
// @contributionURL     https://linktr.ee/0H4S
// ==/UserScript==

(function() {
    'use strict';
	// #region GLOBAL
    const SCRIPT_CONFIG = {
        notificationsUrl: 'https://gist.github.com/0H4S/3945fb0c57d988bd8d41fc560c433b50',
        scriptVersion: '1.3',
    };
    const notifier = new ScriptNotifier(SCRIPT_CONFIG);
    notifier.run();
    const translations = {
        'pt-br': {
            download: 		'Baixar',
            downloadCode: 	'Baixar código'
        },
        'zh-cn': {
            download: 		'下载',
            downloadCode: 	'下载代码'
        },
        en: {
            download: 		'Download',
            downloadCode: 	'Download code'
        },
        es: {
            download: 		'Descargar',
            downloadCode: 	'Descargar código'
        },
        ja: {
            download: 		'ダウンロード',
            downloadCode: 	'コードをダウンロード'
		},
        ko: {
            download: 		'다운로드',
            downloadCode: 	'코드 다운로드'
		},
        de: {
            download: 		'Herunterladen',
            downloadCode: 	'Code herunterladen'
		},
        fr: {
            download: 		'Télécharger',
            downloadCode: 	'Télécharger le code'
		},
        ru: {
            download: 		'Скачать',
            downloadCode: 	'Скачать код'
		}
    };
    function getLanguage() {
        const lang = (navigator.language || navigator.userLanguage).toLowerCase().split('-')[0];
        switch (lang) {
            case 'pt': 	return 'pt-br';
			case 'zh': 	return 'zh-cn';
            case 'es': 	return 'es';
            case 'en': 	return 'en';
			case 'ja':	return 'ja';
			case 'ko':	return 'ko';
			case 'de':	return 'de';
			case 'fr':	return 'fr';
			case 'ru':	return 'ru';
            default: 	return 'en';
        }
    }
    const langKey = getLanguage();
    const i18n = translations[langKey];
	// #endregion
	// #region TIPO DO ARQUIVO
    const fileTypeExtensions = {
        javascript: 'js',
        typescript: 'ts',
        html: 		'html',
        css: 		'css',
        json: 		'json',
        python: 	'py',
        java: 		'java',
        c: 			'c',
        cpp: 		'cpp',
        'c++': 		'cpp',
        'c#': 		'cs',
        php: 		'php',
        ruby: 		'rb',
        go: 		'go',
        rust: 		'rs',
        swift: 		'swift',
        kotlin: 	'kt',
        scala: 		'scala',
        shell: 		'sh',
        bash: 		'sh',
        sql: 		'sql',
        markdown: 	'md',
        yaml: 		'yaml',
        xml: 		'xml',
        text: 		'txt',
        plain: 		'txt',
        txt: 		'txt'
    };
    function getMimeType(ext) {
        const mime = {
            js: 	'application/javascript',
            ts: 	'application/typescript',
            html: 	'text/html',
            css: 	'text/css',
            json: 	'application/json',
            py: 	'text/x-python',
            java: 	'text/x-java-source',
            c: 		'text/x-csrc',
            cpp: 	'text/x-c++src',
            cs: 	'text/x-csharp',
            php: 	'application/x-php',
            rb: 	'application/x-ruby',
            go: 	'text/x-go',
            rs: 	'text/x-rust',
            swift: 	'text/x-swift',
            kt: 	'text/x-kotlin',
            scala: 	'text/x-scala',
            sh: 	'application/x-sh',
            sql: 	'application/sql',
            md: 	'text/markdown',
            yaml: 	'application/x-yaml',
            xml: 	'application/xml',
            txt: 	'text/plain'
        };
        return mime[ext] || 'text/plain';
    }
	// #endregion
	// #region LOCALIZADOR
    const isGPT 	= /chatgpt\.com/.test			(location.hostname);
    const isZAI 	= /chat\.z\.ai/.test			(location.hostname);
    const isGemini 	= /gemini\.google\.com/.test	(location.hostname);
    const isLmArena = /lmarena\.ai/.test			(location.hostname);
    const isKimi 	= /kimi\.com/.test				(location.hostname);
    const isMistral = /chat\.mistral\.ai/.test		(location.hostname);
    const isMetaAI 	= /meta\.ai/.test				(location.hostname);
    const isCopilot = /copilot\.microsoft.com/.test	(location.hostname);
    const isGrok 	= /grok\.com/.test				(location.hostname);
    const isLongCat = /longcat\.chat/.test			(location.hostname);

    function createAndTriggerDownload(fileName, content, mimeType) {
        const blob = new Blob([content], {
            type: mimeType
        });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = fileName;
        document.body.appendChild(a);
        a.click();
        setTimeout(() => {
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        }, 100);
    }
	// #endregion
    // -----------------------
    // --- #region GPT ---
    // -----------------------
    if (isGPT) {
        function createDownloadButtonGPT(container) {
            if (container.querySelector('.download-button-gpt')) {
                return;
            }
            const btn = document.createElement('button');
            btn.className = 'flex gap-1 items-center select-none py-1 download-button-gpt';
            btn.setAttribute('aria-label', i18n.downloadCode);
            const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('width', '20');
            svg.setAttribute('height', '20');
            svg.setAttribute('viewBox', '0 0 20 20');
            svg.setAttribute('fill', 'currentColor');
            svg.classList.add('icon-sm');
            svg.innerHTML = '<path d="M14.707 7.293a1 1 0 0 0-1.414 0L11 9.586V3a1 1 0 1 0-2 0v6.586L6.707 7.293a1 1 0 0 0-1.414 1.414l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414zM3 12a1 1 0 0 1 1 1v3a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-3a1 1 0 1 1 2 0v3a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3v-3a1 1 0 0 1 1-1z"/>';
            btn.appendChild(svg);
            btn.appendChild(document.createTextNode(i18n.download));
            btn.addEventListener('click', downloadCodeGPT);
            container.insertBefore(btn, container.firstChild);
        }
        function downloadCodeGPT() {
            const block = this.closest('.contain-inline-size');
            if (!block) return;
            const typeEl = block.querySelector('.flex.items-center.text-token-text-secondary');
            const fileType = typeEl?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = block.querySelector('code');
            if (!codeEl) return;
            const fileName = `CodeDown-ChatGPT-${fileType}-${new Date().toISOString().replace(/[:.]/g,'-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.textContent, getMimeType(ext));
        }
        const checkGPT = () => document.querySelectorAll('.bg-token-bg-elevated-secondary.text-token-text-secondary.flex').forEach(createDownloadButtonGPT);
        setInterval(checkGPT, 1000);
        window.addEventListener('load', checkGPT);
    }
	// #endregion
    // -----------------------
    // --- #region Z AI ---
    // -----------------------
    if (isZAI) {
        function createDownloadButtonZAI(copyBtn) {
            const buttonContainer = copyBtn.parentElement;
            if (!buttonContainer || buttonContainer.querySelector('.download-button-zai')) {
                return;
            }
            const btn = document.createElement('button');
            btn.className = `${copyBtn.className} download-button-zai`;
            btn.setAttribute('aria-label', i18n.downloadCode);
            const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('width', '20');
            svg.setAttribute('height', '20');
            svg.setAttribute('viewBox', '0 0 20 20');
            svg.setAttribute('fill', 'currentColor');
            svg.classList.add('size-3');
            svg.innerHTML = '<path d="M14.707 7.293a1 1 0 0 0-1.414 0L11 9.586V3a1 1 0 1 0-2 0v6.586L6.707 7.293a1 1 0 0 0-1.414 1.414l4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414zM3 12a1 1 0 0 1 1 1v3a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-3a1 1 0 1 1 2 0v3a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3v-3a1 1 0 0 1 1-1z"/>';
            btn.appendChild(svg);
            btn.appendChild(document.createTextNode(i18n.download));
            btn.addEventListener('click', downloadCodeZAI);
            buttonContainer.insertBefore(btn, copyBtn);
        }
        function downloadCodeZAI() {
            const root = this.closest('.relative');
            if (!root) return;
            const contentEl = root.querySelector('.cm-content[data-language]');
            if (!contentEl) return;
            const lang = (contentEl.getAttribute('data-language') || 'txt').toLowerCase();
            const ext = fileTypeExtensions[lang] || 'txt';
            const text = Array.from(contentEl.querySelectorAll('.cm-line')).map(div => div.innerText.replace(/\u00a0/g, ' ')).join('\n');
            const fileName = `CodeDown-Z.ai-${lang}-${new Date().toISOString().replace(/[:.]/g,'-')}.${ext}`;
            createAndTriggerDownload(fileName, text, getMimeType(ext));
        }
        const checkZAI = () => {
            document.querySelectorAll('button svg path[d^="M853.333333 298.666667"]').forEach(path => {
                const copyBtn = path.closest('button');
                if (copyBtn) createDownloadButtonZAI(copyBtn);
            });
        };
        setInterval(checkZAI, 1000);
        window.addEventListener('load', checkZAI);
    }
	// #endregion
    // -----------------------
    // --- #region Gemini ---
    // -----------------------
    if (isGemini) {
        GM_addStyle(`#codedown-gemini-tooltip { position: fixed; background: white; color: black; padding: 6px 10px; border-radius: 6px; font-size: 13px; font-family: sans-serif; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.2s, visibility 0.2s; z-index: 2147483647; box-shadow: 0 2px 5px rgba(0,0,0,0.2); }`);
        let tooltip = document.createElement('div');
        tooltip.id = 'codedown-gemini-tooltip';
        document.body.appendChild(tooltip);
        function createDownloadButtonGemini(copyBtn) {
            if (copyBtn.parentElement.querySelector('.download-button-gemini')) return;
            const btn = document.createElement('button');
            btn.className = copyBtn.className + ' download-button-gemini';
            btn.setAttribute('aria-label', i18n.downloadCode);
            const matIcon = document.createElement('mat-icon');
            matIcon.className = copyBtn.querySelector('mat-icon').className;
            matIcon.setAttribute('role', 'img');
            matIcon.setAttribute('aria-hidden', 'true');
            matIcon.textContent = 'download';
            btn.appendChild(matIcon);
            btn.addEventListener('click', downloadCodeGemini);
            btn.addEventListener('mouseover', (e) => {
                const rect = e.currentTarget.getBoundingClientRect();
                tooltip.textContent = i18n.downloadCode;
                tooltip.style.opacity = '1';
                tooltip.style.visibility = 'visible';
                tooltip.style.top = `${rect.bottom + 8}px`;
                tooltip.style.left = `${rect.left + rect.width / 2 - tooltip.offsetWidth / 2}px`;
            });
            btn.addEventListener('mouseout', () => {
                tooltip.style.opacity = '0';
                tooltip.style.visibility = 'hidden';
            });
            copyBtn.parentElement.insertBefore(btn, copyBtn);
        }
        function downloadCodeGemini(event) {
            const header = event.currentTarget.closest('.buttons').parentElement;
            const spanType = header.querySelector('span');
            const fileType = spanType?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = event.currentTarget.closest('code-block').querySelector('code[data-test-id="code-content"]');
            if (!codeEl) return;
            const fileName = `CodeDown-Gemini-${fileType}-${new Date().toISOString().replace(/[:.]/g,'-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.innerText, getMimeType(ext));
        }
        const checkGemini = () => document.querySelectorAll('button.copy-button').forEach(createDownloadButtonGemini);
        setInterval(checkGemini, 1000);
        window.addEventListener('load', checkGemini);
    }
	// #endregion
    // -----------------------
    // --- #region LMArena ---
    // -----------------------
    if (isLmArena) {
        GM_addStyle(`.download-button-lmarena { position: relative; } .download-button-lmarena::before { content: attr(data-tooltip); position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 8px; background-color: white; color: black; padding: 5px 9px; border-radius: 5px; font-size: 13px; white-space: nowrap; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.2s, visibility 0.2s; z-index: 2147483647; box-shadow: 0 2px 5px rgba(0,0,0,0.2); } .download-button-lmarena:hover::before { opacity: 1; visibility: visible; }`);
        function createDownloadButtonLmArena(copyBtn) {
            if (copyBtn.parentElement.classList.contains('code-down-buttons-wrapper')) return;
            const wrapper = document.createElement('div');
            wrapper.className = 'flex items-center gap-2 code-down-buttons-wrapper';
            const btn = document.createElement('button');
            btn.className = copyBtn.className + ' download-button-lmarena';
            btn.setAttribute('aria-label', i18n.downloadCode);
            btn.setAttribute('type', 'button');
            btn.setAttribute('data-tooltip', i18n.downloadCode);
            const downloadSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            downloadSvg.setAttribute('width', '16');
            downloadSvg.setAttribute('height', '16');
            downloadSvg.setAttribute('viewBox', '0 0 24 24');
            downloadSvg.setAttribute('fill', 'none');
            downloadSvg.setAttribute('stroke', 'currentColor');
            downloadSvg.setAttribute('stroke-width', '2');
            downloadSvg.setAttribute('stroke-linecap', 'round');
            downloadSvg.setAttribute('stroke-linejoin', 'round');
            downloadSvg.innerHTML = '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line>';
            btn.appendChild(downloadSvg);
            btn.addEventListener('click', downloadCodeLmArena);
            copyBtn.parentElement.insertBefore(wrapper, copyBtn);
            wrapper.appendChild(btn);
            wrapper.appendChild(copyBtn);
        }
        function downloadCodeLmArena(event) {
            event.stopPropagation();
            const container = this.closest('[data-sentry-component="CodeBlock"]');
            if (!container) return;
            const langEl = container.querySelector('[data-sentry-component="CodeBlockGroup"] span');
            const fileType = langEl?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = container.querySelector('[data-sentry-element="CodeBlockCode"] code');
            if (!codeEl) return;
            const fileName = `CodeDown-LMArena-${fileType}-${new Date().toISOString().replace(/[:.]/g,'-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.innerText, getMimeType(ext));
        }
        const checkLmArena = () => document.querySelectorAll('[data-sentry-component="CodeBlock"] button[data-sentry-component="CopyButton"]').forEach(createDownloadButtonLmArena);
        setInterval(checkLmArena, 1000);
        window.addEventListener('load', checkLmArena);
    }
	// #endregion
    // -----------------------
    // --- #region Kimi ---
    // -----------------------
    if (isKimi) {
        function createDownloadButtonKimi(copyBtn) {
            const headerContent = copyBtn.parentElement;
            if (!headerContent || headerContent.querySelector('.download-button-kimi')) return;
            const btn = copyBtn.cloneNode(true);
            btn.classList.add('download-button-kimi');
            btn.querySelector('span').textContent = i18n.download;
            const svg = btn.querySelector('svg');
            svg.setAttribute('viewBox', '0 0 24 24');
            svg.innerHTML = '<path d="M5 20h14v-2H5v2zm14-9h-4V3H9v8H5l7 7l7-7z" fill="currentColor"></path>';
            btn.addEventListener('click', downloadCodeKimi);
            if (!copyBtn.parentElement.classList.contains('codedown-wrapper')) {
                const wrapper = document.createElement('div');
                wrapper.className = 'codedown-wrapper';
                wrapper.style.display = 'flex';
                wrapper.style.gap = '8px';
                headerContent.replaceChild(wrapper, copyBtn);
                wrapper.appendChild(btn);
                wrapper.appendChild(copyBtn);
            }
        }
        function downloadCodeKimi() {
            const codeBlock = this.closest('.segment-code');
            if (!codeBlock) return;
            const langEl = codeBlock.querySelector('.segment-code-lang');
            const fileType = langEl?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = codeBlock.querySelector('code');
            if (!codeEl) return;
            const fileName = `CodeDown-Kimi-${fileType}-${new Date().toISOString().replace(/[:.]/g,'-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.innerText, getMimeType(ext));
        }
        const checkKimi = () => document.querySelectorAll('.segment-code-header-content .simple-button').forEach(createDownloadButtonKimi);
        setInterval(checkKimi, 1000);
        window.addEventListener('load', checkKimi);
    }
	// #endregion
    // -----------------------
    // --- #region Mistral ---
    // -----------------------
    if (isMistral) {
        function createDownloadButtonMistral(copyBtn) {
            const parent = copyBtn.parentElement;
            if (parent.querySelector('.download-button-mistral')) {
                return;
            }
            const btn = document.createElement('button');
            btn.className = copyBtn.className + ' download-button-mistral';
            btn.setAttribute('type', 'button');
            btn.setAttribute('aria-label', i18n.downloadCode);
            const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            for (const attr of copyBtn.querySelector('svg').attributes) {
                svg.setAttribute(attr.name, attr.value);
            }
            svg.innerHTML = '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line>';
            btn.appendChild(svg);
            btn.appendChild(document.createTextNode(i18n.download));
            btn.addEventListener('click', downloadCodeMistral);
            parent.insertBefore(btn, copyBtn);
        }
        function downloadCodeMistral() {
            const container = this.closest('.relative.rounded-md');
            if (!container) return;
            const codeEl = container.querySelector('code[class*="language-"]');
            if (!codeEl) return;
            const langMatch = Array.from(codeEl.classList).find(c => c.startsWith('language-'));
            const fileType = langMatch ? langMatch.replace('language-', '').toLowerCase() : 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const fileName = `CodeDown-LeChat-${fileType}-${new Date().toISOString().replace(/[:.]/g,'-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.innerText, getMimeType(ext));
        }
        const checkMistral = () => {
            document.querySelectorAll('div[data-exclude-copy="true"] button svg.lucide-copy').forEach(svgEl => {
                const copyBtn = svgEl.closest('button');
                if (copyBtn) {
                    createDownloadButtonMistral(copyBtn);
                }
            });
        };
        setInterval(checkMistral, 1000);
        window.addEventListener('load', checkMistral);
    }
	// #endregion
    // -----------------------
    // --- #region Meta AI ---
    // -----------------------
    if (isMetaAI) {
        function createDownloadButtonMetaAI(copyBtn) {
            const parent = copyBtn.parentElement;
            if (!parent || parent.querySelector('.download-button-meta')) {
                return;
            }
            const btn = copyBtn.cloneNode(true);
            btn.classList.add('download-button-meta');
            btn.setAttribute('aria-label', i18n.download);
            btn.removeAttribute('data-tooltip-content');
            const svg = btn.querySelector('svg');
            if (svg) {
                svg.innerHTML = '<path fill-rule="evenodd" clip-rule="evenodd" d="M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z"></path>';
            }
            btn.addEventListener('click', downloadCodeMetaAI);
            parent.insertBefore(btn, copyBtn);
        }
        function downloadCodeMetaAI(event) {
            event.stopPropagation();
            const container = this.closest('.x78zum5.xdt5ytf.xfe5zq5');
            if (!container) return;
            const langEl = container.querySelector('div[class*="x6s0dn4"] > span');
            const fileType = langEl?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = container.querySelector('pre > code');
            if (!codeEl) return;
            const fileName = `CodeDown-Meta-${fileType}-${new Date().toISOString().replace(/[:.]/g, '-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.innerText, getMimeType(ext));
        }
        const checkMetaAI = () => {
            const svgPathSelector = 'M5 14h1v2H5a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h8a3 3 0 0 1 3 3v1h-2V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1zm14 6h-8a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1zm3-1a3 3 0 0 1-3 3h-8a3 3 0 0 1-3-3v-8a3 3 0 0 1 3-3h8a3 3 0 0 1 3 3v8z';
            document.querySelectorAll(`svg path[d="${svgPathSelector}"]`).forEach(pathEl => {
                const copyBtn = pathEl.closest('div[role="button"]');
                if (copyBtn) {
                    const container = copyBtn.closest('.x78zum5.xdt5ytf.xfe5zq5');
                    if (container && container.querySelector('pre > code')) {
                        createDownloadButtonMetaAI(copyBtn);
                    }
                }
            });
        };
        setInterval(checkMetaAI, 1000);
        window.addEventListener('load', checkMetaAI);
    }
	// #endregion
    // -----------------------
    // --- #region Copilot ---
    // -----------------------
    if (isCopilot) {
        function createDownloadButtonCopilot(copyBtn) {
            const parent = copyBtn.parentElement;
            if (parent.querySelector('.download-button-copilot')) {
                return;
            }
            const btn = copyBtn.cloneNode(true);
            btn.classList.add('download-button-copilot');
            btn.setAttribute('title', i18n.downloadCode);
            btn.removeAttribute('data-copy');
            const contentDiv = btn.querySelector('div');
            if (contentDiv) {
                contentDiv.innerHTML = `<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="w-5"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 19v-2h14v2H5z"></path></svg> ${i18n.download}`;
            }
            btn.addEventListener('click', downloadCodeCopilot);
            const wrapper = document.createElement('div');
            wrapper.className = 'flex items-center codedown-copilot-wrapper';
            wrapper.style.gap = '0.25rem';
            parent.insertBefore(wrapper, copyBtn);
            wrapper.appendChild(btn);
            wrapper.appendChild(copyBtn);
        }
        function downloadCodeCopilot(event) {
            event.stopPropagation();
            const header = this.closest('.flex.justify-between.items-center');
            const container = header ? header.parentElement : null;
            if (!container) return;
            const langEl = container.querySelector('.capitalize');
            const fileType = langEl?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = container.querySelector('pre > code');
            if (!codeEl) return;
            const fileName = `CodeDown-Copilot-${fileType}-${new Date().toISOString().replace(/[:.]/g, '-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.innerText, getMimeType(ext));
        }
        const checkCopilot = () => {
            const svgPathSelector = 'M8.5 2C7.39543 2 6.5 2.89543 6.5 4V14C6.5 15.1046 7.39543 16 8.5 16H14.5C15.6046 16 16.5 15.1046 16.5 14V4C16.5 2.89543 15.6046 2 14.5 2H8.5ZM7.5 4C7.5 3.44772 7.94772 3 8.5 3H14.5C15.0523 3 15.5 3.44772 15.5 4V14C15.5 14.5523 15.0523 15 14.5 15H8.5C7.94772 15 7.5 14.5523 7.5 14V4ZM4.5 6.00001C4.5 5.25973 4.9022 4.61339 5.5 4.26758V14.5C5.5 15.8807 6.61929 17 8 17H14.2324C13.8866 17.5978 13.2403 18 12.5 18H8C6.067 18 4.5 16.433 4.5 14.5V6.00001Z';
            document.querySelectorAll(`button svg mask path[d="${svgPathSelector}"]`).forEach(pathEl => {
                const copyBtn = pathEl.closest('button');
                if (copyBtn && !copyBtn.parentElement.classList.contains('codedown-copilot-wrapper')) {
                    createDownloadButtonCopilot(copyBtn);
                }
            });
        };
        setInterval(checkCopilot, 1000);
        window.addEventListener('load', checkCopilot);
    }
	// #endregion
    // -----------------------
    // --- #region Grok ---
    // -----------------------
    if (isGrok) {
        function createDownloadButtonGrok(collapseBtn) {
            const parent = collapseBtn.parentElement;
            if (parent.querySelector('.download-button-grok')) return;
            const btn = collapseBtn.cloneNode(true);
            btn.classList.add('download-button-grok');
            btn.setAttribute('aria-label', i18n.downloadCode);
            const svg = btn.querySelector('svg');
            if (svg) {
                svg.innerHTML = '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line>';
                svg.setAttribute('viewBox', '0 0 24 24');
            }
            const span = btn.querySelector('span');
            if (span) {
                span.textContent = i18n.download;
            }
            btn.addEventListener('click', downloadCodeGrok);
            parent.insertBefore(btn, collapseBtn);
        }
        function downloadCodeGrok(event) {
            event.stopPropagation();
            const container = this.closest('.relative.not-prose');
            if (!container) return;
            const langEl = container.querySelector('.flex.flex-row.px-4 span');
            const fileType = langEl?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = container.querySelector('pre.shiki > code');
            if (!codeEl) return;
            const codeText = Array.from(codeEl.querySelectorAll('.line'))
                                .map(line => line.textContent)
                                .join('\n');
            const fileName = `CodeDown-Grok-${fileType}-${new Date().toISOString().replace(/[:.]/g, '-')}.${ext}`;
            createAndTriggerDownload(fileName, codeText, getMimeType(ext));
        }
        const checkGrok = () => {
            document.querySelectorAll('button svg.lucide-chevrons-down-up').forEach(svgEl => {
                const collapseBtn = svgEl.closest('button');
                if (collapseBtn) {
                    createDownloadButtonGrok(collapseBtn);
                }
            });
        };
        setInterval(checkGrok, 1000);
        window.addEventListener('load', checkGrok);
    }
	// #endregion
    // -----------------------
    // --- #region LongCat ---
    // -----------------------
    if (isLongCat) {
        function createDownloadButtonLongCat(copyBtn) {
            if (copyBtn.parentElement.classList.contains('codedown-longcat-wrapper')) {
                return;
            }
            const header = copyBtn.parentElement;
            if (header.querySelector('.download-button-longcat')) {
                return;
            }
            const btn = document.createElement('div');
            btn.className = copyBtn.className + ' download-button-longcat';
            btn.setAttribute('aria-label', i18n.downloadCode);
            btn.style.display = 'flex';
            btn.style.alignItems = 'center';
            btn.style.gap = '5px';
            const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('width', '16');
            svg.setAttribute('height', '16');
            svg.setAttribute('viewBox', '0 0 24 24');
            svg.setAttribute('fill', 'none');
            svg.setAttribute('stroke', 'currentColor');
            svg.setAttribute('stroke-width', '2');
            svg.setAttribute('stroke-linecap', 'round');
            svg.setAttribute('stroke-linejoin', 'round');
            svg.innerHTML = '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line>';
            const span = document.createElement('span');
            span.className = 'code-block-header__text code-block-header__click';
            span.textContent = i18n.download;
            btn.appendChild(svg);
            btn.appendChild(span);
            btn.addEventListener('click', downloadCodeLongCat);
            const wrapper = document.createElement('div');
            wrapper.className = 'codedown-longcat-wrapper';
            wrapper.style.display = 'flex';
            wrapper.style.alignItems = 'center';
            wrapper.style.gap = '12px';
            header.insertBefore(wrapper, copyBtn);
            wrapper.appendChild(btn);
            wrapper.appendChild(copyBtn);
        }
        function downloadCodeLongCat(event) {
            event.stopPropagation();
            const header = this.closest('.code-block-header');
            if (!header) return;
            const codeBlockContainer = header.parentElement;
            if (!codeBlockContainer) return;
            const langEl = header.querySelector('.code-block-header__lang');
            const fileType = langEl?.textContent.trim().toLowerCase() || 'txt';
            const ext = fileTypeExtensions[fileType] || 'txt';
            const codeEl = codeBlockContainer.querySelector('code.code-block-body');
            if (!codeEl) return;
            const fileName = `CodeDown-LongCat-${fileType}-${new Date().toISOString().replace(/[:.]/g, '-')}.${ext}`;
            createAndTriggerDownload(fileName, codeEl.innerText, getMimeType(ext));
        }
        const checkLongCat = () => {
            document.querySelectorAll('.code-block-header__copy').forEach(createDownloadButtonLongCat);
        };
        setInterval(checkLongCat, 1000);
        window.addEventListener('load', checkLongCat);
    }
	// #endregion
})();