Reputation: 1
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
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