ChatGPT 代码导出按钮

为 ChatGPT 响应中的代码块添加导出按钮,提示用户根据代码块的类名检测到的编程语言将代码保存为文件。

  1. // ==UserScript==
  2. // @name ChatGPT Code Export Button
  3. // @name:en ChatGPT Code Export Button
  4. // @name:zh-CN ChatGPT 代码导出按钮
  5. // @name:es Botón de Exportación de Código de ChatGPT
  6. // @name:hi चैटजीपीटी कोड निर्यात बटन
  7. // @name:fr Bouton d'Exportation de Code ChatGPT
  8. // @name:ar زر تصدير الكود في ChatGPT
  9. // @name:bn চ্যাটজিপিটি কোড রপ্তানি বাটন
  10. // @name:ru Кнопка экспорта кода ChatGPT
  11. // @name:pt Botão de Exportação de Código do ChatGPT
  12. // @name:ur چیٹ جی پی ٹی کوڈ برآمد بٹن
  13. // @namespace http://tampermonkey.net/
  14. // @version 2024/10/05
  15. // @license MIT
  16. // @description Adds Export button to code blocks in ChatGPT responses, prompts user to save code as file with predefined filename based on coding language detected from the code block's class name.
  17. // @description:en Adds Export button to code blocks in ChatGPT responses, prompts user to save code as file with predefined filename based on coding language detected from the code block's class name.
  18. // @description:zh-CN 为 ChatGPT 响应中的代码块添加导出按钮,提示用户根据代码块的类名检测到的编程语言将代码保存为文件。
  19. // @description:es Agrega un botón de exportación a los bloques de código en las respuestas de ChatGPT, solicitando al usuario que guarde el código como archivo con un nombre predefinido según el lenguaje de programación detectado del nombre de la clase del bloque de código.
  20. // @description:hi चैटजीपीटी प्रतिक्रियाओं में कोड ब्लॉक्स में निर्यात बटन जोड़ता है, उपयोगकर्ता को कोड को फ़ाइल के रूप में सहेजने के लिए प्रीडिफ़ाइन्ड फ़ाइलनाम पर प्रोम्प्ट करता है जोड़ता है। कोड ब्लॉक के क्लास नाम से डिटेक्ट किया गया।
  21. // @description:fr Ajoute un bouton d'exportation aux blocs de code dans les réponses de ChatGPT, invite l'utilisateur à enregistrer le code sous forme de fichier avec un nom prédéfini basé sur le langage de programmation détecté à partir du nom de classe du bloc de code.
  22. // @description:ar يضيف زر التصدير إلى كتل الكود في ردود ChatGPT ، ويطلب من المستخدم حفظ الكود كملف باسم محدد مسبقًا بناءً على لغة البرمجة المكتشفة من اسم الفئة لكتلة الكود.
  23. // @description:bn ChatGPT রেসপন্সে কোড ব্লকের জন্য রপ্তানি বাটন যোগ করে, ব্যবহারকারীকে কোডটি ক্লাস নাম থেকে ডিটেক্ট করে পূর্বনির্ধারিত ফাইলনেমের মধ্যে সংরক্ষণ করতে বলে।
  24. // @description:ru Добавляет кнопку экспорта в блоки кода в ответах ChatGPT, предлагает пользователю сохранить код в файл с предопределенным именем на основе обнаруженного языка программирования из имени класса блока кода.
  25. // @description:pt Adiciona um botão de exportação aos blocos de código nas respostas do ChatGPT, solicitando ao usuário que salve o código como arquivo com um nome predefinido com base na linguagem de programação detectada a partir do nome da classe do bloco de código.
  26. // @description:ur چیٹ جی پی ٹی ردعملات میں کوڈ بلاکس میں برآمد بٹن شامل کرتا ہے، صارف کو کوڈ کو فائل کے طور پر محفوظ کرنے کے لیے پہلے سے تعین شدہ فائل نام پر پرومپٹ کرتا ہے جو کوڈ بلاک کے کلاس کے نام سے دریافت کیا گیا ہے
  27. // @author Muffin & Arcadie
  28. // @match https://chatgpt.com/*
  29. // @grant none
  30. // ==/UserScript==
  31.  
  32. (function() {
  33. 'use strict';
  34.  
  35. // Function to add "Export" button to existing code headers
  36. function addExportButtonToHeaders() {
  37. const codeHeaders = document.querySelectorAll('.flex.items-center.text-token-text-secondary.bg-token-main-surface-secondary.px-4.py-2.text-xs.font-sans.justify-between.rounded-t-md.h-9');
  38.  
  39. codeHeaders.forEach(header => {
  40. // Check if "Export" button is already added
  41. if (header.querySelector('.export-button')) {
  42. return; // Skip if already added
  43. }
  44.  
  45. const textNode = Array.from(header.childNodes).find(node => node.nodeType === Node.TEXT_NODE);
  46. const language = textNode ? textNode.textContent.trim() : '';
  47.  
  48. // Create the "Export" button
  49. const exportButton = document.createElement('button');
  50. exportButton.classList.add('export-button', 'flex', 'items-center', 'gap-1', 'text-xs', 'p-1', 'rounded');
  51. exportButton.setAttribute('title', 'Export Code');
  52.  
  53. // Create the SVG icon
  54. const exportIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  55. exportIcon.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
  56. exportIcon.setAttribute('viewBox', '0 0 1000 1000'); // Adjust viewBox as needed
  57. exportIcon.classList.add('h-4', 'w-4');
  58.  
  59. // Adding <defs> and <style> block
  60. const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  61. const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
  62. style.textContent = `.cls-1`;
  63. defs.appendChild(style);
  64. exportIcon.appendChild(defs);
  65.  
  66. // Adding your actual SVG paths
  67. const path1 = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  68. path1.setAttribute('d', 'm423.2,668.89l9.44-5.45c-7.66-2.87-15.26-5.91-22.81-9.15,4.38,5.04,8.84,9.89,13.37,14.61Z');
  69. path1.setAttribute('class', 'cls-1');
  70. exportIcon.appendChild(path1);
  71.  
  72. const path2 = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  73. path2.setAttribute('d', 'm233.24,672.15c-1.31-.31-2.62-.6-3.92-.95-37.87-10.15-70.17-34.9-89.82-68.84-17.33-29.94-23.57-65.02-17.64-99.1,1.17.7,3.2,1.95,4.67,2.79l57.28,33.08c-4.17-20.96-6.91-42.43-8.22-64.38l-23.3-13.46c-33.92-19.64-58.66-51.93-68.81-89.79-10.15-37.86-4.87-78.19,14.68-112.16,17.25-29.98,44.5-52.93,76.98-64.85,0,1.35-.08,3.75-.08,5.41v181.53c-.03,4.53,1.15,8.99,3.42,12.92,2.27,3.93,5.54,7.18,9.48,9.42l1.47.85c7.69-10.62,18.1-19.33,30.52-24.99,2.2-1,4.44-1.88,6.71-2.67v-177.06c.02-28.1,8.04-55.61,23.12-79.32,15.09-23.71,36.61-42.62,62.06-54.54,25.45-11.92,53.76-16.34,81.63-12.75,27.87,3.59,54.14,15.05,75.73,33.03-1.2.65-3.28,1.8-4.67,2.64l-157.13,90.76c-3.94,2.24-7.22,5.49-9.49,9.42-2.27,3.92-3.45,8.39-3.42,12.92l-.09,183.24c3.17,2.08,6.2,4.38,9.07,6.94,6.16,5.49,12.16,10.9,18.02,16.19l.14.12c2.98,2.69,5.92,5.34,8.83,7.96v-70.78l85.44-49.35,85.44,49.32v98.67l-76.55,44.18c12.49,7.4,25.07,14.01,37.79,19.84l38.73-22.36v37.58c11.85,3.9,23.84,7.18,35.99,9.84v-166.9l66.42,38.35c.35.17.65.43.87.75.23.32.37.69.42,1.07v38.04c3.9-2.91,8.08-5.5,12.55-7.65,10.38-4.99,21.96-7.63,33.49-7.63,1.88,0,3.75.08,5.61.22v-21.06c.04-4.53-1.13-8.98-3.38-12.91s-5.51-7.18-9.44-9.44l-191.84-110.77,66.42-38.34c.33-.22.7-.35,1.09-.38.39-.04.78.03,1.15.18l158.86,91.71c24.34,14.06,44.17,34.76,57.17,59.68,13,24.92,18.63,53.02,16.23,81.03-.51,5.98-1.41,11.91-2.63,17.74l43.84,35.07c9.59-27.52,13.09-56.95,10-86.23-4.4-41.89-22-81.29-50.24-112.54,8.85-26.57,11.92-54.72,9-82.56-2.92-27.85-11.74-54.75-25.9-78.91-20.98-36.54-53.03-65.47-91.52-82.62-38.49-17.15-81.43-21.62-122.63-12.78-18.58-20.94-41.42-37.67-66.99-49.08C430.26,6.13,402.55.33,374.55.5c-42.12-.1-83.19,13.18-117.28,37.92-34.09,24.74-59.44,59.67-72.4,99.75-27.44,5.62-53.36,17.03-76.04,33.48-22.67,16.45-41.57,37.55-55.43,61.89-21.15,36.44-30.17,78.66-25.78,120.56,4.4,41.9,21.99,81.33,50.24,112.59-8.85,26.57-11.92,54.71-9,82.56,2.92,27.85,11.74,54.75,25.9,78.91,20.98,36.54,53.03,65.47,91.52,82.62,26.61,11.86,55.35,17.64,84.16,17.17-2.63-3.43-5.24-6.9-7.82-10.42-10.78-14.71-20.58-29.85-29.39-45.38ZM570.51,114.04c28.07,1.21,55.21,10.38,78.25,26.44,23.04,16.07,41.03,38.36,51.87,64.28,10.83,25.92,14.07,54.38,9.31,82.07-1.16-.72-3.2-1.94-4.67-2.78l-157.14-90.76c-3.92-2.29-8.37-3.49-12.9-3.49s-8.99,1.21-12.91,3.49l-191.84,110.77v-76.7c-.02-.39.05-.78.22-1.14.17-.35.42-.66.73-.9l158.85-91.64c24.33-14.03,52.16-20.84,80.23-19.64Z');
  74. path2.setAttribute('class', 'cls-1');
  75. exportIcon.appendChild(path2);
  76.  
  77. const path3 = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  78. path3.setAttribute('d', 'm502.87,730.73c19.95,11.06,41.04,19.95,63.33,26.7,2.81-1.83,5.6-3.71,8.33-5.69,20.27-14.71,37.41-33.04,50.73-53.9-21.31-.2-42.35-1.47-62.99-3.79-.2.2-.38.41-.58.61-16.64,16.65-36.85,28.9-58.81,36.07Z');
  79. path3.setAttribute('class', 'cls-1');
  80. exportIcon.appendChild(path3);
  81.  
  82. const path4 = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  83. path4.setAttribute('d', 'm959.11,704.34l-284.19-227.36c-6.75-5.4-15.23-8.38-23.88-8.38-5.7,0-11.42,1.3-16.55,3.77-13.16,6.32-21.66,19.85-21.66,34.45v75.19c-28.92-1.03-57.02-4.48-83.72-10.3-69.87-15.24-134.55-48.71-197.73-102.3-11.95-10.13-23.61-20.66-35.95-31.8l-.14-.12c-5.77-5.21-11.75-10.6-17.83-16.02-7.01-6.24-16.04-9.68-25.43-9.68-5.5,0-10.84,1.16-15.85,3.45-13.77,6.28-22.55,20.12-22.36,35.26,1.14,90.66,28.18,172.74,80.36,243.95,80.72,110.16,188,174.2,319.04,190.48v76.37c0,14.6,8.5,28.12,21.66,34.45,5.14,2.47,10.86,3.77,16.55,3.77,8.65,0,17.13-2.98,23.88-8.38l283.8-227.1c9.11-7.29,14.34-18.17,14.34-29.84s-5.23-22.55-14.34-29.84Zm-269.46,177.41v-31.76c0-20.26-15.84-37.02-36.06-38.16-125.38-7.08-222.78-60.26-297.76-162.59-23.24-31.72-40.44-66.31-51.37-103.25,65.99,51.32,134.41,84.25,208.36,100.38,37.68,8.22,77.51,12.39,118.38,12.39,5.52,0,11.13-.08,16.69-.23,3.4-.09,6.1-.54,7.72-.81l.23-.04c.19-.03.39-.07.62-.1,18.7-2.68,32.8-18.94,32.8-37.83v-33.42l184.8,147.85-184.41,147.57Z');
  84. path4.setAttribute('class', 'cls-1');
  85. exportIcon.appendChild(path4);
  86.  
  87. // Append the SVG icon to the button
  88. exportButton.appendChild(exportIcon);
  89.  
  90. // Add the button text
  91. const buttonText = document.createElement('span');
  92. buttonText.textContent = 'Export';
  93. exportButton.appendChild(buttonText);
  94.  
  95. // Create the tooltip
  96. const tooltip = document.createElement('div');
  97. tooltip.classList.add('tooltip', 'flex', 'items-center', 'gap-1', 'text-xs', 'p-1', 'rounded', 'absolute', 'bg-black', 'text-white', 'hidden');
  98. tooltip.style.top = '110%';
  99. tooltip.style.left = '50%';
  100. tooltip.style.transform = 'translateX(-50%)';
  101. tooltip.style.whiteSpace = 'nowrap';
  102.  
  103. // Create the tooltip text
  104. const tooltipText = document.createElement('span');
  105. tooltipText.textContent = 'Export Code';
  106. tooltip.appendChild(tooltipText);
  107.  
  108. // Append the tooltip to the button
  109. exportButton.appendChild(tooltip);
  110.  
  111. // Find the element containing "Copy code"
  112. let copyCodeDiv = null;
  113. const elements = header.querySelectorAll('.flex.items-center.relative.text-token-text-secondary.bg-token-main-surface-secondary.px-4.py-2.text-xs.font-sans.justify-between.rounded-t-md div');
  114. elements.forEach(element => {
  115. if (element.innerHTML.includes('Copy code')) {
  116. copyCodeDiv = element;
  117. }
  118. });
  119.  
  120. // Insert "Export" button before the found element or append to header if not found
  121. if (copyCodeDiv) {
  122. copyCodeDiv.parentNode.insertBefore(exportButton, copyCodeDiv);
  123. } else {
  124. header.appendChild(exportButton);
  125. }
  126.  
  127. // Add hover event listener for the "Export" button to show tooltip
  128. exportButton.addEventListener('mouseenter', () => {
  129. tooltip.classList.remove('hidden');
  130. });
  131.  
  132. // Add hover event listener for the "Export" button to hide tooltip
  133. exportButton.addEventListener('mouseleave', () => {
  134. tooltip.classList.add('hidden');
  135. });
  136.  
  137. // Add click event listener for the "Export" button
  138. exportButton.addEventListener('click', () => {
  139. // Get the grandparent element (pre > div > header)
  140. const preElement = header.parentElement.parentElement; // This navigates to the 'pre' element
  141. // Now find the <code> block inside the <pre> tag
  142. const codeBlock = preElement.querySelector('code');
  143. // Now you have the code content inside the 'codeBlock' element as text
  144. console.log(codeBlock.textContent); // This will log the code content to the console
  145. // Call export function with the updated code block and language
  146. exportCode(codeBlock, language);
  147. });
  148. });
  149. }
  150.  
  151. // Function to open File Explorer for saving the code as file
  152. async function exportCode(codeBlock, language) {
  153. let fileName;
  154. let fileExtension;
  155. let mimeType;
  156.  
  157. // Determine filename, extension, and MIME type based on language
  158. switch (language) {
  159. case 'javascript':
  160. case 'js':
  161. fileName = 'script';
  162. fileExtension = '.js';
  163. mimeType = 'application/javascript';
  164. break;
  165. case 'html':
  166. fileName = 'index';
  167. fileExtension = '.html';
  168. mimeType = 'text/html';
  169. break;
  170. case 'css':
  171. fileName = 'styles';
  172. fileExtension = '.css';
  173. mimeType = 'text/css';
  174. break;
  175. case 'python':
  176. case 'py':
  177. fileName = 'main';
  178. fileExtension = '.py';
  179. mimeType = 'text/x-python';
  180. break;
  181. case 'json':
  182. fileName = 'manifest';
  183. fileExtension = '.json';
  184. mimeType = 'application/json';
  185. break;
  186. case 'java':
  187. fileName = 'Main'; // Entry point for Java programs
  188. fileExtension = '.java';
  189. mimeType = 'text/x-java-source';
  190. break;
  191. case 'c':
  192. fileName = 'program';
  193. fileExtension = '.c';
  194. mimeType = 'text/x-c';
  195. break;
  196. case 'cpp':
  197. case 'c++':
  198. fileName = 'program';
  199. fileExtension = '.cpp';
  200. mimeType = 'text/x-c++';
  201. break;
  202. case 'csharp':
  203. case 'cs':
  204. fileName = 'Program';
  205. fileExtension = '.cs';
  206. mimeType = 'text/x-csharp';
  207. break;
  208. case 'ruby':
  209. fileName = 'script';
  210. fileExtension = '.rb';
  211. mimeType = 'text/x-ruby';
  212. break;
  213. case 'php':
  214. fileName = 'script';
  215. fileExtension = '.php';
  216. mimeType = 'application/php';
  217. break;
  218. case 'swift':
  219. fileName = 'main';
  220. fileExtension = '.swift';
  221. mimeType = 'text/x-swift';
  222. break;
  223. case 'go':
  224. fileName = 'main';
  225. fileExtension = '.go';
  226. mimeType = 'text/x-go';
  227. break;
  228. default:
  229. fileName = 'code';
  230. fileExtension = '.txt';
  231. mimeType = 'text/plain';
  232. break;
  233. }
  234.  
  235. // Create a Blob object with the code content
  236. const blob = new Blob([codeBlock.innerText], { type: mimeType });
  237.  
  238. try {
  239. if (window.showSaveFilePicker) {
  240. // Use File System Access API if available
  241. const fileHandle = await window.showSaveFilePicker({
  242. suggestedName: fileName + fileExtension,
  243. types: [
  244. {
  245. description: language,
  246. accept: {
  247. [mimeType]: [fileExtension],
  248. },
  249. },
  250. ],
  251. });
  252.  
  253. const writable = await fileHandle.createWritable();
  254. await writable.write(blob);
  255. await writable.close();
  256. } else {
  257. // Fallback for browsers that do not support showSaveFilePicker
  258. const downloadLink = document.createElement('a');
  259. downloadLink.href = URL.createObjectURL(blob);
  260. downloadLink.download = fileName + fileExtension;
  261. downloadLink.style.display = 'none';
  262. document.body.appendChild(downloadLink);
  263. downloadLink.click();
  264. URL.revokeObjectURL(downloadLink.href);
  265. document.body.removeChild(downloadLink);
  266. }
  267. } catch (error) {
  268. console.error('Save file dialog was canceled or failed', error);
  269. }
  270. }
  271.  
  272. // Observe the document for changes and add "Export" button to new code headers
  273. const observer = new MutationObserver(addExportButtonToHeaders);
  274. observer.observe(document.body, { childList: true, subtree: true });
  275.  
  276. // Initial processing of existing code headers
  277. addExportButtonToHeaders();
  278.  
  279. // Add custom CSS styles if needed
  280. const style = document.createElement('style');
  281. style.textContent = `
  282. .export-button:hover .tooltip {
  283. display: block;
  284. opacity: 1;
  285. }
  286. .export-button:hover svg {
  287. fill: #333;
  288. }
  289. .export-button:hover {
  290. background-color: #c7c7c7;
  291. color: #333;
  292. }
  293. .export-button {
  294. position: relative;
  295. background: none;
  296. border: none;
  297. cursor: pointer;
  298. display: flex;
  299. align-items: center;
  300. padding: 4px 8px;
  301. border-radius: 4px;
  302. color: rgb(180, 180, 180);
  303. transition: background-color 0.3s ease, color 0.3s ease;
  304. }
  305. .export-button svg {
  306. width: 16px;
  307. height: 16px;
  308. fill: rgb(180, 180, 180);
  309. transition: fill 0.3s ease;
  310. }
  311. .export-button span {
  312. margin-left: 0px;
  313. font-size: 12px;
  314. font-weight: 420;
  315. color: inherit;
  316. }
  317. .export-button .tooltip {
  318. display: none;
  319. position: absolute;
  320. top: 100%;
  321. left: 50%;
  322. transform: translateX(-50%);
  323. background-color: #333;
  324. color: #fff;
  325. font-size: 10px;
  326. padding: 4px 8px;
  327. border-radius: 4px;
  328. white-space: nowrap;
  329. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  330. opacity: 0;
  331. transition: opacity 0.2s ease;
  332. z-index: 10;
  333. }
  334. /* Style for the container with specific padding and spacing */
  335. .flex.items-center.text-token-text-secondary.bg-token-main-surface-secondary.px-4.py-2.text-xs.font-sans.justify-between.rounded-t-md.h-9 {
  336. padding-right: 7rem; /* Adjusted padding */
  337. }
  338. `;
  339. document.head.appendChild(style);
  340. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址