├── icon.png ├── usage.png ├── manifest.json ├── popup.html ├── LICENSE ├── readme.md └── content.js /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/italojs/correct-me-ai/HEAD/icon.png -------------------------------------------------------------------------------- /usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/italojs/correct-me-ai/HEAD/usage.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "AI Corrector", 4 | "version": "1.0", 5 | "description": "Correct the selected text with AI", 6 | "permissions": ["activeTab"], 7 | "content_scripts": [ 8 | { 9 | "matches": [""], 10 | "js": ["content.js"], 11 | "run_at": "document_end" 12 | } 13 | ], 14 | "icons": { 15 | "48": "icon.png" 16 | }, 17 | "browser_action": { 18 | "default_icon": "icon.png", 19 | "default_popup": "popup.html" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AI corrector 7 | 8 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Italo José 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. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Chrome Extension for Text Correction with OpenAI API 2 | 3 | ![](./usage.png) 4 | ## Description 5 | 6 | This Chrome extension enables users to select text on any web page and receive instant corrections for the selected text using the OpenAI API. An icon will appear next to the selected text, and upon clicking this icon, a modal will display with a language selector and the text correction in the chosen language. 7 | 8 | ## Features 9 | 10 | - Text selection for correction 11 | - Interactive icon to access the correction 12 | - Modal with language selector and text correction 13 | - Language selection storage for future use 14 | - Integration with OpenAI API for real-time corrections 15 | 16 | ## How to Use 17 | 18 | 1. Clone this repository to your local machine. 19 | 2. Open Chrome and navigate to `chrome://extensions/`. 20 | 3. Enable Developer Mode. 21 | 4. Click on "Load unpacked" and select the folder of the cloned repository. 22 | 5. The extension should now be visible and active. 23 | 6. Navigate to any web page, select a text, and click on the appearing icon to view the correction. 24 | 25 | ## Code Structure 26 | 27 | - `content.js`: Contains all the JavaScript code to manipulate the DOM, capture the selected text, display the icon and modal, and make requests to the OpenAI API. 28 | 29 | ## Requirements 30 | 31 | - Google Chrome 32 | - OpenAI API Key 33 | 34 | ## OpenAI API Setup 35 | 36 | You need an OpenAI API key to make requests. Replace `'YOUR_OPENAI_API_KEY'` with your API token in the `content.js` file. 37 | 38 | ## Contributing 39 | 40 | Feel free to clone, modify, and distribute this code as needed. Pull requests and improvements are welcome! 41 | 42 | ## License 43 | 44 | This project is open-source and available under the MIT license. 45 | 46 | ## Support 47 | 48 | For assistance or discussions about this project, please open an issue on the repository. 49 | -------------------------------------------------------------------------------- /content.js: -------------------------------------------------------------------------------- 1 | const OPEN_API_KEY = // "YOUR_OPEN_API_KEY_HERE" 2 | document.addEventListener('click', function(e) { 3 | let selectedText = window.getSelection().toString().trim(); 4 | 5 | if (!e.target.closest('#language-popup') && !e.target.classList.contains('translation-icon')) { 6 | document.querySelectorAll('.translation-icon-container').forEach(container => container.remove()); 7 | } 8 | 9 | if (selectedText.length > 0 && !e.target.closest('#language-popup') && !e.target.classList.contains('translation-icon')) { 10 | let container = document.createElement('div'); 11 | container.style.position = 'absolute'; 12 | container.style.top = '0'; 13 | container.style.left = '0'; 14 | container.style.width = '800px'; 15 | container.style.height = 'auto'; 16 | container.style.zIndex = '2147483647'; 17 | container.classList.add('translation-icon-container'); 18 | 19 | let icon = document.createElement('img'); 20 | icon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAhQAAAIUB4uz/wQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKCSURBVEiJtZVNSBRhGMd/7+yuu4pWuxBohIiItkFZtChhW5B0KoiioFMQ0TEpT56CCDwWdBA6RdAlNMhDIdjHITMoy1hK3cA+UNh0tHVddm2cfeftYLvqrrOOSg/M4X2e9///zTMzzztCKUXRiF6NIbQrKBUCEQT+oIgBD7Fc99h7+3cxubAFjF6vwmU9QHGiiD5NeuIZMtlJqH/YOeBrWyNK9AGVxe4uF/pAHDl7kmM/3q4PGGkP4JIfgBpH5gBKwtTzGFqikXBMX1nSCja7rM4NmQMIFwSaqsiUv8ovrQaMtAdAXdyQeTZK/KBkkP7qXfYALdMClG4KAODbqaG52+0Bgt2bNgdwl4MQh/8fQFmArLUHwLYtAcwECE+qCEC82RLAmAXNN24P0NQLYJ2zw85cX7o8pU9XpgsHLXptAFRLdmkp6H6ZIrTHy5fvJmZGcbC+hHejBmePllHiEUsbY30gU0laJ1c95sJBs9QlYD63QcCR/T4GPxvMpy3iSYuBiEFT0LtsPheB9CR4K2/m2619FkXbzoHozk8PjS2SSFm0HvItJ+fHQH8NFfWPCH+6kK8p7ACg4W4PqPPArzXrsPTFxPpgZhAq6p6sZW4PyEK8WhC4X1BbnIOJx2CZU+zY10I4csbOxm0LAKi5MwfiMtG2OiCcy6e+gbvcIB2o5fhgupiFfQe5UAr4WJByl01xaqioOazXwb94P9nQPJPajinB8kLPz2Y8Kl552oHWQQcQSwYiadOHqXxIfBjSSzLjn3WidQQwpacXkNl1JpNB4el1orX/6edFV1fXgYWFheHp6Wn8fv+Njo6OW050jt4BgGEY0UQiMa7rerWUsmAI7eIvX1b2jh7te6MAAAAASUVORK5CYII='; 21 | icon.style.position = 'absolute'; 22 | icon.style.top = e.clientY + 'px'; 23 | icon.style.left = e.clientX + 'px'; 24 | icon.style.cursor = 'pointer'; 25 | 26 | container.appendChild(icon); 27 | document.body.appendChild(container); 28 | 29 | icon.onclick = function(event) { 30 | event.stopPropagation(); 31 | if (!document.getElementById('language-popup')) { 32 | createPopup(e.clientX, e.clientY, selectedText, container); 33 | } 34 | }; 35 | } 36 | }); 37 | 38 | function createPopup(x, y, selectedText, container) { 39 | let popup = document.createElement('div'); 40 | popup.id = 'language-popup'; 41 | popup.style.position = 'absolute'; 42 | popup.style.maxWidth = '600px'; 43 | popup.style.backgroundColor = 'white'; 44 | popup.style.border = '1px solid black'; 45 | popup.style.zIndex = '2147483647'; 46 | popup.style.padding = '10px'; 47 | 48 | 49 | const popupWidth = 600; 50 | const popupHeight = 150; 51 | const windowWidth = window.innerWidth; 52 | const windowHeight = window.innerHeight; 53 | 54 | if (x + popupWidth > windowWidth) { 55 | x = windowWidth - popupWidth - 100; 56 | } 57 | 58 | if (y + popupHeight > windowHeight) { 59 | y = windowHeight - popupHeight - 100; 60 | } 61 | 62 | popup.style.top = y + 'px'; 63 | popup.style.left = x + 'px'; 64 | 65 | let select = document.createElement('select'); 66 | let options = ['English', 'Spanish', 'Portuguese']; 67 | options.forEach(option => { 68 | let opt = document.createElement('option'); 69 | opt.textContent = option; 70 | select.appendChild(opt); 71 | }); 72 | 73 | popup.appendChild(select); 74 | container.appendChild(popup); 75 | 76 | 77 | let loading = document.createElement('div'); 78 | loading.id = 'loading'; 79 | loading.textContent = 'Loading...'; 80 | popup.appendChild(loading); 81 | 82 | let correction = document.createElement('p'); 83 | popup.appendChild(correction); 84 | 85 | let selectedLanguage = localStorage.getItem('selectedLanguage') || 'Inglês'; 86 | 87 | const getCorrection = (language) => { 88 | loading.style.display = 'block'; 89 | fetch('https://api.openai.com/v1/engines/text-davinci-003/completions', { 90 | method: 'POST', 91 | headers: { 92 | 'Content-Type': 'application/json', 93 | 'Authorization': `Bearer ${OPEN_API_KEY}` 94 | }, 95 | body: JSON.stringify({ 96 | prompt: `You are a teacher of language ${language}, if existent, indicate the gramatic errors and why is wrong of the following sentense, please, reply in ${language} language, be brief: "${selectedText}". `, 97 | max_tokens: 4000 98 | }) 99 | }) 100 | .then(response => response.json()) 101 | .then(data => { 102 | loading.style.display = 'none'; 103 | if (data.choices && data.choices[0] && data.choices[0].text) { 104 | correction.textContent = data.choices[0].text.trim(); 105 | } else { 106 | console.error('Sorry, i cant get the correction.'); 107 | } 108 | }) 109 | .catch(error => { 110 | loading.style.display = 'none'; 111 | console.error('Erro:', error); 112 | }); 113 | } 114 | 115 | getCorrection(selectedLanguage); 116 | select.value = selectedLanguage; 117 | 118 | select.addEventListener('change', function() { 119 | let language = select.value; 120 | localStorage.setItem('selectedLanguage', language); 121 | getCorrection(language); 122 | }); 123 | 124 | container.appendChild(popup); 125 | } 126 | --------------------------------------------------------------------------------