// ==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
})();