DEV Community

Cover image for How I create my first Chrome extension with Github Copilot
Doan Trong Nam
Doan Trong Nam

Posted on

How I create my first Chrome extension with Github Copilot

My story is that I'm learning Japanese on a website called Dungmori.com, and I study new vocabulary on the Quizlet website. I encountered difficulties in copying vocabulary from Dungmori to Quizlet because I had to copy each word one by one. Previously, I used to copy sets of vocabulary created by other Quizlet users, then manually checked for any missing words compared to Dungmori and added them myself. This method consumed a lot of my time. Later, I discovered that Quizlet allows importing multiple words with various formatting options. For example, two words separated by a comma, tab, space, or two cards separated by line breaks \n, \r\n, ...

Quizlet Set import UI

Meanwhile, on Dungmori, they present new words using a standard <table> tag, which allows me to easily use JavaScript to transform the text within this table into a text string for importing into Quizlet.

Dungmori Vocab table

But do I have to search for the code, open DevTools, and paste the code into the console tab every time I want to fetch vocabulary from this table? This question led me to consider creating an extension to install on the browser. However, I've never written an extension before, I only know HTML, CSS, and JavaScript. Perhaps GitHub Copilot can help me with that, right?

So f**king tired developer

So, I began asking Copilot how to create an extension from scratch. The answer was that I needed to create a file called manifest.json to store the important configurations of the extension, a file named popup.html to design the interface for the extension, another file called popup.js to write the logic, and a file named content.js to interact with the DOM elements of the website. Copilot also guided me on how to import a code folder into the browser by enabling Developer mode in the extension settings, then selecting the code folder and reloading the browser.

// manifest.json
{
  "manifest_version": 2,
  "name": "My First Chrome Extension",
  "version": "1.0",
  "description": "A simple Chrome extension",
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": ["activeTab"],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode
<!-- popup.html -->
<!DOCTYPE html>
<html>
  <body>
    <h1>Hello, this is my first Chrome extension!</h1>
    <script src="popup.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

I started writing the logic into the content.js file to convert the text in the table into a string that can be imported into Quizlet and then copied to the clipboard. I won't delve much into this part because it involves basic DOM operations. Afterward, I ran a test, and voila, the logic ran as soon as the web page loaded. However, I wanted to trigger it by clicking a button in the extension popup. That way, it would require more steps to use, but it would be cooler ¯_(ツ)_/¯. Why not?
Then, I turned to Copilot again and received the answer that this configuration is in the manifest.json file.

"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
Enter fullscreen mode Exit fullscreen mode

The solution? Delete that section of the config, and manually trigger it using the chrome.scripting.executeScript() method

chrome.tabs.query({active: true, currentWindow: true}, 
    function(tabs) {
        chrome.scripting.executeScript({
            target: {tabId: tabs[0].id},
            files: ['content.js']
        }).then(() => {
            console.log('Injected the content script.');
        }).catch(err => console.error(err));
    });
Enter fullscreen mode Exit fullscreen mode

Yeah, and now the content.js file can be triggered when I click the button in the extension popup, but the copy to clipboard function isn't working as before. Once again, the almighty Copilot came to my rescue, providing the answer that:

The error "Document is not focused" occurs because the document of the background page or popup loses focus when you switch to the content page, and the Clipboard API requires the document to be focused to write to the clipboard.

And the solution is that I need to send the text that needs to be copied from the content.js file to the popup.js file using a method that I'm not sure about, but the idea seems similar to a pub/sub mechanism.

// content.js
chrome.runtime.sendMessage({type: "copy", text: normalizedRows.join("\r\n")});

// background.js or popup.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.type === "copy") {
        navigator.clipboard.writeText(request.text).then(function() {
            console.log('Text copied to clipboard');
        }).catch(function(err) {
            console.error('Could not copy text: ', err);
        });
    }
});
Enter fullscreen mode Exit fullscreen mode

BOOOOM! THE RESULT IS HERE!
Result

Now, I can copy vocabulary from Dungmori into the clipboard with just one click. Thanks to Copilot, it took me less than an hour to create this extension. Imagine if I had to search Google to do this; I would have to open a billion tabs every time an issue arises. But with Copilot, I just stay put in my VS Code window. Previously, I tried with ChatGPT and Gemini, but the output didn't come close to this.

100000000000000 tabs
Above is not some high-tech tech sharing article; it's just my simple story and fun experience with Copilot. Also, thanks to Dall-E for helping me create illustrations, and ChatGPT for making my English translations sound less like a robot. Peace, I'm out.

GitLab Repository: https://gitlab.com/1337NamNori/copy-vocab-extension

Top comments (0)