├── .DS_Store ├── icons ├── 128.png ├── 16.png ├── 48.png └── .DS_Store ├── popup ├── .DS_Store ├── popup.js ├── popup.html └── popup.css ├── resources ├── logo.png ├── .DS_Store ├── settings.png ├── cpp_factorial.png ├── java_sum_even.png ├── csharp_sum_even.png └── python_factorial.png ├── manifest.json ├── LICENSE ├── background.js ├── options ├── options.js └── options.html ├── README.md └── scripts └── content-script.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/.DS_Store -------------------------------------------------------------------------------- /icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/icons/128.png -------------------------------------------------------------------------------- /icons/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/icons/16.png -------------------------------------------------------------------------------- /icons/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/icons/48.png -------------------------------------------------------------------------------- /icons/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/icons/.DS_Store -------------------------------------------------------------------------------- /popup/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/popup/.DS_Store -------------------------------------------------------------------------------- /resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/resources/logo.png -------------------------------------------------------------------------------- /resources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/resources/.DS_Store -------------------------------------------------------------------------------- /resources/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/resources/settings.png -------------------------------------------------------------------------------- /resources/cpp_factorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/resources/cpp_factorial.png -------------------------------------------------------------------------------- /resources/java_sum_even.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/resources/java_sum_even.png -------------------------------------------------------------------------------- /resources/csharp_sum_even.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/resources/csharp_sum_even.png -------------------------------------------------------------------------------- /resources/python_factorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haseeb-heaven/code-runner-extension/HEAD/resources/python_factorial.png -------------------------------------------------------------------------------- /popup/popup.js: -------------------------------------------------------------------------------- 1 | // popup.js 2 | document.addEventListener("DOMContentLoaded", () => { 3 | chrome.runtime.openOptionsPage(); 4 | }); 5 | -------------------------------------------------------------------------------- /popup/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extension Popup 5 | 6 | 7 | 8 |
9 | 13 | Settings 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "ChatGPT Code Runner", 4 | "version": "1.0", 5 | "description": "Run and save the code in ChatGPT, Supports upto 70+ languages.", 6 | "permissions": ["storage", "activeTab", "clipboardRead"], 7 | "host_permissions": [ 8 | "https://api.jdoodle.com/v1/execute", 9 | "*://*/*" 10 | ], 11 | "options_page": "options/options.html", 12 | "icons": { 13 | "16": "icons/16.png", 14 | "48": "icons/48.png", 15 | "128": "icons/128.png" 16 | }, 17 | "action": { 18 | "default_popup": "popup/popup.html", 19 | "default_icon": {"48": "icons/48.png"} 20 | }, 21 | "content_scripts": [ 22 | { 23 | "matches": ["https://chat.openai.com/*"], 24 | "js": ["scripts/content-script.js"] 25 | } 26 | ], 27 | "background": { 28 | "service_worker": "background.js" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /popup/popup.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | #container { 8 | width: 300px; 9 | padding: 16px; 10 | } 11 | 12 | #header { 13 | display: flex; 14 | align-items: center; 15 | } 16 | 17 | #logo { 18 | width: 48px; 19 | height: 48px; 20 | margin-right: 8px; 21 | } 22 | 23 | #code-input { 24 | width: 100%; 25 | padding: 8px; 26 | margin: 16px 0; 27 | box-sizing: border-box; 28 | } 29 | 30 | #button-container { 31 | display: flex; 32 | justify-content: space-between; 33 | } 34 | 35 | button { 36 | padding: 8px 16px; 37 | border: none; 38 | border-radius: 4px; 39 | font-weight: bold; 40 | cursor: pointer; 41 | } 42 | 43 | #run-code { 44 | background-color: #007bff; 45 | color: #fff; 46 | } 47 | 48 | #save-code { 49 | background-color: #28a745; 50 | color: #fff; 51 | } 52 | 53 | #options-link { 54 | display: block; 55 | margin-top: 16px; 56 | color: #007bff; 57 | text-decoration: none; 58 | } 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 HeavenHM 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | // Brief : This file contains the background script for the extension. 2 | // This uses JDoodle Compiler API to run the code and return the output. 3 | // Author: HeavenHM 4 | chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { 5 | if (request && request.type === 'runCode') { 6 | const { languageCode, code, clientId, clientSecret } = request; 7 | console.log("Running code in language code: ", languageCode); 8 | const compilerApiUrl = "https://api.jdoodle.com/v1/execute"; 9 | 10 | fetch(compilerApiUrl, { 11 | method: 'POST', 12 | headers: { 13 | 'Content-Type': 'application/json', 14 | 'X-Requested-With': 'XMLHttpRequest', 15 | }, 16 | body: JSON.stringify({ 17 | clientId, 18 | clientSecret, 19 | script: code, 20 | language: languageCode, 21 | versionIndex: '0', 22 | }), 23 | }) 24 | .then((response) => response.json()) 25 | .then((data) => { 26 | if (data && data.output) { 27 | console.log('Service worker sending response:', data.output); 28 | // Sending a successful response: 29 | sendResponse({ status: 200, output: data.output }); 30 | } else { 31 | console.error('Unexpected API response:', data); 32 | // Sending an error response: 33 | sendResponse({ status: 500, error: 'Unexpected API response' }); 34 | } 35 | }) 36 | .catch((error) => { 37 | console.error('Error while fetching data from Compiler API :', error); 38 | sendResponse({ status: 500, error: 'Error while fetching data from Compiler API' }); 39 | }); 40 | 41 | return true; // Indicate that the response will be sent asynchronously 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /options/options.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', () => { 2 | restoreOptions(); 3 | 4 | const form = document.getElementById('settings-form'); 5 | form.addEventListener('submit', saveOptions); 6 | }); 7 | 8 | function saveOptions(e) { 9 | e.preventDefault(); 10 | 11 | // Save new settings 12 | const apiKey = document.getElementById('api-key').value; 13 | const apiSecret = document.getElementById('api-secret').value; 14 | const theme = document.getElementById('theme').value; 15 | const fileName = document.getElementById('file-name').value; 16 | const fileExtension = document.getElementById('file-extension').value; 17 | const outputType = document.getElementById('output-type').value; 18 | 19 | // Check for empty values 20 | if (!apiKey || !apiSecret || !theme || !fileName || !fileExtension || !outputType) { 21 | alert('Please fill in all the settings fields'); 22 | return; 23 | } 24 | 25 | chrome.storage.sync.set( 26 | { apiKey, apiSecret, theme, fileName, fileExtension, outputType }, 27 | () => { 28 | console.log('Settings saved'); 29 | alert('Settings saved'); 30 | } 31 | ); 32 | } 33 | 34 | function restoreOptions() { 35 | chrome.storage.sync.get( 36 | ['apiKey', 'apiSecret', 'theme', 'fileName', 'fileExtension', 'outputType'], 37 | (result) => { 38 | if (result.apiKey) { 39 | document.getElementById('api-key').value = result.apiKey; 40 | } 41 | 42 | if (result.apiSecret) { 43 | document.getElementById('api-secret').value = result.apiSecret; 44 | } 45 | 46 | if (result.theme) { 47 | document.getElementById('theme').value = result.theme; 48 | } 49 | 50 | if (result.fileName) { 51 | document.getElementById('file-name').value = result.fileName; 52 | } 53 | 54 | if (result.fileExtension) { 55 | document.getElementById('file-extension').value = result.fileExtension; 56 | } 57 | 58 | if (result.outputType) { 59 | document.getElementById('output-type').value = result.outputType; 60 | } 61 | } 62 | ); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![cover_logo](https://github.com/haseeb-heaven/ChatGPT-CodeRunner/blob/master/resources/logo.png?raw=true "") 2 | # Chat-GPT Code Runner 3 | 4 | Chat-GPT Code Runner is a _Google Chrome_ extension that enables you to **Run Code** and **Save code** in more than **70 programming languages** using the **JDoodle Compiler _API_**. This powerful tool offers a variety of **themes** and the ability to _save_ your code locally. Enhance your coding experience with Chat-GPT Code Runner! 5 | - **Support this Project** 6 | ## Features 7 | 8 | - **Save Code Locally**: Save your code to your local machine for easy access and management. 9 | - **Run Code in 70+ Languages**: Supports over 70 programming languages, offering versatility and flexibility for your coding needs. 10 | - **JDoodle Compiler**: Utilizes the JDoodle Compiler API to compile and run code online. 11 | - **Multiple Themes**: Choose from a variety of themes to customize your coding environment. 12 | 13 | ## Installation and Setup 14 | 15 | 1. Clone or download the repository to your local machine. 16 | 2. Follow the instructions on [this page](https://www.jdoodle.com/compiler-api/) to create a free JDoodle account and obtain your API Key and Secret. With a free account, you'll receive 200 credits per day. 17 | 3. Install the extension in your Google Chrome browser: 18 | - Open the Extension Management page by navigating to `chrome://extensions`. 19 | - Enable Developer Mode by clicking the toggle switch next to "Developer mode". 20 | - Click the "Load unpacked" button and select the extension directory. 21 | 4. Configure the extension settings: 22 | - Open the extension's settings by right-clicking the Chat-GPT Code Runner icon in your browser and selecting "Options". 23 | - Enter your JDoodle API Key and Secret in the corresponding fields and save the settings. 24 | 25 | Now you're ready to use Chat-GPT Code Runner! 26 | 27 | ## Usage 28 | 29 | 1.Ask **ChatGPT** to generate code for you.
30 | 2.Now you will see two buttons as **Run Code** and **Save Code** in the browser.
31 | 3.Now click on **Run Code** to run the code and you can see the output directly in the browser.
32 | 4.Now click on **Save Code** to save the code in your local machine.
33 | 34 | ## Usage Demo. 35 | 1. Demo of Python code generated by ChatGPT.
36 | ![python_code](https://github.com/haseeb-heaven/ChatGPT-CodeRunner/blob/master/resources/python_factorial.png?raw=true "") 37 | 2. Demo of C++ code generated by ChatGPT.
38 | ![cpp_code](https://github.com/haseeb-heaven/ChatGPT-CodeRunner/blob/master/resources/cpp_factorial.png?raw=true "") 39 | 3. Demo of Java code generated by ChatGPT.
40 | ![java_code](https://github.com/haseeb-heaven/ChatGPT-CodeRunner/blob/master/resources/java_sum_even.png?raw=true "") 41 | 4. Demo of C# code generated by ChatGPT.
42 | ![csharp_code](https://github.com/haseeb-heaven/ChatGPT-CodeRunner/blob/master/resources/csharp_sum_even.png?raw=true "") 43 | 44 | # Video Demo. 45 | This showcase video demo of **ChatGP**T _Code runner_ in action showing **Save** and **Run** code features.
46 | [![video_demo](https://img.youtube.com/vi/W9OWmsmINSo/0.jpg)](https://www.youtube.com/shorts/W9OWmsmINSo) 47 | 48 | 49 | ## Settings and customization. 50 | ![settings_page](https://github.com/haseeb-heaven/ChatGPT-CodeRunner/blob/master/resources/settings.png?raw=true "")
51 | This extesion also provides you the ability to customize the theme of the buttons and output type.
52 | 1. **Theme**: You can choose from the _10 themes_ available. 53 | 2. **Output Type**: You can choose from the 2 output types available. 54 | 3. **Run Code**: You can choose from the 2 options available. 55 | 4. **Save Code**: You can choose set custom **file name** and **file extension** for the code to be saved. 56 | 57 | Written by **_HeavenHM @ 2023_** . 58 | -------------------------------------------------------------------------------- /options/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Extension Settings 6 | 97 | 98 | 99 | 100 |

ChatGPT Code Runner Settings

101 |
102 |

Compiler Settings

103 | 104 | 105 | 106 | 107 | 108 |

Theme Settings

109 | 110 | 122 | 123 |

File Settings

124 | 125 | 126 | 127 | 128 | 129 |

Output Settings

130 | 131 | 135 | 136 | 137 |
138 | 139 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /scripts/content-script.js: -------------------------------------------------------------------------------- 1 | /* Description: This extension is used to save and run code snippets from the Chat-GPT website. 2 | It uses JDoodle Compiler API to run the code and display the output. 3 | Author : HeavenHM. 4 | Date : 03/05/2023 */ 5 | 6 | // List of supported languages and their file extensions. 7 | const supportedLanguages = { 8 | "javascript": ".js", 9 | "html": ".html", 10 | "css": ".css", 11 | "python": ".py", 12 | "java": ".java", 13 | "c": ".c", 14 | "cpp": ".cpp", 15 | "c++": ".cpp", 16 | "php": ".php", 17 | "ruby": ".rb", 18 | "swift": ".swift", 19 | "typescript": ".ts", 20 | "go": ".go", 21 | "kotlin": ".kt", 22 | "rust": ".rs", 23 | "scala": ".scala", 24 | "perl": ".pl", 25 | "lua": ".lua", 26 | "objective-c": ".m", 27 | "shell": ".sh", 28 | "sql": ".sql", 29 | "visual basic": ".vb", 30 | "c#": ".cs", 31 | "csharp": ".cs", 32 | "f#": ".fs", 33 | "haskell": ".hs", 34 | }; 35 | 36 | // List of language codes supported by JDoodle Compiler API. 37 | const languageCodes = { 38 | "c++": "cpp17", 39 | "cpp": "cpp14", 40 | "cs": "csharp", 41 | "objective-c": "objc", 42 | "javascript": "nodejs", 43 | "python": "python3", 44 | "basic": "freebasic", 45 | }; 46 | 47 | // List of themes supported by the extension. 48 | const themes = [ 49 | { name: 'emerald_water', color_fg: '#2ecc71', color_bg: '#2eec7f' }, 50 | { name: 'midnight_sky', color_fg: '#2c3e50', color_bg: '#34495e' }, 51 | { name: 'midnight_plum', color_fg: '#4b0082', color_bg: '#483d8b' }, 52 | { name: 'classic', color_fg: '#808080', color_bg: '#f2f2f2' }, 53 | { name: 'royal_purple', color_fg: '#6A1B9A', color_bg: '#9C27B0' }, 54 | { name: 'sunny_day', color_fg: '#FFEB3B', color_bg: '#FFC107' }, 55 | { name: 'ocean_breeze', color_fg: '#039be5', color_bg: '#03a9f4' }, 56 | { name: 'cherry_blossom', color_fg: '#e91e63', color_bg: '#ff80ab' }, 57 | { name: 'fire_engine', color_fg: '#d50000', color_bg: '#f44336' }, 58 | { name: 'forest_green', color_fg: '#006400', color_bg: '#228B22' } 59 | ]; 60 | 61 | 62 | // Method to get the theme code from the theme name. 63 | function getThemeColors(themeName) { 64 | const theme = themes.find((theme) => theme.name.toLowerCase() === themeName.toLowerCase()); 65 | const themeColors = theme ? [theme.color_fg, theme.color_bg] : ['#2ecc71', '#2eec7f']; 66 | return themeColors; 67 | } 68 | 69 | // Method to convert colour name to hex code. 70 | function colourNameToHex(colour) { 71 | const canvas = document.createElement('canvas'); 72 | canvas.width = canvas.height = 1; 73 | const ctx = canvas.getContext('2d'); 74 | ctx.fillStyle = colour; 75 | ctx.fillRect(0, 0, 1, 1); 76 | const data = ctx.getImageData(0, 0, 1, 1).data; 77 | const colorHex = "#" + data[0].toString(16).padStart(2, '0') + 78 | data[1].toString(16).padStart(2, '0') + 79 | data[2].toString(16).padStart(2, '0'); 80 | return colorHex; 81 | } 82 | 83 | // Utility function to apply the same theme to buttons 84 | function applyButtonTheme(button, colorStyle = "green", backgroundColorStyle = "gray", rawColorsHex = false, displayStyle = "inline-block") { 85 | button.classList.add("flex", "ml-auto", "gap-2"); 86 | button.style.padding = "2px 10px"; 87 | button.style.border = "1px solid #fff"; 88 | button.style.borderRadius = "20px"; 89 | button.style.color = rawColorsHex ? colorStyle : colourNameToHex(colorStyle); 90 | button.style.backgroundColorStyle = rawColorsHex ? backgroundColorStyle : colourNameToHex(backgroundColorStyle); 91 | button.style.fontWeight = "300"; 92 | button.style.marginRight = "10px"; 93 | button.style.display = displayStyle; 94 | } 95 | 96 | // Creating the save and run code buttons. 97 | function createSaveFileButton(colorStyle = "green", backgroundColorStyle = "gray", rawColorsHex = false) { 98 | const button = document.createElement("button"); 99 | button.textContent = "Save code"; 100 | button.id = "save-code-btn"; 101 | applyButtonTheme(button, colorStyle, backgroundColorStyle, rawColorsHex); 102 | return button; 103 | } 104 | 105 | // Creating Run code button. 106 | function createRunCodeButton(colorStyle = "green", backgroundColorStyle = "gray", rawColorsHex = false) { 107 | const button = document.createElement("button"); 108 | button.textContent = "Run code"; 109 | button.id = "run-code-btn"; 110 | applyButtonTheme(button, colorStyle, backgroundColorStyle, rawColorsHex); 111 | return button; 112 | } 113 | 114 | // Removing the SVG icon from the Copy button. 115 | function removeSvgIcon() { 116 | const svgIcon = document.querySelector('button.flex.ml-auto.gap-2 svg'); 117 | if (svgIcon) { 118 | svgIcon.parentNode.removeChild(svgIcon); 119 | } 120 | } 121 | 122 | // Creating the handler for save and run code buttons. 123 | async function handleSaveFileClick(container) { 124 | const copyButton = container.querySelector('button[class="flex ml-auto gap-2"]'); 125 | const languageSpan = container.querySelector("span"); 126 | const language = languageSpan ? languageSpan.textContent.trim() : ""; 127 | const defaultFileExtension = getSettings().fileExtension; 128 | 129 | if (copyButton) { 130 | copyButton.click(); 131 | try { 132 | const clipboardData = await navigator.clipboard.readText(); 133 | const fileExtension = supportedLanguages[language] || defaultFileExtension; 134 | saveToFile(fileExtension, clipboardData); 135 | } catch (err) { 136 | console.error("Failed to read clipboard data:", err); 137 | } 138 | } 139 | } 140 | 141 | // Handle the run code button click. 142 | async function handleRunCodeClick(container) { 143 | const copyButton = container.querySelector('button[class="flex ml-auto gap-2"]'); 144 | const languageSpan = container.querySelector("span"); 145 | var language = languageSpan ? languageSpan.textContent.trim() : ""; 146 | var languageCode = language; 147 | 148 | // check if language is langCode 149 | if (language in languageCodes) { 150 | languageCode = languageCodes[language]; 151 | } 152 | 153 | if (copyButton) { 154 | copyButton.click(); 155 | try { 156 | const clipboardData = await navigator.clipboard.readText(); 157 | runCode(language, languageCode, clipboardData); 158 | } catch (err) { 159 | console.error("Failed to read clipboard data:", err); 160 | } 161 | } 162 | } 163 | 164 | // Helper method to get the data from the storage. 165 | function getFromStorage(keys) { 166 | return new Promise((resolve) => { 167 | chrome.storage.sync.get(keys, resolve); 168 | }); 169 | } 170 | 171 | // Method to get the settings from the storage. 172 | async function getSettings(initialRun = false) { 173 | try { 174 | const { apiKey, apiSecret, theme, fileName, fileExtension, outputType } = await getFromStorage(['apiKey', 'apiSecret', 'theme', 'fileName', 'fileExtension', 'outputType']); 175 | 176 | if (!apiKey || !apiSecret) { 177 | if (!initialRun) { 178 | const errorMsg = "Chat-GPT Code Runner:\nAPI Key or Secret not set\nPlease go to extension settings and set them"; 179 | console.error(errorMsg); 180 | alert(errorMsg); 181 | throw new Error(errorMsg); 182 | } 183 | } 184 | 185 | const settings = { 186 | clientId: apiKey, 187 | clientSecret: apiSecret, 188 | theme, 189 | fileName, 190 | fileExtension, 191 | outputType, 192 | }; 193 | return settings; 194 | 195 | } catch (error) { 196 | console.error("Failed to get settings:", error); 197 | } 198 | } 199 | 200 | 201 | // Display the output in the code container. 202 | function displayOutput(outputText, language) { 203 | try { 204 | const containers = document.querySelectorAll('.p-4.overflow-y-auto'); 205 | containers.forEach(container => { 206 | const languageClass = `language-${language}`; 207 | const hasLanguageChild = container.querySelector(`.\\!whitespace-pre.hljs.${languageClass}`); 208 | 209 | if (hasLanguageChild) { 210 | const existingOutputElement = container.querySelector(".output-text"); 211 | if (!existingOutputElement) { 212 | const outputElement = createOutputElement(outputText); 213 | container.appendChild(outputElement); 214 | } else { 215 | existingOutputElement.textContent = outputText; 216 | } 217 | } 218 | }); 219 | } 220 | catch (error) { 221 | console.error("Error in displayOutput: ", error); 222 | // Display the output using alert. 223 | alert(outputText); 224 | } 225 | } 226 | 227 | // Create the output element. 228 | function createOutputElement(text) { 229 | const outputElement = document.createElement('div'); 230 | outputElement.classList.add('output-text'); 231 | outputElement.textContent = text; 232 | return outputElement; 233 | } 234 | 235 | // Run the code using JDoodle Compiler API. 236 | async function runCode(language, languageCode, code) { 237 | console.log("Running code: in language: ", language, " with language code: ", languageCode); 238 | const { clientId, clientSecret, outputType } = await getSettings(); 239 | 240 | chrome.runtime.sendMessage({ type: 'runCode', languageCode, code, clientId, clientSecret }, (response) => { 241 | if (response && response.status === 200) { 242 | console.log("Response from Compiler: ", response); 243 | let outputResponse = "Compiler output: \n" + response.output; 244 | // Print the output with type. 245 | if (outputType == "codeblock") { 246 | displayOutput(outputResponse, language); 247 | } 248 | else { 249 | alert(outputResponse); 250 | } 251 | } else { 252 | console.error("Error while running code: ", response.error); 253 | alert("Error while running code\nPlease check console for more details"); 254 | } 255 | }); 256 | } 257 | 258 | 259 | // Method to save the code to a file. 260 | async function saveToFile(extension, data) { 261 | const settings = await getSettings(); 262 | var { fileName, fileExtension } = settings; 263 | fileExtension = extension || fileExtension; 264 | 265 | const fileNameExtension = fileName + `${fileExtension}`; 266 | const file = new Blob([data], { type: "text/plain" }); 267 | const url = URL.createObjectURL(file); 268 | 269 | const link = document.createElement("a"); 270 | link.href = url; 271 | link.download = fileNameExtension; 272 | link.style.display = "none"; 273 | document.body.appendChild(link); 274 | link.click(); 275 | 276 | setTimeout(() => { 277 | document.body.removeChild(link); 278 | URL.revokeObjectURL(url); 279 | }, 100); 280 | } 281 | 282 | // Add Save and Run Code buttons to all code containers. 283 | async function addButtonToContainers() { 284 | const containers = document.querySelectorAll('.flex.items-center.relative.text-gray-200.bg-gray-800.px-4.py-2.text-xs.font-sans.justify-between.rounded-t-md'); 285 | 286 | // Get the theme settings 287 | const settings = await getSettings(true); 288 | var theme = settings.theme; 289 | theme = theme ? theme : "emerald_water"; 290 | const [fgColor, bgColor] = getThemeColors(theme); 291 | 292 | containers.forEach(container => { 293 | const existingFileButton = container.querySelector("#save-code-btn"); 294 | if (!existingFileButton) { 295 | const button = createSaveFileButton(fgColor, bgColor, true); 296 | container.appendChild(button); 297 | button.addEventListener("click", () => handleSaveFileClick(container)); 298 | } 299 | 300 | const existingRunCodeButton = container.querySelector("#run-code-btn"); 301 | if (!existingRunCodeButton) { 302 | const button = createRunCodeButton(fgColor, bgColor, true); 303 | container.appendChild(button); 304 | button.addEventListener("click", () => handleRunCodeClick(container)); 305 | } 306 | const copyButton = container.querySelector('button[class="flex ml-auto gap-2"]'); 307 | applyButtonTheme(copyButton, fgColor, bgColor, true); 308 | removeSvgIcon(); 309 | }); 310 | 311 | } 312 | 313 | // Add buttons to existing code containers. 314 | //setInterval(addButtonToContainers, 5000); 315 | 316 | // Creating the observer to add buttons to new code containers. 317 | const observer = new MutationObserver(addButtonToContainers); 318 | observer.observe(document.body, { childList: true, subtree: true }); 319 | 320 | --------------------------------------------------------------------------------