├── .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 |
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 | 
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 | 
37 | 2. Demo of C++ code generated by ChatGPT.
38 | 
39 | 3. Demo of Java code generated by ChatGPT.
40 | 
41 | 4. Demo of C# code generated by ChatGPT.
42 | 
43 |
44 | # Video Demo.
45 | This showcase video demo of **ChatGP**T _Code runner_ in action showing **Save** and **Run** code features.
46 | [](https://www.youtube.com/shorts/W9OWmsmINSo)
47 |
48 |
49 | ## Settings and customization.
50 | 
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 |
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 |
--------------------------------------------------------------------------------