Peka Car
Peka Car

Reputation: 1

Why isn't my Chrome extension for highlighting multiple keywords working?

i would need help identifying error in code for Google chrome extension I'm trying to make.

Extension should highlight multiple keywords in different color of choice on active url /tab.

Since i need this for sensitive data I'm reluctant to use similar existing extensions and since im total amateur with coding i used ChatGPT to code some basics.

At the end UI that looks decent but problem is that extension does not highlight anything on page.

Code looks ok, but i cant find the reason why extension does not work. Any help or insight is appreciated.

Here are all files :

Manifest.json:
{
    "manifest_version": 3,
    "name": "Search Word Highlighter",
    "version": "1.0",
    "description": "Chrome extension to find and highlight multiple search words on the current URL.",
    "icons": {
      "16": "icon16.png",
      "48": "icon48.png",
      "128": "icon128.png"
    },
    "action": {
      "default_popup": "popup.html",
      "default_icon": {
        "16": "icon16.png",
        "48": "icon48.png",
        "128": "icon128.png"
      }
    },
    "permissions": [
      "activeTab",
      "storage",
      "scripting"
    ],
    "host_permissions": [
      "<all_urls>"
    ],
    "content_scripts": [
        {
            "matches": ["http://*/*", "https://*/*"],
            "js": ["content.js"],
            "run_at": "document_end"
          }
      ],
      
    "background": {
      "service_worker": "background.js"
    }
  }
 
popup.html:
<!DOCTYPE html>
<html>
<head>
  <title>Highlight multi</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 10px;
    }
    
    form {
      display: flex;
      flex-direction: column;
      margin-bottom: 10px;
    }
    
    .keyword-container {
      display: flex;
      align-items: center;
      margin-bottom: 10px;
    }
    
    input[type="text"] {
      margin-right: 10px;
    }
    
    input[type="color"] {
      padding: 0;
      height: 24px;
      width: 24px;
      border: none;
      border-radius: 50%;
      cursor: pointer;
    }
    
    button {
      margin-top: 10px;
    }
    
    ul {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    
    li {
      margin-bottom: 5px;
    }
  </style>
</head>
<body>
  <form id="add-keyword-form">
    <div class="keyword-container">
      <input type="text" class="keyword-input" placeholder="Enter a keyword">
      <input type="color" class="color-input" value="#ff0000">
    </div>
    <button type="button" id="add-keyword-button">Add Keyword</button>
    <button type="button" id="search-button">Search</button>
  </form>
  
  <ul id="keywords-list"></ul>
  
  <script src="popup.js"></script>
</body>
</html>

popup.js:
document.addEventListener("DOMContentLoaded", function () {
    const form = document.getElementById("add-keyword-form");
    const addKeywordButton = document.getElementById("add-keyword-button");
    const searchButton = document.getElementById("search-button");
    const keywordsList = document.getElementById("keywords-list");
  
    let keywordIndex = 1;
  
    // Handle add keyword button click
    addKeywordButton.addEventListener("click", function () {
      addKeywordField();
    });
  
    // Handle search button click to trigger the search function
    searchButton.addEventListener("click", function () {
      const keywordInputs = document.querySelectorAll(".keyword-input");
      const colorInputs = document.querySelectorAll(".color-input");
      const keywords = [];
      for (let i = 0; i < keywordInputs.length; i++) {
        const keyword = keywordInputs[i].value.trim();
        const color = colorInputs[i].value;
        if (keyword && color) {
          keywords.push({ keyword, color });
        }
      }
      if (keywords.length > 0 || keywordInputs[0].value.trim() !== "") {
        searchKeywords(keywords);
      }
    });
  
    // Function to add a new keyword field
    function addKeywordField() {
      const container = document.createElement("div");
      container.classList.add("keyword-container");
  
      const keywordInput = document.createElement("input");
      keywordInput.setAttribute("type", "text");
      keywordInput.setAttribute("placeholder", "Enter a keyword");
      keywordInput.classList.add("keyword-input");
  
      const colorInput = document.createElement("input");
      colorInput.setAttribute("type", "color");
      colorInput.setAttribute("value", "#ff0000");
      colorInput.classList.add("color-input");
  
      container.appendChild(keywordInput);
      container.appendChild(colorInput);
      form.insertBefore(container, addKeywordButton);
    }
  
    // Function to search the keywords
    function searchKeywords(keywords) {
      // Send a message to the content script to highlight the keywords on the page
      chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.tabs.sendMessage(tabs[0].id, { action: "highlightKeyWords", keywords: keywords }, function (response) {
          // Handle the response if needed
        });
      });
  
      // Display the keywords in the list
      keywordsList.innerHTML = "";
      keywords.forEach(keyword => {
        const li = document.createElement("li");
        li.textContent = keyword.keyword;
        li.style.color = keyword.color;
        keywordsList.appendChild(li);
      });
    }
  });
  
content.js:
// Function to highlight all occurrences of a keyword
function highlightKeyword(keyword, color) {
  const regex = new RegExp(`\\b${keyword}\\b`, "gi");
  const matches = document.body.innerText.match(regex);
  if (matches) {
    for (const match of matches) {
      const span = document.createElement("span");
      span.style.backgroundColor = color;
      span.style.color = "yellow";
      span.textContent = match;

      const replacedHtml = document.body.innerHTML.replace(new RegExp(match, "g"), span.outerHTML);
      document.body.innerHTML = replacedHtml;
    }
  }
}

// Function to search the keywords and highlight them on the page
function searchKeywords(keywords) {
  keywords.forEach(keyword => {
    highlightKeyword(keyword.keyword, keyword.color);
  });
}

// Listen for messages from the extension popup
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
  if (message.action === "highlightWords") {
    const keywords = message.keywords;
    searchKeywords(keywords);
  }
});

background.js:
chrome.action.onClicked.addListener((tab) => {
  chrome.scripting.executeScript({
    target: { tabId: tab.id },
    files: ["content.js"]
  });
});

chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
  if (message.action === "getKeywords") {
    chrome.storage.local.get("keywords", function (data) {
      sendResponse({ keywords: data.keywords });
    });
    return true; // Needed to indicate that the response will be sent asynchronously
  } else if (message.action === "saveKeywords") {
    chrome.storage.local.set({ keywords: message.keywords });
  } else if (message.action === "highlightKeywords") {
    // Forward the message to the content script
    chrome.tabs.sendMessage(sender.tab.id, message);
  }
});

chrome.runtime.onInstalled.addListener(function () {
  // Check if persistent storage is available and request it if necessary
  if (navigator.storage && navigator.storage.persist) {
    navigator.storage.persist().then((persistent) => {
      if (persistent) {
        console.log("Persistent storage granted.");
      } else {
        console.log("Persistent storage not granted.");
      }
    });
  }
});

css:
body {
    font-family: Arial, sans-serif;
    margin: 20px;
  }
  
  h1 {
    font-size: 18px;
    margin-bottom: 10px;
  }
  
  form {
    margin-bottom: 20px;
  }
  
  input[type="text"] {
    width: 200px;
  }
  
  
  button {
    padding: 6px 12px;
    background-color: #007bff;
    color: #fff;
    border: none;
    cursor: pointer;
  }
  

Thank you for help

I found some explanations for previous manifest version 2 here but that does not help. Chat GPT cant detect any errors

Upvotes: -1

Views: 421

Answers (1)

Sergey92zp
Sergey92zp

Reputation: 589

If chatGPT could read docs, it would know that "The action.onClicked event will not be dispatched if the extension action has specified a popup to show on click on the current tab." You need delete invokation from background.js then add this

chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    chrome.scripting.executeScript({
      target: { tabId: tabs[0].id },
      files: ["content.js"],
    });
  });

after let keywordIndex = 1; in popup.js

And JS is actually case sensitive language, so you need to change action to "highlightKeywords" in exactly this case in all js files. For example in your content.js it is "highlightWords" without Key and with capital W, and of course such action not exist anywhere else in code.

Upvotes: 1

Related Questions