diff --git a/chrome-extension/background.js b/chrome-extension/background.js
new file mode 100644
index 0000000..174ec31
--- /dev/null
+++ b/chrome-extension/background.js
@@ -0,0 +1,24 @@
+chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
+ if (message.action === "injectWebMarker") {
+ const { code } = message;
+ chrome.scripting.executeScript(
+ {
+ target: { tabId: sender.tab.id },
+ world: "MAIN",
+ func: new Function(code),
+ },
+ () => {
+ if (chrome.runtime.lastError) {
+ console.error(chrome.runtime.lastError);
+ sendResponse({
+ success: false,
+ error: chrome.runtime.lastError.message,
+ });
+ } else {
+ sendResponse({ success: true });
+ }
+ }
+ );
+ return true;
+ }
+});
diff --git a/chrome-extension/contentScript.js b/chrome-extension/contentScript.js
new file mode 100644
index 0000000..7ad803f
--- /dev/null
+++ b/chrome-extension/contentScript.js
@@ -0,0 +1,38 @@
+chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
+ const { action, options } = message;
+
+ if (action === "injectWebMarker") {
+ sendResponse({ success: true });
+ return;
+ }
+
+ const executeAction = () => {
+ if (action === "markPage") {
+ const markedElements = WebMarker.mark(options);
+ sendResponse({ markedElements });
+ } else if (action === "unmarkPage") {
+ WebMarker.unmark();
+ sendResponse({ success: true });
+ } else if (action === "refresh") {
+ if (WebMarker.isMarked()) {
+ WebMarker.unmark();
+ }
+ const markedElements = WebMarker.mark(options);
+ sendResponse({ markedElements });
+ }
+ };
+
+ if (WebMarker && WebMarker.mark) {
+ executeAction();
+ } else {
+ // Wait for WebMarker to load
+ const interval = setInterval(() => {
+ if (WebMarker && WebMarker.mark) {
+ clearInterval(interval);
+ executeAction();
+ }
+ }, 50);
+ }
+
+ return true;
+});
diff --git a/chrome-extension/devtools.html b/chrome-extension/devtools.html
new file mode 100644
index 0000000..07db577
--- /dev/null
+++ b/chrome-extension/devtools.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/chrome-extension/devtools.js b/chrome-extension/devtools.js
new file mode 100644
index 0000000..c5a6ace
--- /dev/null
+++ b/chrome-extension/devtools.js
@@ -0,0 +1,8 @@
+chrome.devtools.panels.create(
+ "WebMarker",
+ "icon.png",
+ "panel.html",
+ function (panel) {
+ // Panel created
+ }
+);
diff --git a/chrome-extension/icon.png b/chrome-extension/icon.png
new file mode 100644
index 0000000..e1cbb17
Binary files /dev/null and b/chrome-extension/icon.png differ
diff --git a/chrome-extension/manifest.json b/chrome-extension/manifest.json
new file mode 100644
index 0000000..caf848e
--- /dev/null
+++ b/chrome-extension/manifest.json
@@ -0,0 +1,28 @@
+{
+ "manifest_version": 3,
+ "name": "WebMarker Extension",
+ "version": "1.0",
+ "description": "Adds visual markings to web pages using WebMarker.",
+ "permissions": ["scripting", "activeTab"],
+ "host_permissions": [""],
+ "devtools_page": "devtools.html",
+ "content_scripts": [
+ {
+ "matches": [""],
+ "js": ["contentScript.js", "dist/main.js"],
+ "run_at": "document_end"
+ }
+ ],
+ "web_accessible_resources": [
+ {
+ "resources": ["dist/main.js"],
+ "matches": [""]
+ }
+ ],
+ "icons": {
+ "128": "icon.png"
+ },
+ "background": {
+ "service_worker": "background.js"
+ }
+}
diff --git a/chrome-extension/panel.html b/chrome-extension/panel.html
new file mode 100644
index 0000000..b089999
--- /dev/null
+++ b/chrome-extension/panel.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chrome-extension/panel.js b/chrome-extension/panel.js
new file mode 100644
index 0000000..d2b2bcc
--- /dev/null
+++ b/chrome-extension/panel.js
@@ -0,0 +1,59 @@
+document.addEventListener("DOMContentLoaded", () => {
+ const markPageCheckbox = document.getElementById("markPage");
+ const selectorInput = document.getElementById("selector");
+ const markPlacementSelect = document.getElementById("markPlacement");
+ const showBoundingBoxesCheckbox =
+ document.getElementById("showBoundingBoxes");
+ const viewPortOnlyCheckbox = document.getElementById("viewPortOnly");
+ const copyOptionsButton = document.getElementById("copyOptions");
+ const refreshButton = document.getElementById("refresh");
+ const outputDiv = document.getElementById("output");
+
+ const getCurrentOptions = () => {
+ return {
+ selector: selectorInput.value,
+ markPlacement: markPlacementSelect.value,
+ showBoundingBoxes: showBoundingBoxesCheckbox.checked,
+ viewPortOnly: viewPortOnlyCheckbox.checked,
+ // TODO: Add new options
+ };
+ };
+
+ const sendMessageToContentScript = (action) => {
+ const options = getCurrentOptions();
+ chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
+ if (tabs.length === 0) return;
+ chrome.tabs.sendMessage(tabs[0].id, { action, options }, (response) => {
+ if (chrome.runtime.lastError) {
+ outputDiv.textContent = "Error: " + chrome.runtime.lastError.message;
+ return;
+ }
+ if (response && response.markedElements) {
+ outputDiv.textContent = JSON.stringify(
+ response.markedElements,
+ null,
+ 2
+ );
+ } else if (response && response.success) {
+ outputDiv.textContent = "Unmarked successfully.";
+ }
+ });
+ });
+ };
+
+ markPageCheckbox.addEventListener("change", () => {
+ const action = markPageCheckbox.checked ? "markPage" : "unmarkPage";
+ sendMessageToContentScript(action);
+ });
+
+ copyOptionsButton.addEventListener("click", () => {
+ const options = getCurrentOptions();
+ navigator.clipboard.writeText(JSON.stringify(options, null, 2)).then(() => {
+ alert("Options copied to clipboard!");
+ });
+ });
+
+ refreshButton.addEventListener("click", () => {
+ sendMessageToContentScript("refresh");
+ });
+});