Build chrome extensions that allow interaction with browser contenttags/v0.16.0
| @@ -0,0 +1,45 @@ | |||
| # Chrome Extension | |||
| chrome-extension/ | |||
| │ | |||
| ├── manifest.json # Main configuration file for the extension | |||
| ├── popup.html # Main user interface of the extension | |||
| ├── popup.js # Script for the main interface | |||
| ├── background.js # Background script for the extension | |||
| ├── content.js # Script to interact with web pages | |||
| ├── styles/ | |||
| │ └── popup.css # CSS file for the popup | |||
| ├── icons/ | |||
| │ ├── icon16.png # 16x16 pixel icon | |||
| │ ├── icon48.png # 48x48 pixel icon | |||
| │ └── icon128.png # 128x128 pixel icon | |||
| ├── assets/ | |||
| │ └── ... # Directory for other assets (images, fonts, etc.) | |||
| ├── scripts/ | |||
| │ ├── utils.js # File containing utility functions | |||
| │ └── api.js # File containing API call logic | |||
| └── README.md # Instructions for using and installing the extension | |||
| # Installation | |||
| 1. Open chrome://extensions/. | |||
| 2. Enable Developer mode. | |||
| 3. Click Load unpacked and select the project directory. | |||
| # Features | |||
| 1. Interact with web pages. | |||
| 2. Run in the background to handle logic. | |||
| # Usage | |||
| - Click the extension icon in the toolbar. | |||
| - Follow the instructions in the interface. | |||
| # Additional Notes | |||
| - **manifest.json**: This file is crucial as it defines the extension's metadata, permissions, and entry points. | |||
| - **background.js**: This script runs independently of any web page and can perform tasks such as listening for browser events, making network requests, and storing data. | |||
| - **content.js**: This script injects code into web pages to manipulate the DOM, modify styles, or communicate with the background script. | |||
| - **popup.html/popup.js**: These files create the popup that appears when the user clicks the extension icon. | |||
| icons: These icons are used to represent the extension in the browser's UI. | |||
| More Detailed Explanation | |||
| - **manifest.json**: Specifies the extension's name, version, permissions, and other details. It also defines the entry points for the background script, content scripts, and the popup. | |||
| - **background.js**: Handles tasks that need to run continuously, such as syncing data, listening for browser events, or controlling the extension's behavior. | |||
| - **content.js**: Interacts directly with the web page's DOM, allowing you to modify the content, style, or behavior of the page. | |||
| - **popup.html/popup.js**: Creates a user interface that allows users to interact with the extension. | |||
| Other files: These files can contain additional scripts, styles, or assets that are used by the extension. | |||
| @@ -0,0 +1,29 @@ | |||
| <svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M3.43265 20.7677C4.15835 21.5062 4.15834 22.7035 3.43262 23.4419L3.39546 23.4797C2.66974 24.2182 1.49312 24.2182 0.767417 23.4797C0.0417107 22.7412 0.0417219 21.544 0.767442 20.8055L0.804608 20.7677C1.53033 20.0292 2.70694 20.0293 3.43265 20.7677Z" | |||
| fill="#B2DDFF" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M12.1689 21.3375C12.8933 22.0773 12.8912 23.2746 12.1641 24.0117L7.01662 29.2307C6.2896 29.9678 5.11299 29.9657 4.38859 29.2259C3.66419 28.4861 3.66632 27.2888 4.39334 26.5517L9.54085 21.3327C10.2679 20.5956 11.4445 20.5977 12.1689 21.3375Z" | |||
| fill="#53B1FD" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M19.1551 30.3217C19.7244 29.4528 20.8781 29.218 21.7321 29.7973L21.8436 29.8729C22.6975 30.4522 22.9283 31.6262 22.359 32.4952C21.7897 33.3641 20.6359 33.5989 19.782 33.0196L19.6705 32.944C18.8165 32.3647 18.5858 31.1907 19.1551 30.3217Z" | |||
| fill="#B2DDFF" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M31.4184 20.6544C32.1441 21.3929 32.1441 22.5902 31.4184 23.3286L28.8911 25.9003C28.1654 26.6388 26.9887 26.6388 26.263 25.9003C25.5373 25.1619 25.5373 23.9646 26.263 23.2261L28.7903 20.6544C29.516 19.916 30.6927 19.916 31.4184 20.6544Z" | |||
| fill="#53B1FD" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M31.4557 11.1427C32.1814 11.8812 32.1814 13.0785 31.4557 13.8169L12.7797 32.8209C12.054 33.5594 10.8774 33.5594 10.1517 32.8209C9.42599 32.0825 9.42599 30.8852 10.1517 30.1467L28.8277 11.1427C29.5534 10.4043 30.73 10.4043 31.4557 11.1427Z" | |||
| fill="#1570EF" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M27.925 5.29994C28.6508 6.0384 28.6508 7.23568 27.925 7.97414L17.184 18.9038C16.4583 19.6423 15.2817 19.6423 14.556 18.9038C13.8303 18.1653 13.8303 16.9681 14.556 16.2296L25.297 5.29994C26.0227 4.56148 27.1993 4.56148 27.925 5.29994Z" | |||
| fill="#1570EF" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M22.256 1.59299C22.9822 2.33095 22.983 3.52823 22.2578 4.26718L8.45055 18.3358C7.72533 19.0748 6.54871 19.0756 5.82251 18.3376C5.09631 17.5996 5.09552 16.4024 5.82075 15.6634L19.6279 1.59478C20.3532 0.855827 21.5298 0.855022 22.256 1.59299Z" | |||
| fill="#1570EF" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M8.58225 6.09619C9.30671 6.83592 9.30469 8.0332 8.57772 8.77038L3.17006 14.2541C2.4431 14.9913 1.26649 14.9893 0.542025 14.2495C-0.182438 13.5098 -0.180413 12.3125 0.546548 11.5753L5.95421 6.09159C6.68117 5.3544 7.85778 5.35646 8.58225 6.09619Z" | |||
| fill="#53B1FD" /> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" | |||
| d="M11.893 0.624023C12.9193 0.624023 13.7513 1.47063 13.7513 2.51497V2.70406C13.7513 3.7484 12.9193 4.59501 11.893 4.59501C10.8667 4.59501 10.0347 3.7484 10.0347 2.70406V2.51497C10.0347 1.47063 10.8667 0.624023 11.893 0.624023Z" | |||
| fill="#B2DDFF" /> | |||
| </svg> | |||
| @@ -0,0 +1,17 @@ | |||
| chrome.runtime.onInstalled.addListener(() => { | |||
| console.log("Tiện ích đã được cài đặt!"); | |||
| }); | |||
| chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { | |||
| if (message.action === "PAGE_INFO") { | |||
| console.log( message); | |||
| chrome.storage.local.set({ pageInfo: message }, () => { | |||
| console.log("Page info saved to local storage."); | |||
| }); | |||
| // Send a response to the content script | |||
| sendResponse({ status: "success", message: "Page info received and processed." }); | |||
| } | |||
| }); | |||
| @@ -0,0 +1,68 @@ | |||
| (function () { | |||
| const extractElementData = (el) => { | |||
| const tag = el.tagName.toLowerCase(); | |||
| if ( | |||
| tag === "input" && | |||
| el.name !== "DXScript" && | |||
| el.name !== "DXMVCEditorsValues" && | |||
| el.name !== "DXCss" | |||
| ) { | |||
| return { | |||
| type: "input", | |||
| name: el.name, | |||
| value: | |||
| el.type === "checkbox" || el.type === "radio" | |||
| ? el.checked | |||
| ? el.value | |||
| : null | |||
| : el.value, | |||
| }; | |||
| } else if (tag === "select") { | |||
| const selectedOption = el.querySelector("option:checked"); | |||
| return { | |||
| type: "select", | |||
| name: el.name, | |||
| value: selectedOption ? selectedOption.value : null, | |||
| }; | |||
| } else if (tag.startsWith("h") && el.textContent.trim()) { | |||
| return { type: "header", tag, content: el.textContent.trim() }; | |||
| } else if ( | |||
| ["label", "span", "p", "b", "strong"].includes(tag) && | |||
| el.textContent.trim() | |||
| ) { | |||
| return { type: tag, content: el.textContent.trim() }; | |||
| } | |||
| }; | |||
| const getElementValues = (els) => | |||
| Array.from(els).map(extractElementData).filter(Boolean); | |||
| const getIframeInputValues = (iframe) => { | |||
| try { | |||
| const iframeDoc = iframe.contentWindow.document; | |||
| return getElementValues( | |||
| iframeDoc.querySelectorAll("input, select, header, label, span, p") | |||
| ); | |||
| } catch (e) { | |||
| console.error("Can't access iframe:", e); | |||
| return []; | |||
| } | |||
| }; | |||
| const inputValues = getElementValues( | |||
| document.querySelectorAll("input, select, header, label, span, p") | |||
| ); | |||
| const iframeInputValues = Array.from(document.querySelectorAll("iframe")).map( | |||
| getIframeInputValues | |||
| ); | |||
| return ` | |||
| ## input values\n | |||
| \`\`\`json\n | |||
| ${JSON.stringify(inputValues)}\n | |||
| \`\`\`\n | |||
| ## iframe input values\n | |||
| \`\`\`json\n | |||
| ${JSON.stringify(iframeInputValues)}\n | |||
| \`\`\``; | |||
| })(); | |||
| @@ -0,0 +1,34 @@ | |||
| { | |||
| "manifest_version": 3, | |||
| "name": "Ragflow Extension", | |||
| "description": "Ragflow for Chrome", | |||
| "version": "1.0", | |||
| "options_page": "options.html", | |||
| "permissions": ["activeTab", "scripting", "storage"], | |||
| "background": { | |||
| "service_worker": "background.js" | |||
| }, | |||
| "action": { | |||
| "default_popup": "popup.html", | |||
| "default_icon": { | |||
| "16": "icons/icon-16x16.png", | |||
| "48": "icons/icon-48x48.png", | |||
| "128": "icons/icon-128x128.png" | |||
| } | |||
| }, | |||
| "content_scripts": [ | |||
| { | |||
| "matches": ["<all_urls>"], | |||
| "js": ["content.js"], | |||
| "css": ["styles/popup.css"] | |||
| } | |||
| ], | |||
| "icons": { | |||
| "16": "icons/icon-16x16.png", | |||
| "48": "icons/icon-48x48.png", | |||
| "128": "icons/icon-128x128.png" | |||
| } | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8" /> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
| <title>RagFlow option</title> | |||
| <link rel="stylesheet" href="styles/options.css" /> | |||
| </head> | |||
| <body id="ragflow"> | |||
| <div id="form-config"> | |||
| <div class="header"> | |||
| <img src="assets/logo-with-text.png" alt="Logo" class="logo" /> | |||
| </div> | |||
| <div class="content"> | |||
| <label for="base-url">Base URL:</label> | |||
| <input type="text" id="base-url" placeholder="Enter base URL" /> | |||
| <label for="from">From:</label> | |||
| <select id="from"> | |||
| <option selected value="agent">agent</option> | |||
| <option value="chat">chat</option> | |||
| </select> | |||
| <label for="auth">Auth:</label> | |||
| <input type="text" id="auth" placeholder="Enter auth" /> | |||
| <label for="shared-id">Shared ID:</label> | |||
| <input type="text" id="shared-id" placeholder="Enter shared ID" /> | |||
| <button id="save-config">🛖</button> | |||
| </div> | |||
| </div> | |||
| <script src="options.js"></script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,36 @@ | |||
| document.addEventListener("DOMContentLoaded", () => { | |||
| chrome.storage.sync.get(["baseURL", "from", "auth", "sharedID"], (result) => { | |||
| if (result.baseURL) { | |||
| document.getElementById("base-url").value = result.baseURL; | |||
| } | |||
| if (result.from) { | |||
| document.getElementById("from").value = result.from; | |||
| } | |||
| if (result.auth) { | |||
| document.getElementById("auth").value = result.auth; | |||
| } | |||
| if (result.sharedID) { | |||
| document.getElementById("shared-id").value = result.sharedID; | |||
| } | |||
| }); | |||
| document.getElementById("save-config").addEventListener("click", () => { | |||
| const baseURL = document.getElementById("base-url").value; | |||
| const from = document.getElementById("from").value; | |||
| const auth = document.getElementById("auth").value; | |||
| const sharedID = document.getElementById("shared-id").value; | |||
| chrome.storage.sync.set( | |||
| { | |||
| baseURL: baseURL, | |||
| from: from, | |||
| auth: auth, | |||
| sharedID: sharedID, | |||
| }, | |||
| () => { | |||
| alert("Successfully saved"); | |||
| } | |||
| ); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,20 @@ | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <meta charset="utf-8" /> | |||
| <meta name="viewport" | |||
| content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" /> | |||
| <title>RAGFLOW</title> | |||
| <link rel="stylesheet" href="styles/popup.css" /> | |||
| </head> | |||
| <body id="ragflow"> | |||
| <div class="window"> | |||
| <textarea id="getHtml"></textarea> | |||
| <iframe src="" style="width: 100%; height: 100%; min-height: 600px" frameborder="0"></iframe> | |||
| </div> | |||
| <script src="popup.js"></script> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,24 @@ | |||
| document.addEventListener("DOMContentLoaded", () => { | |||
| chrome.storage.sync.get(["baseURL", "from", "auth", "sharedID"], (result) => { | |||
| if (result.baseURL && result.sharedID && result.from && result.auth) { | |||
| const iframeSrc = `${result.baseURL}chat/share?shared_id=${result.sharedID}&from=${result.from}&auth=${result.auth}`; | |||
| const iframe = document.querySelector("iframe"); | |||
| iframe.src = iframeSrc; | |||
| } | |||
| }); | |||
| chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { | |||
| chrome.scripting.executeScript( | |||
| { | |||
| target: { tabId: tabs[0].id }, | |||
| files: ["content.js"], | |||
| }, | |||
| (results) => { | |||
| if (results && results[0]) { | |||
| const getHtml = document.getElementById("getHtml"); | |||
| getHtml.value = results[0].result; | |||
| } | |||
| } | |||
| ); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,91 @@ | |||
| #ragflow { | |||
| font-family: "Segoe UI", Arial, sans-serif; | |||
| margin: 0; | |||
| padding: 0; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| height: 600px; | |||
| } | |||
| #ragflow .window { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| flex: 1; | |||
| overflow: hidden; | |||
| } | |||
| #ragflow #form-config { | |||
| background-color: #fff; | |||
| box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| overflow: hidden; | |||
| } | |||
| #ragflow .header { | |||
| background-color: #fff; | |||
| padding: 4px; | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| flex-direction: row; | |||
| } | |||
| #ragflow .header .title { | |||
| font-size: 16px; | |||
| } | |||
| #ragflow .header .logo { | |||
| width: 100px; /* Adjust size as needed */ | |||
| height: auto; | |||
| margin-right: 10px; | |||
| } | |||
| #ragflow .content { | |||
| padding: 20px; | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| } | |||
| #ragflow label { | |||
| font-weight: bold; | |||
| margin-bottom: 5px; | |||
| } | |||
| #ragflow input, | |||
| #ragflow select { | |||
| width: 100%; | |||
| padding: 8px; | |||
| margin-bottom: 15px; | |||
| border: 1px solid #ccc; | |||
| border-radius: 5px; | |||
| box-sizing: border-box; | |||
| } | |||
| #ragflow button { | |||
| background-color: #0078d4; | |||
| color: #fff; | |||
| padding: 10px; | |||
| border: none; | |||
| border-radius: 5px; | |||
| cursor: pointer; | |||
| font-size: 14px; | |||
| } | |||
| #ragflow button:hover { | |||
| background-color: #005bb5; | |||
| } | |||
| #ragflow #config-button { | |||
| display: flex; | |||
| position: absolute; | |||
| top: 2px; | |||
| right: 2px; | |||
| font-size: 22px; | |||
| } | |||
| #ragflow #config-button:hover { | |||
| cursor: pointer; | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| #ragflow { | |||
| font-family: "Segoe UI", Arial, sans-serif; | |||
| margin: 0; | |||
| padding: 0; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| width: 320px; | |||
| } | |||
| #ragflow .window { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| flex: 1; | |||
| overflow: hidden; | |||
| } | |||
| #ragflow #output { | |||
| position: absolute; | |||
| } | |||