diff --git a/README.md b/README.md index 1818fd88..c3ec183b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ChatGPT for Google -A browser extension to display ChatGPT response alongside Google Search results, supports Chrome/Edge/Firefox +A browser extension to display ChatGPT response alongside Search Engine results, supports Chrome/Edge/Firefox Buy Me A Coffee diff --git a/src/content-script/engine-match-config.mjs b/src/content-script/engine-match-config.mjs new file mode 100644 index 00000000..d493bc5b --- /dev/null +++ b/src/content-script/engine-match-config.mjs @@ -0,0 +1,71 @@ +/** + * @typedef {object} SiteConfig + * @property {string[]} inputQuery - for search box + * @property {string[]} sidebarContainerQuery - prepend child to + * @property {string[]} appendContainerQuery - if sidebarContainer not exists, append child to + */ +/** + * @type {Object.} + */ +export const config = { + google: { + inputQuery: ["input[name='q']"], + sidebarContainerQuery: ["#rhs"], + appendContainerQuery: ["#rcnt"] + }, + bing: { + inputQuery: ["textarea[name='q']"], + sidebarContainerQuery: ["#b_context"], + appendContainerQuery: [] + }, + yahoo: { + inputQuery: ["input[name='p']"], + sidebarContainerQuery: ["#right", ".Contents__inner.Contents__inner--sub"], + appendContainerQuery: ["#cols", "#contents__wrap"] + }, + duckduckgo: { + inputQuery: ["input[name='q']"], + sidebarContainerQuery: [".results--sidebar.js-results-sidebar"], + appendContainerQuery: ["#links_wrapper"] + }, + startpage: { + inputQuery: ["input[name='query']"], + sidebarContainerQuery: [".layout-web__sidebar.layout-web__sidebar--web"], + appendContainerQuery: [".layout-web__body.layout-web__body--desktop"] + }, + baidu: { + inputQuery: ["input[name='wd']"], + sidebarContainerQuery: ["#content_right"], + appendContainerQuery: ["#container"] + }, + kagi: { + inputQuery: ["input[name='q']"], + sidebarContainerQuery: [".right-content-box._0_right_sidebar"], + appendContainerQuery: ["#_0_app_content"], + }, + yandex: { + inputQuery: ["input[name='text']"], + sidebarContainerQuery: ["#search-result-aside"], + appendContainerQuery: [] + }, + naver: { + inputQuery: ["input[name='query']"], + sidebarContainerQuery: ["#sub_pack"], + appendContainerQuery: ["#content"] + }, + brave: { + inputQuery: ["input[name='q']"], + sidebarContainerQuery: ["#side-right"], + appendContainerQuery: [] + }, + searx: { + inputQuery: ["input[name='q']"], + sidebarContainerQuery: ["#sidebar_results"], + appendContainerQuery: [] + }, + ecosia: { + inputQuery: ["input[name='q']"], + sidebarContainerQuery: [".sidebar.web__sidebar"], + appendContainerQuery: ["#main"] + } +} diff --git a/src/content-script/index.mjs b/src/content-script/index.mjs index a119a10e..e4e28f14 100644 --- a/src/content-script/index.mjs +++ b/src/content-script/index.mjs @@ -1,5 +1,7 @@ import MarkdownIt from "markdown-it"; import Browser from "webextension-polyfill"; +import {getPossibleElementByQuerySelector} from "./utils.mjs" +import {config} from "./engine-match-config.mjs" async function run(question) { const markdown = new MarkdownIt(); @@ -8,12 +10,14 @@ async function run(question) { container.className = "chat-gpt-container"; container.innerHTML = '

Waiting for ChatGPT response...

'; - const siderbarContainer = document.getElementById("rhs"); + const siderbarContainer = getPossibleElementByQuerySelector(config[siteName].sidebarContainerQuery); if (siderbarContainer) { siderbarContainer.prepend(container); } else { container.classList.add("sidebar-free"); - document.getElementById("rcnt").appendChild(container); + const appendContainer = getPossibleElementByQuerySelector(config[siteName].appendContainerQuery); + if (appendContainer) + appendContainer.appendChild(container); } const port = Browser.runtime.connect(); @@ -32,7 +36,11 @@ async function run(question) { port.postMessage({ question }); } -const searchInput = document.getElementsByName("q")[0]; +const matchedSites = Object.keys(config); +const siteRegex = new RegExp(`(${matchedSites.join('|')})`); +const siteName = document.location.hostname.match(siteRegex)[0]; + +const searchInput = getPossibleElementByQuerySelector(config[siteName].inputQuery); if (searchInput && searchInput.value) { // only run on first page const startParam = new URL(location.href).searchParams.get("start") || "0"; diff --git a/src/content-script/utils.mjs b/src/content-script/utils.mjs new file mode 100644 index 00000000..73061b36 --- /dev/null +++ b/src/content-script/utils.mjs @@ -0,0 +1,8 @@ +export function getPossibleElementByQuerySelector(queryArray) { + for (const query of queryArray) { + const element = document.querySelector(query); + if (element) { + return element; + } + } +} diff --git a/src/manifest.json b/src/manifest.json index 8aecf95a..5716fede 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -15,8 +15,22 @@ }, "content_scripts": [ { - "matches": ["https://*/search*"], - "include_globs": ["*.google.*/*"], + "matches": ["https://*/*"], + "include_globs": [ + "https://*.google.*/*", + "https://kagi.*/*", + "https://*.bing.*/*", + "https://*.yahoo.*/*", + "https://*.naver.*/*", + "https://*.brave.*/*", + "https://*.ecosia.org/*", + "https://searx.be/*", + "https://www.searx.be/*", + "https://yandex.*/*", + "https://duckduckgo.*", + "https://*.startpage.*/*", + "https://*.baidu.*" + ], "js": ["content-script.js"], "css": ["github-markdown.css", "styles.css"] } diff --git a/src/manifest.v2.json b/src/manifest.v2.json index 4be92747..8d3b4a55 100644 --- a/src/manifest.v2.json +++ b/src/manifest.v2.json @@ -15,8 +15,22 @@ }, "content_scripts": [ { - "matches": ["https://*/search*"], - "include_globs": ["*.google.*/*"], + "matches": ["https://*/*"], + "include_globs": [ + "https://*.google.*/*", + "https://kagi.*/*", + "https://*.bing.*/*", + "https://*.yahoo.*/*", + "https://*.naver.*/*", + "https://*.brave.*/*", + "https://*.ecosia.org/*", + "https://searx.be/*", + "https://www.searx.be/*", + "https://yandex.*/*", + "https://duckduckgo.*", + "https://*.startpage.*/*", + "https://*.baidu.*" + ], "js": ["content-script.js"], "css": ["github-markdown.css", "styles.css"] }