Last active
July 10, 2024 03:15
-
-
Save dreness/bd45eee1f5dbb3f892eb4802745bfd74 to your computer and use it in GitHub Desktop.
Tampermonkey script for use with chatgpt.com to add a "Save code" button below the "Copy code" button
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Save Code Snippets | |
// @namespace http://tampermonkey.net/ | |
// @version 1.0 | |
// @description Add a button to save code snippets from ChatGPT responses | |
// @author dre | |
// @match https://chat.openai.com/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=openai.com | |
// @grant GM_download | |
// ==/UserScript== | |
/* Goal is to add a "Save code" button to each code block in the ChatGPT response, | |
right below the 'Copy code' button | |
The general shape of the DOM is as follows: | |
page | |
prompt_container | |
prompt_text | |
response_container | |
response_text | |
response_code_container? | |
response_code_header | |
language_name | |
copy_code_button | |
save_code_button | |
response_code | |
TODO | |
- try to suggest an appropriate file name extension | |
*/ | |
(function () { | |
'use strict'; | |
function downloadCodeSnippet(code, fileName) { | |
const blob = new Blob([code], { type: 'text/plain' }); | |
const url = URL.createObjectURL(blob); | |
const a = document.createElement('a'); | |
a.href = url; | |
a.download = fileName; | |
document.body.appendChild(a); | |
a.click(); | |
document.body.removeChild(a); | |
URL.revokeObjectURL(url); | |
} | |
// Add a "Save code" button below each "Copy code" button | |
function addSaveButton() { | |
const codeBlocks = document.querySelectorAll('pre'); | |
codeBlocks.forEach(codeBlock => { | |
// check the codeBlock for an existing save button, which will have the class 'save-code-button'. | |
// If present, skip this iteration. | |
if (codeBlock.parentNode.querySelector('.save-code-button')) { | |
return; | |
} | |
const buttons = codeBlock.parentNode.querySelectorAll('button'); | |
buttons.forEach(button => { | |
if (button.textContent === 'Copy code') { | |
const saveButton = document.createElement('button'); | |
saveButton.className = 'flex gap-1 items-center save-code-button'; | |
saveButton.onclick = () => { | |
const code = | |
button.parentElement.parentElement.parentElement.parentElement | |
.children[1].innerText; | |
let chatId = window.location.pathname.split('/').pop(); | |
let fileName = prompt('Enter the filename:', 'code.txt'); | |
if (!fileName) { | |
return; | |
} | |
if (chatId) { | |
fileName = `${chatId}_${fileName}`; | |
} | |
downloadCodeSnippet(code, fileName); | |
}; | |
const svg = document.createElementNS( | |
'http://www.w3.org/2000/svg', | |
'svg' | |
); | |
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); | |
svg.setAttribute('width', '24'); | |
svg.setAttribute('height', '24'); | |
svg.setAttribute('fill', 'none'); | |
svg.setAttribute('viewBox', '0 0 24 24'); | |
svg.setAttribute('class', 'icon-sm'); | |
const path = document.createElementNS( | |
'http://www.w3.org/2000/svg', | |
'path' | |
); | |
path.setAttribute('fill', 'white'); | |
path.setAttribute( | |
'd', | |
'M7.93184 18.7313C8.18368 18.7313 8.41618 18.6677 8.86336 18.1979L15.5295 11.0094C15.7181 10.8074 15.8637 10.5991 15.8637 10.3249C15.8637 9.93867 15.5627 9.7282 15.1999 9.7282L11.059 9.7282L11.059 1.69172C11.059 0.591447 10.491 0 9.42586 0L6.35145 0C5.27461 0 4.71832 0.591447 4.71832 1.69172L4.71832 9.7282L0.658832 9.7282C0.296017 9.7282 0 9.93867 0 10.3233C0 10.5975 0.144727 10.8107 0.318401 11.0094L7.00114 18.1979C7.4366 18.6568 7.68082 18.7313 7.93184 18.7313Z' | |
); | |
svg.appendChild(path); | |
saveButton.appendChild(svg); | |
saveButton.appendChild(document.createTextNode('Save code')); | |
button.parentNode.appendChild(saveButton); | |
} | |
}); | |
}); | |
} | |
// Add save button to existing code blocks | |
addSaveButton(); | |
// Add mutation observer to detect new code blocks | |
const observer = new MutationObserver(mutations => { | |
observer.disconnect(); | |
mutations.forEach(() => { | |
addSaveButton(); | |
}); | |
observer.observe(document.body, { childList: true, subtree: true }); | |
}); | |
observer.observe(document.body, { childList: true, subtree: true }); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
save-code-demo.mp4