URL Modifier for Search Engines

Modify (Redirect) URL links in search engines results to alternative frontends or for other purposes

当前为 2024-02-14 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name URL Modifier for Search Engines
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.5.5
  5. // @description Modify (Redirect) URL links in search engines results to alternative frontends or for other purposes
  6. // @author Domenic
  7.  
  8. // @match *://www.google.com/search?*
  9. // @match *://www.google.ad/search?*
  10. // @match *://www.google.ae/search?*
  11. // @match *://www.google.com.af/search?*
  12. // @match *://www.google.com.ag/search?*
  13. // @match *://www.google.al/search?*
  14. // @match *://www.google.am/search?*
  15. // @match *://www.google.co.ao/search?*
  16. // @match *://www.google.com.ar/search?*
  17. // @match *://www.google.as/search?*
  18. // @match *://www.google.at/search?*
  19. // @match *://www.google.com.au/search?*
  20. // @match *://www.google.az/search?*
  21. // @match *://www.google.ba/search?*
  22. // @match *://www.google.com.bd/search?*
  23. // @match *://www.google.be/search?*
  24. // @match *://www.google.bf/search?*
  25. // @match *://www.google.bg/search?*
  26. // @match *://www.google.com.bh/search?*
  27. // @match *://www.google.bi/search?*
  28. // @match *://www.google.bj/search?*
  29. // @match *://www.google.com.bn/search?*
  30. // @match *://www.google.com.bo/search?*
  31. // @match *://www.google.com.br/search?*
  32. // @match *://www.google.bs/search?*
  33. // @match *://www.google.bt/search?*
  34. // @match *://www.google.co.bw/search?*
  35. // @match *://www.google.by/search?*
  36. // @match *://www.google.com.bz/search?*
  37. // @match *://www.google.ca/search?*
  38. // @match *://www.google.cd/search?*
  39. // @match *://www.google.cf/search?*
  40. // @match *://www.google.cg/search?*
  41. // @match *://www.google.ch/search?*
  42. // @match *://www.google.ci/search?*
  43. // @match *://www.google.co.ck/search?*
  44. // @match *://www.google.cl/search?*
  45. // @match *://www.google.cm/search?*
  46. // @match *://www.google.cn/search?*
  47. // @match *://www.google.com.co/search?*
  48. // @match *://www.google.co.cr/search?*
  49. // @match *://www.google.com.cu/search?*
  50. // @match *://www.google.cv/search?*
  51. // @match *://www.google.com.cy/search?*
  52. // @match *://www.google.cz/search?*
  53. // @match *://www.google.de/search?*
  54. // @match *://www.google.dj/search?*
  55. // @match *://www.google.dk/search?*
  56. // @match *://www.google.dm/search?*
  57. // @match *://www.google.com.do/search?*
  58. // @match *://www.google.dz/search?*
  59. // @match *://www.google.com.ec/search?*
  60. // @match *://www.google.ee/search?*
  61. // @match *://www.google.com.eg/search?*
  62. // @match *://www.google.es/search?*
  63. // @match *://www.google.com.et/search?*
  64. // @match *://www.google.fi/search?*
  65. // @match *://www.google.com.fj/search?*
  66. // @match *://www.google.fm/search?*
  67. // @match *://www.google.fr/search?*
  68. // @match *://www.google.ga/search?*
  69. // @match *://www.google.ge/search?*
  70. // @match *://www.google.gg/search?*
  71. // @match *://www.google.com.gh/search?*
  72. // @match *://www.google.com.gi/search?*
  73. // @match *://www.google.gl/search?*
  74. // @match *://www.google.gm/search?*
  75. // @match *://www.google.gr/search?*
  76. // @match *://www.google.com.gt/search?*
  77. // @match *://www.google.gy/search?*
  78. // @match *://www.google.com.hk/search?*
  79. // @match *://www.google.hn/search?*
  80. // @match *://www.google.hr/search?*
  81. // @match *://www.google.ht/search?*
  82. // @match *://www.google.hu/search?*
  83. // @match *://www.google.co.id/search?*
  84. // @match *://www.google.ie/search?*
  85. // @match *://www.google.co.il/search?*
  86. // @match *://www.google.im/search?*
  87. // @match *://www.google.co.in/search?*
  88. // @match *://www.google.iq/search?*
  89. // @match *://www.google.is/search?*
  90. // @match *://www.google.it/search?*
  91. // @match *://www.google.je/search?*
  92. // @match *://www.google.com.jm/search?*
  93. // @match *://www.google.jo/search?*
  94. // @match *://www.google.co.jp/search?*
  95. // @match *://www.google.co.ke/search?*
  96. // @match *://www.google.com.kh/search?*
  97. // @match *://www.google.ki/search?*
  98. // @match *://www.google.kg/search?*
  99. // @match *://www.google.co.kr/search?*
  100. // @match *://www.google.com.kw/search?*
  101. // @match *://www.google.kz/search?*
  102. // @match *://www.google.la/search?*
  103. // @match *://www.google.com.lb/search?*
  104. // @match *://www.google.li/search?*
  105. // @match *://www.google.lk/search?*
  106. // @match *://www.google.co.ls/search?*
  107. // @match *://www.google.lt/search?*
  108. // @match *://www.google.lu/search?*
  109. // @match *://www.google.lv/search?*
  110. // @match *://www.google.com.ly/search?*
  111. // @match *://www.google.co.ma/search?*
  112. // @match *://www.google.md/search?*
  113. // @match *://www.google.me/search?*
  114. // @match *://www.google.mg/search?*
  115. // @match *://www.google.mk/search?*
  116. // @match *://www.google.ml/search?*
  117. // @match *://www.google.com.mm/search?*
  118. // @match *://www.google.mn/search?*
  119. // @match *://www.google.com.mt/search?*
  120. // @match *://www.google.mu/search?*
  121. // @match *://www.google.mv/search?*
  122. // @match *://www.google.mw/search?*
  123. // @match *://www.google.com.mx/search?*
  124. // @match *://www.google.com.my/search?*
  125. // @match *://www.google.co.mz/search?*
  126. // @match *://www.google.com.na/search?*
  127. // @match *://www.google.com.ng/search?*
  128. // @match *://www.google.com.ni/search?*
  129. // @match *://www.google.ne/search?*
  130. // @match *://www.google.nl/search?*
  131. // @match *://www.google.no/search?*
  132. // @match *://www.google.com.np/search?*
  133. // @match *://www.google.nr/search?*
  134. // @match *://www.google.nu/search?*
  135. // @match *://www.google.co.nz/search?*
  136. // @match *://www.google.com.om/search?*
  137. // @match *://www.google.com.pa/search?*
  138. // @match *://www.google.com.pe/search?*
  139. // @match *://www.google.com.pg/search?*
  140. // @match *://www.google.com.ph/search?*
  141. // @match *://www.google.com.pk/search?*
  142. // @match *://www.google.pl/search?*
  143. // @match *://www.google.pn/search?*
  144. // @match *://www.google.com.pr/search?*
  145. // @match *://www.google.ps/search?*
  146. // @match *://www.google.pt/search?*
  147. // @match *://www.google.com.py/search?*
  148. // @match *://www.google.com.qa/search?*
  149. // @match *://www.google.ro/search?*
  150. // @match *://www.google.ru/search?*
  151. // @match *://www.google.rw/search?*
  152. // @match *://www.google.com.sa/search?*
  153. // @match *://www.google.com.sb/search?*
  154. // @match *://www.google.sc/search?*
  155. // @match *://www.google.se/search?*
  156. // @match *://www.google.com.sg/search?*
  157. // @match *://www.google.sh/search?*
  158. // @match *://www.google.si/search?*
  159. // @match *://www.google.sk/search?*
  160. // @match *://www.google.com.sl/search?*
  161. // @match *://www.google.sn/search?*
  162. // @match *://www.google.so/search?*
  163. // @match *://www.google.sm/search?*
  164. // @match *://www.google.sr/search?*
  165. // @match *://www.google.st/search?*
  166. // @match *://www.google.com.sv/search?*
  167. // @match *://www.google.td/search?*
  168. // @match *://www.google.tg/search?*
  169. // @match *://www.google.co.th/search?*
  170. // @match *://www.google.com.tj/search?*
  171. // @match *://www.google.tl/search?*
  172. // @match *://www.google.tm/search?*
  173. // @match *://www.google.tn/search?*
  174. // @match *://www.google.to/search?*
  175. // @match *://www.google.com.tr/search?*
  176. // @match *://www.google.tt/search?*
  177. // @match *://www.google.com.tw/search?*
  178. // @match *://www.google.co.tz/search?*
  179. // @match *://www.google.com.ua/search?*
  180. // @match *://www.google.co.ug/search?*
  181. // @match *://www.google.co.uk/search?*
  182. // @match *://www.google.com.uy/search?*
  183. // @match *://www.google.co.uz/search?*
  184. // @match *://www.google.com.vc/search?*
  185. // @match *://www.google.co.ve/search?*
  186. // @match *://www.google.co.vi/search?*
  187. // @match *://www.google.com.vn/search?*
  188. // @match *://www.google.vu/search?*
  189. // @match *://www.google.ws/search?*
  190. // @match *://www.google.rs/search?*
  191. // @match *://www.google.co.za/search?*
  192. // @match *://www.google.co.zm/search?*
  193. // @match *://www.google.co.zw/search?*
  194. // @match *://www.google.cat/search?*
  195.  
  196. // @match *://search.yahoo.com/search*
  197. // @match *://search.yahoo.co.jp/search?*
  198. // @match *://*.search.yahoo.com/search*
  199.  
  200. // @match *://yandex.com/search/?*
  201. // @match *://yandex.ru/search/?*
  202.  
  203. // @match *://search.disroot.org/search*
  204. // @match *://searx.tiekoetter.com/search*
  205. // @match *://search.bus-hit.me/search*
  206. // @match *://search.inetol.net/search*
  207. // @match *://priv.au/search*
  208. // @match *://searx.be/search*
  209. // @match *://searxng.site/search*
  210. // @match *://search.hbubli.cc/search*
  211. // @match *://search.im-in.space/search*
  212. // @match *://opnxng.com/search*
  213. // @match *://search.upinmars.com/search*
  214. // @match *://search.sapti.me/search*
  215. // @match *://freesearch.club/search*
  216. // @match *://xo.wtf/search*
  217. // @match *://www.gruble.de/search*
  218. // @match *://searx.tuxcloud.net/search*
  219. // @match *://baresearch.org/search*
  220. // @match *://searx.daetalytica.io/search*
  221. // @match *://etsi.me/search*
  222. // @match *://search.leptons.xyz/search*
  223. // @match *://search.rowie.at/search*
  224. // @match *://search.mdosch.de/search*
  225. // @match *://searx.catfluori.de/search*
  226. // @match *://searx.si/search*
  227. // @match *://searx.namejeff.xyz/search*
  228. // @match *://search.itstechtime.com/search*
  229. // @match *://s.mble.dk/search*
  230. // @match *://searx.kutay.dev/search*
  231. // @match *://ooglester.com/search*
  232. // @match *://searx.ox2.fr/search*
  233. // @match *://searx.techsaviours.org/search*
  234. // @match *://searx.perennialte.ch/search*
  235. // @match *://s.trung.fun/searxng/search*
  236. // @match *://search.in.projectsegfau.lt/search*
  237. // @match *://search.projectsegfau.lt/search*
  238. // @match *://darmarit.org/searx/search*
  239. // @match *://searx.lunar.icu/search*
  240. // @match *://nyc1.sx.ggtyler.dev/search*
  241. // @match *://search.rhscz.eu/search*
  242. // @match *://paulgo.io/search*
  243. // @match *://northboot.xyz/search*
  244. // @match *://searx.zhenyapav.com/search*
  245. // @match *://searxng.ch/search*
  246. // @match *://copp.gg/search*
  247. // @match *://searx.sev.monster/search*
  248. // @match *://searx.oakleycord.dev/search*
  249. // @match *://searx.juancord.xyz/search*
  250. // @match *://searx.work/search*
  251. // @match *://search.ononoki.org/search*
  252. // @match *://search.demoniak.ch/search*
  253. // @match *://searx.cthd.icu/search*
  254. // @match *://searx.fmhy.net/search*
  255. // @match *://searx.headpat.exchange/search*
  256. // @match *://sex.finaltek.net/search*
  257. // @match *://search.gcomm.ch/search*
  258. // @match *://search.smnz.de/search*
  259. // @match *://searx.ankha.ac/search*
  260. // @match *://search.lvkaszus.pl/search*
  261. // @match *://searx.nobulart.com/search*
  262. // @match *://sx.t-1.org/search*
  263. // @match *://www.jabber-germany.de/searx/search*
  264. // @match *://sx.catgirl.cloud/search*
  265. // @match *://sx.vern.cc/searxng/search*
  266.  
  267. // @match *://www.startpage.com/search*
  268. // @match *://www.startpage.com/sp/search*
  269.  
  270. // @match *://search.brave.com/search*
  271.  
  272. // @match *://duckduckgo.com
  273. // @match *://duckduckgo.com/?*
  274.  
  275. // @match *://ghosterysearch.com/search?*
  276. // @match *://presearch.com/search?*
  277.  
  278. // @match *://metager.org/*meta/meta.ger3*
  279. // @match *://metager.de/*meta/meta.ger3*
  280.  
  281. // @match *://4get.ca/web?*
  282. // @match *://4get.silly.computer/web?*
  283. // @match *://4get.plunked.party/web?*
  284. // @match *://4get.konakona.moe/web?*
  285. // @match *://4get.sijh.net/web?*
  286. // @match *://4get.hbubli.cc/web?*
  287. // @match *://4get.perennialte.ch/web?*
  288. // @match *://4get.zzls.xyz/web?*
  289. // @match *://4getus.zzls.xyz/web?*
  290. // @match *://4get.seitan-ayoub.lol/web?*
  291. // @match *://4get.dcs0.hu/web?*
  292. // @match *://4get.psily.garden/web?*
  293. // @match *://4get.lvkaszus.pl/web?*
  294. // @match *://4get.kizuki.lol/web?*
  295.  
  296. // @match *://search.ahwx.org/search.php?*
  297. // @match *://search2.ahwx.org/search.php?*
  298. // @match *://search3.ahwx.org/search.php?*
  299. // @match *://ly.owo.si/search.php?*
  300. // @match *://librey.franklyflawless.org/search.php?*
  301. // @match *://librey.org/search.php?*
  302. // @match *://search.davidovski.xyz/search.php?*
  303. // @match *://search.milivojevic.in.rs/search.php?*
  304. // @match *://glass.prpl.wtf/search.php?*
  305. // @match *://librex.uk.to/search.php?*
  306. // @match *://librey.ix.tc/search.php?*
  307. // @match *://search.funami.tech/search.php?*
  308. // @match *://librex.retro-hax.net/search.php?*
  309. // @match *://librex.nohost.network/search.php?*
  310. // @match *://search.pabloferreiro.es/search.php?*
  311. // @match *://librey.baczek.me/search.php?*
  312. // @match *://lx.benike.me/search.php?*
  313. // @match *://search.seitan-ayoub.lol/search.php?*
  314. // @match *://librey.myroware.net/search.php?*
  315. // @match *://librey.nezumi.party/search.php?*
  316. // @match *://search.zeroish.xyz/search.php?*
  317.  
  318. // @match *://stract.com/search?*
  319.  
  320. // @match *://www.etools.ch/searchSubmit.do*
  321. // @match *://www.etools.ch/mobileSearch.do*
  322.  
  323. // @match *://www.mojeek.com/search?*
  324. // @match *://yep.com/web?*
  325. // @match *://www.torry.io/search*
  326. // @match *://www.qwant.com/?*
  327. // @match *://www.ecosia.org/search?*
  328. // @match *://search.becovi.com/serp.php?*
  329. // @match *://good-search.org/*search/?*
  330. // @match *://www.alltheinternet.com/?*
  331. // @match *://www.searchalot.com/?*
  332. // @match *://search.aol.com/*search*
  333. // @match *://www.onesearch.com/*search*
  334. // @match *://www.info.com/serp?*
  335. // @match *://oceanhero.today/web?*
  336.  
  337. // @match *://swisscows.com/*/web?*
  338.  
  339. // @match *://search.lilo.org/?*
  340. // @match *://search.entireweb.com/search?*
  341. // @match *://www.tadadoo.com/search?*
  342. // @match *://search.gmx.com/web/result?*
  343. // @match *://search.gmx.com/web?*
  344. // @match *://youcare.world/all?*
  345. // @match *://search.lycos.com/web/?*
  346. // @match *://alohafind.com/search/?*
  347. // @match *://spot.ecloud.global/search*
  348. // @match *://qmamu.com/search?*
  349. // @match *://search.carrot2.org/*
  350. // @match *://www.nona.de/?*
  351. // @match *://www.sapo.pt/pesquisa/web/tudo?*
  352. // @match *://www.exalead.com/search/web/results/?*
  353. // @match *://search.goo.ne.jp/web.jsp?*
  354. // @match *://search.seznam.cz/?*
  355. // @match *://www.startsiden.no/sok/?*
  356. // @match *://search.marginalia.nu/search?*
  357. // @match *://search.naver.com/search.naver?*
  358. // @match *://gibiru.com/results.html?*
  359. // @match *://www.lukol.com/s.php?*
  360. // @match *://www.draze.com/web/search?*
  361.  
  362. // @match *://www.yelliot.com/search/?*
  363. // @match *://fr.yelliot.com/search/?*
  364. // @match *://ar.yelliot.com/search/?*
  365. // @match *://es.yelliot.com/search/?*
  366. // @match *://de.yelliot.com/search/?*
  367. // @match *://it.yelliot.com/search/?*
  368. // @match *://ru.yelliot.com/search/?*
  369. // @match *://cn.yelliot.com/search/?*
  370. // @match *://in.yelliot.com/search/?*
  371. // @match *://pt.yelliot.com/search/?*
  372.  
  373. // @match *://efind.com/search*
  374. // @match *://fireball.de/de/search?*
  375. // @match *://freespoke.com/search/web?*
  376. // @match *://gogoprivate.com/search*
  377. // @match *://resulthunter.com/search?*
  378. // @match *://search.givewater.com/serp?*
  379. // @match *://results.excite.com/serp?*
  380. // @match *://www.webcrawler.com/serp?*
  381. // @match *://www.metacrawler.com/serp?*
  382. // @match *://www.dogpile.com/serp?*
  383. // @match *://www.infospace.com/serp?*
  384. // @match *://www.refseek.com/search?*
  385. // @match *://www.zapmeta.com/search?*
  386. // @match *://www.izito.com/search?*
  387. // @match *://www.ask.com/web?*
  388. // @match *://www.pronto.com/web?*
  389. // @match *://anoox.com/find.php?*
  390.  
  391. // @grant none
  392. // @run-at document-end
  393. // @license GPL-2.0-only
  394. // ==/UserScript==
  395.  
  396. (function () {
  397. 'use strict';
  398.  
  399. // Define URL modification rules with precompiled regex
  400. const urlModificationRules = [
  401. // {
  402. // matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?(?:https?:\/\/)(?:[\w-]+\.|)((?:imdb|imgur|instagram|medium|odysee|quora|reddit|tiktok|twitter|wikipedia|youtube)\.(?:[a-z]+).*?)(?:$|\/RK=.*|&sa=.*)/),
  403. // replaceWith: 'https://farside.link/$1'
  404. // },
  405. {
  406. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/((?!test)[a-z]+)\.?m?\.wikipedia\.org\/(?:[a-z]+|wiki)\/(?!Special:Search)(.*?)(?:$|\/RK=.*|&sa=.*)/),
  407. replaceWith: 'https://www.wikiwand.com/$1/$2'
  408. },
  409. {
  410. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/zh\.?m?\.wikipedia\.org\/(?:zh-hans|wiki)\/(.*?)(?:$|\/RK=.*|&sa=.*)/),
  411. replaceWith: 'https://www.wikiwand.com/zh-hans/$1'
  412. },
  413. {
  414. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/wikipedia\.org\/(?:[a-z]+|wiki)\/(?!Special:Search)(.*?)(?:$|\/RK=.*|&sa=.*)/),
  415. replaceWith: 'https://www.wikiwand.com/en/$1'
  416. },
  417. {
  418. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:old|www)\.reddit\.com\/((?:r|u)\/.*?)(?:$|\/RK=.*|&sa=.*)/),
  419. replaceWith: 'https://safereddit.com/$1'
  420. // replaceWith: 'https://lr.vern.cc/$1'
  421. },
  422. {
  423. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.quora\.com\/((?=.*-)[\w-]+|profile\/.*?)(?:$|\/RK=.*|&sa=.*)/),
  424. replaceWith: 'https://quetre.iket.me/$1'
  425. },
  426. {
  427. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/twitter\.com\/([A-Za-z_][\w]+)(\/status\/(?:\d+))?(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  428. replaceWith: 'https://nitter.catsarch.com/$1$2'
  429. },
  430. {
  431. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:www\.)?stackoverflow\.com\/(questions\/\d+(?:\/[\w-]+)?)(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  432. replaceWith: 'https://ao.vern.cc/$1'
  433. },
  434. {
  435. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(.*?(?:medium.*?|towardsdatascience|betterprogramming|plainenglish|gitconnected|aninjusticemag|betterhumans|uxdesign|uxplanet)\.\w+\/(?!tag)(?=.*-)(?:[\w\/-]+|[\w@.]+\/[\w-]+))(?:\?source=.*)?(?:$|\/RK=.*|&sa=.*)/),
  436. replaceWith: 'https://freedium.cfd/https://$1'
  437. },
  438. {
  439. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:www\.|m\.)?youtube\.com\/((?:@|watch\?|playlist\?|channel\/|user\/|shorts\/).*?)(?:$|\/RK=.*|&sa=.*)/),
  440. // replaceWith: 'https://vid.puffyan.us/$1'
  441. replaceWith: 'https://piped.video/$1'
  442. },
  443. {
  444. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/music\.youtube\.com\/((?:playlist\?|watch\?|channel\/|browse\/).*?)(?:$|\/RK=.*|&sa=.*)/),
  445. replaceWith: 'https://hyperpipe.surge.sh/$1'
  446. },
  447. {
  448. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.twitch\.tv\/(\w+)(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  449. replaceWith: 'https://ttv.vern.cc/$1'
  450. },
  451. {
  452. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:m|www)\.imdb\.com\/((?:title|name)\/\w+)(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  453. replaceWith: 'https://ld.vern.cc/$1'
  454. },
  455. {
  456. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.goodreads\.com\/((?:(?:[a-z]+\/)?book\/show|work\/quotes|series|author\/show)\/[\w.-]+)(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  457. replaceWith: 'https://bl.vern.cc/$1'
  458. },
  459. {
  460. // only support English Fandom sites
  461. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/((?!www|community).*?)\.fandom\.com\/wiki\/(.*?)(?:$|\/RK=.*|&sa=.*)/),
  462. replaceWith: 'https://antifandom.com/$1/wiki/$2'
  463. },
  464. {
  465. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.urbandictionary\.com\/(define\.php\?term=.*?)(?:$|\/RK=.*|&sa=.*)/),
  466. replaceWith: 'https://rd.vern.cc/$1'
  467. },
  468. {
  469. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.reuters\.com\/((?=.*\/)(?=.*-).*?)(?:$|\/RK=.*|&sa=.*)/),
  470. replaceWith: 'https://nu.vern.cc/$1'
  471. },
  472. {
  473. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(www\.ft\.com\/content\/[\w-]+)(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  474. replaceWith: 'https://archive.today/https://$1'
  475. },
  476. {
  477. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(www\.bloomberg\.com\/(?:(?:[a-z]+\/)?news|opinion)\/.*?)(?:$|\/RK=.*|&sa=.*)/),
  478. replaceWith: 'https://archive.today/https://$1'
  479. },
  480. {
  481. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.npr\.org\/(?:\d{4}\/\d{2}\/\d{2}|sections)\/(?:[A-Za-z-]+\/\d{4}\/\d{2}\/\d{2}\/)?(\d+)\/(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  482. replaceWith: 'https://text.npr.org/$1'
  483. },
  484. {
  485. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/news\.ycombinator\.com\/item\?id=(\d+)(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  486. replaceWith: 'https://www.hckrnws.com/stories/$1'
  487. },
  488. {
  489. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:[a-z]+)\.slashdot\.org(.*?)(?:$|\/RK=.*|&sa=.*)/),
  490. replaceWith: 'https://slashdot.org$1'
  491. },
  492. {
  493. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:(?:.*)(?:arxiv\.org\/pdf|arxiv-export-lb\.library\.cornell\.edu\/(?:pdf|abs)))\/(\d{4}\.\d{4,5}(v\d)?)(?:.*)/),
  494. replaceWith: 'https://arxiv.org/abs/$1'
  495. },
  496. {
  497. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(ieeexplore\.ieee\.org\/document\/\d+)\/(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  498. replaceWith: 'https://$1'
  499. },
  500. {
  501. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/github\.ink(.*?)(?:$|\/RK=.*|&sa=.*)/),
  502. replaceWith: 'https://github.com$1'
  503. },
  504. {
  505. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.snopes\.com(.*?)(?:$|\/RK=.*|&sa=.*)/),
  506. replaceWith: 'https://sd.vern.cc$1'
  507. },
  508. {
  509. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.instructables\.com\/(.*?)(?:$|\/RK=.*|&sa=.*)/),
  510. replaceWith: 'https://ds.vern.cc/$1'
  511. // replaceWith: 'https://structables.private.coffee/$1'
  512. },
  513. {
  514. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/genius\.com\/((?=[\w-]+lyrics|search\?q=).*?)(?:$|\/RK=.*|&sa=.*)/),
  515. replaceWith: 'https://dm.vern.cc/$1'
  516. },
  517. {
  518. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(.*?)\.bandcamp\.com\/(?:$|\/RK=.*|&sa=.*)/),
  519. replaceWith: 'https://tn.vern.cc/artist.php?name=$1'
  520. },
  521. {
  522. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(.*?)\.bandcamp\.com\/(.*?)\/(.*?)(?:$|\/RK=.*|&sa=.*)/),
  523. replaceWith: 'https://tn.vern.cc/release.php?artist=$1&type=$2&name=$3'
  524. },
  525. {
  526. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/bandcamp\.com\/search\?q=(.*?)(?:$|\/RK=.*|&sa=.*)/),
  527. replaceWith: 'https://tn.vern.cc/search.php?query=$1'
  528. },
  529. {
  530. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/f4\.bcbits\.com\/img\/(.*?)(?:$|\/RK=.*|&sa=.*)/),
  531. replaceWith: 'https://tn.vern.cc/image.php?file=$1'
  532. },
  533. {
  534. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/t4\.bcbits\.com\/stream\/(.*?)\/(.*?)\/(.*?)\?token=(.*?)(?:$|\/RK=.*|&sa=.*)/),
  535. replaceWith: 'https://tn.vern.cc/audio.php?directory=$1&format=$2&file=$3&token=$4'
  536. },
  537. {
  538. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:[\w.]+)?imgur.com\/((?:a\/)?(?!gallery)[\w.]+)(?:.*?)(?:$|\/RK=.*|&sa=.*)/),
  539. replaceWith: 'https://rimgo.totaldarkness.net/$1'
  540. },
  541. {
  542. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/www\.pixiv\.net\/(?:[a-z]+\/)?(artworks\/\d+|tags\/\w+|users\/\d+).*/),
  543. replaceWith: 'https://pixivfe.exozy.me/$1'
  544. },
  545. {
  546. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/knowyourmeme\.com\/(.*?)(?:$|\/RK=.*|&sa=.*)/),
  547. replaceWith: 'https://mm.vern.cc/$1'
  548. },
  549. {
  550. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/tenor\.com\/((?:view|search)\/.*?)(?:$|\/RK=.*|&sa=.*)/),
  551. replaceWith: 'https://sp.vern.cc/$1'
  552. },
  553. {
  554. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))?https?:\/\/(?:\w+\.)?ifunny\.co\/(picture\/.*?)(?:$|\/RK=.*|&sa=.*)/),
  555. replaceWith: 'https://uf.vern.cc/$1'
  556. },
  557. {
  558. matchRegex: new RegExp(/^(?:.*?(?:\/RU=|&q=|&as=))https?:\/\/(.*?)(?:$|\/RK=.*|&sa=.*)/),
  559. replaceWith: 'https://$1'
  560. },
  561. // Add more rules here as needed
  562. ];
  563.  
  564. // Define enhanced selector rules for each search engine
  565. const selectorRules = {
  566. 'google': [
  567. {
  568. selector: 'div.MjjYud div.yuRUbf div span a',
  569. childSelector: 'div.byrV5b cite',
  570. updateChildText: true,
  571. containProtocol: true,
  572. urlDisplayMethod: 1
  573. },
  574. {
  575. // selector for sub-results
  576. selector: 'div.MjjYud div.HiHjCd a'
  577. },
  578. {
  579. // selector for sidebar links
  580. selector: 'div.TQc1id#rhs a'
  581. }
  582. ],
  583. 'yahoo': [
  584. {
  585. parentSelector: 'div#left div#web ol li div div.compTitle h3.title',
  586. linkNodeSelector: 'a',
  587. textNodeSelector: 'span.p-abs',
  588. childSelector: 'span',
  589. updateChildText: true,
  590. containProtocol: false,
  591. multiElementsForUrlDisplay: 2
  592. },
  593. {
  594. selector: 'div#left div#web ol li div ul.compArticleList a'
  595. },
  596. {
  597. selector: 'div#left div#web ol li div div.compGenericCardList a'
  598. },
  599. {
  600. selector: 'div#right ol.cardReg.searchRightTop a'
  601. }
  602. ],
  603. 'yahoojp': [
  604. {
  605. parentSelector: 'div.sw-CardBase div.sw-Card__title',
  606. linkNodeSelector: 'a.sw-Card__titleInner',
  607. textNodeSelector: 'div.sw-Card__titleCiteWrapper cite ol',
  608. childSelector: 'li',
  609. updateChildText: true,
  610. containProtocol: true,
  611. multiElementsForUrlDisplay: 1
  612. },
  613. {
  614. selector: 'div.sw-CardBase p.Algo__osl a'
  615. },
  616. {
  617. selector: 'div.sw-CardBase div.sw-Card.AnswerKnowledgePanel__title div.sw-Tooltip__balloonInner a',
  618. updateTextByOverwrite: true,
  619. urlDisplayMethod: 2
  620. },
  621. {
  622. selector: 'div.sw-CardBase div.sw-Card.AnswerKnowledgePanel__title a'
  623. },
  624. {
  625. selector: 'div.sw-CardBase div.sw-Card.AnswerKnowledgePanel__info a'
  626. }
  627. ],
  628. 'yandex': [
  629. {
  630. selector: 'ul#search-result li div.Organic-Subtitle div a',
  631. updateChildText: true,
  632. containProtocol: false,
  633. urlDisplayMethod: 1,
  634. },
  635. {
  636. selector: 'ul#search-result li div.Organic div a',
  637. }
  638. ],
  639. 'searx': [
  640. {
  641. selector: 'article.result a.url_wrapper',
  642. childSelector: 'span span',
  643. updateChildText: true,
  644. containProtocol: true,
  645. multiElementsForUrlDisplay: 1
  646. },
  647. {
  648. selector: 'article.result h3 a'
  649. },
  650. {
  651. selector: 'aside.infobox div.urls ul li a'
  652. }
  653. ],
  654. 'startpage': [
  655. {
  656. selector: 'a.w-gl__result-url.result-link',
  657. updateTextByOverwrite: true,
  658. urlDisplayMethod: 2
  659. },
  660. {
  661. selector: 'a.w-gl__result-title.result-link'
  662. },
  663. {
  664. selector: 'div.sx-kp-main a'
  665. }
  666. ],
  667. 'brave': [
  668. {
  669. selector: 'div.snippet a.h',
  670. childSelector: 'div.site cite.snippet-url span',
  671. updateChildText: true,
  672. containProtocol: false,
  673. multiElementsForUrlDisplay: 1
  674. },
  675. {
  676. selector: 'div#discussions.snippet a',
  677. },
  678. {
  679. selector: 'div#infobox-snippet.snippet a'
  680. }
  681. ],
  682. 'duckduckgo': [
  683. {
  684. selector: 'a.eVNpHGjtxRBq_gLOfGDr.LQNqh2U1kzYxREs65IJu'
  685. },
  686. {
  687. selector: 'a.Rn_JXVtoPVAFyGkcaXyK',
  688. childSelector: 'span',
  689. updateChildText: true,
  690. containProtocol: true,
  691. multiElementsForUrlDisplay: 1
  692. },
  693. {
  694. // Selector for sub-results
  695. selector: 'ul.b269SZlC2oyR13Fcc4Iy li a.f3uDrYrWF3Exrfp1m3Og'
  696. },
  697. {
  698. selector: 'div.react-module div section div a'
  699. }
  700. ],
  701. 'ghostery': [
  702. {
  703. selector: 'li.result h2 a'
  704. },
  705. {
  706. selector: 'li.result div.snippet div.address a.url',
  707. updateTextByOverwrite: true,
  708. urlDisplayMethod: 2
  709. }
  710. ],
  711. 'presearch': [
  712. {
  713. selector: 'div.relative div.w-auto a',
  714. childSelector: 'div',
  715. updateChildText: true,
  716. urlDisplayMethod: 3,
  717. },
  718. {
  719. selector: 'div.relative div.inline-block a'
  720. }
  721. ],
  722. 'metager': [
  723. {
  724. selector: 'h2.result-title a'
  725. },
  726. {
  727. selector: 'div.result-subheadline a',
  728. updateTextByOverwrite: true,
  729. urlDisplayMethod: 3
  730. },
  731. {
  732. selector: 'div.quicktip div.quicktip-headline h1 a'
  733. },
  734. {
  735. selector: 'div.quicktip div.quicktip-detail h2 a'
  736. }
  737. ],
  738. '4get': [
  739. {
  740. parentSelector: 'div.text-result',
  741. linkNodeSelector: 'a.hover',
  742. textNodeSelector: 'div.url',
  743. childSelector: 'a.part',
  744. updateChildText: true,
  745. containProtocol: true,
  746. multiElementsForUrlDisplay: 4
  747. },
  748. {
  749. selector: 'div.text-result div.sublinks a'
  750. },
  751. {
  752. parentSelector: 'div.right-wrapper div.answer',
  753. linkNodeSelector: 'a.answer-title',
  754. textNodeSelector: 'div.url',
  755. childSelector: 'a.part',
  756. updateChildText: true,
  757. containProtocol: true,
  758. multiElementsForUrlDisplay: 4
  759. }
  760. ],
  761. 'librey': [
  762. {
  763. selector: 'div.text-result-wrapper a',
  764. updateTextWithoutOverwrite: true,
  765. useTopLevelDomain: true,
  766. urlDisplayMethod: 2
  767. },
  768. {
  769. selector: 'p.special-result-container a',
  770. updateTextWithoutOverwrite: true,
  771. urlDisplayMethod: 2
  772. },
  773. ],
  774. 'stract': [
  775. {
  776. selector: 'div.grid div div.flex div div a.text-link'
  777. },
  778. {
  779. selector: 'div.grid div div.flex div div div a',
  780. updateTextByOverwrite: true,
  781. urlDisplayMethod: 2
  782. },
  783. {
  784. selector: 'div.mb-5.text-xl a'
  785. },
  786. {
  787. selector: 'div.text-sm a.text-link'
  788. }
  789. ],
  790. 'etools': [
  791. {
  792. // searchSubmit.do
  793. selector: 'td.record a.title'
  794. },
  795. {
  796. // mobileSearch.do
  797. selector: 'p a.title'
  798. }
  799. ],
  800. 'mojeek': [
  801. {
  802. selector: 'ul.results-standard li h2 a.title'
  803. },
  804. {
  805. selector: 'ul.results-standard li a.ob',
  806. childSelector: 'span.url',
  807. updateChildText: true,
  808. containProtocol: true,
  809. urlDisplayMethod: 1
  810. },
  811. {
  812. selector: 'div.infobox p a'
  813. },
  814. {
  815. selector: 'div.results.news-results li a'
  816. },
  817. {
  818. selector: 'div.right-col div.results ul li a'
  819. }
  820. ],
  821. 'yep': [
  822. {
  823. selector: 'div.css-102xgmn-card div div a',
  824. childSelector: 'div span',
  825. updateChildText: true,
  826. containProtocol: false,
  827. urlDisplayMethod: 1
  828. }
  829. ],
  830. 'torry': [
  831. {
  832. selector: 'div.searpList p a.toranclick',
  833. updateTextByOverwrite: true,
  834. urlDisplayMethod: 2
  835. },
  836. {
  837. selector: 'div.searpList div h2 a.toranclick',
  838. },
  839. {
  840. selector: 'div.searpList ul li a',
  841. }
  842. ],
  843. 'qwant': [
  844. {
  845. selector: 'div._35zId._3A7p7 a.external'
  846. },
  847. {
  848. selector: 'div._35zId._3WA-c a.external',
  849. childSelector: 'span',
  850. updateChildText: true,
  851. containProtocol: false,
  852. multiElementsForUrlDisplay: 1
  853. },
  854. {
  855. // Selector for sub-results
  856. selector: 'div._12BMd div._2-LMx._2E8gc._16lFV.Ks7KS.tCpbb.m_hqb a.external'
  857. },
  858. {
  859. selector: 'div._3McWE.is-sidebar a.external'
  860. }
  861. ],
  862. 'ecosia': [
  863. {
  864. selector: 'div.mainline__result-wrapper div.result__header div.result__info a',
  865. childSelector: 'span span',
  866. updateChildText: true,
  867. containProtocol: true,
  868. multiElementsForUrlDisplay: 1
  869. },
  870. {
  871. selector: 'div.mainline__result-wrapper div.result__header div.result__title a'
  872. },
  873. {
  874. selector: 'div.mainline__result-wrapper div ul li a'
  875. },
  876. {
  877. selector: 'aside.sidebar article div.entity-links ul li a'
  878. },
  879. {
  880. selector: 'aside.sidebar article div.entity__content p a'
  881. }
  882. ],
  883. 'oscobo': [
  884. {
  885. selector: 'div.result a',
  886. childSelector: 'span.siteTitleWrap span.favicons',
  887. updateTextWithoutOverwrite: true,
  888. containProtocol: true,
  889. urlDisplayMethod: 1
  890. }
  891. ],
  892. 'good': [
  893. {
  894. selector: 'div.content div.margin-bottom--small.box a.link--search',
  895. childSelector: 'p.url',
  896. updateTextByOverwrite: true,
  897. urlDisplayMethod: 2
  898. },
  899. {
  900. selector: 'div.sx-kp-top a'
  901. },
  902. {
  903. selector: 'div.sx-kp-tab-content-wrap section ul.sx-kp-social-links a'
  904. },
  905. {
  906. selector: 'div.sx-kp-tab-content-wrap section div.sx-kp-attributions a'
  907. }
  908. ],
  909. 'alltheinternet': [
  910. {
  911. parentSelector: 'div.gs-webResult.gs-result',
  912. linkNodeSelector: 'a.gs-title',
  913. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-long',
  914. updateTextByOverwrite: true,
  915. urlDisplayMethod: 2
  916. }
  917. ],
  918. 'searchalot': [
  919. {
  920. parentSelector: 'div.gs-webResult.gs-result',
  921. linkNodeSelector: 'a.gs-title',
  922. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-long',
  923. updateTextByOverwrite: true,
  924. urlDisplayMethod: 2
  925. }
  926. ],
  927. 'aol': [
  928. {
  929. parentSelector: 'div#left div#web ol li div div.compTitle',
  930. linkNodeSelector: 'h3.title a',
  931. textNodeSelector: 'div span',
  932. updateTextByOverwrite: true,
  933. urlDisplayMethod: 3
  934. },
  935. {
  936. selector: 'div#left div#web ol li div div.compList a'
  937. },
  938. {
  939. selector: 'div#right ol.cardReg.searchRightTop a'
  940. }
  941. ],
  942. 'onesearch': [
  943. {
  944. parentSelector: 'div#left div#web ol li div div.compTitle',
  945. linkNodeSelector: 'h3.title a',
  946. textNodeSelector: 'div span',
  947. updateTextByOverwrite: true,
  948. urlDisplayMethod: 3
  949. },
  950. {
  951. selector: 'div#left div#web ol li div div.compList a'
  952. },
  953. {
  954. selector: 'div#right ol.cardReg.searchRightTop a'
  955. }
  956. ],
  957. 'info': [
  958. {
  959. parentSelector: 'div.web-yahoo__result',
  960. linkNodeSelector: 'a.web-yahoo__title',
  961. textNodeSelector: 'span.web-yahoo__url',
  962. updateTextWithoutOverwrite: true,
  963. urlDisplayMethod: 2
  964. },
  965. {
  966. selector: 'div.sidebar-results a'
  967. }
  968. ],
  969. 'oceanhero': [
  970. {
  971. selector: 'div div div a',
  972. childSelector: 'span cite',
  973. updateChildText: true,
  974. containProtocol: false,
  975. urlDisplayMethod: 1
  976. },
  977. {
  978. selector: 'section div ul li a'
  979. },
  980. {
  981. selector: 'div div div p a'
  982. }
  983. ],
  984. 'swisscows': [
  985. {
  986. selector: 'article.item-web a.site',
  987. updateTextWithoutOverwrite: true,
  988. containProtocol: false,
  989. urlDisplayMethod: 1
  990. },
  991. {
  992. selector: 'article.item-web a'
  993. }
  994. ],
  995. 'lilo': [
  996. {
  997. selector: 'div.lilo-text-result div p a.has-text-grey-darker',
  998. // Displayed URL modification not working correctly in Lilo
  999. // Reason is unknown, the displayed URL will return to the original URL after modification
  1000. // childSelector: 'span',
  1001. // updateChildText: true,
  1002. // containProtocol: true,
  1003. // multiElementsForUrlDisplay: 2
  1004. },
  1005. {
  1006. selector: 'div.lilo-text-result div a.has-text-primary'
  1007. },
  1008. {
  1009. selector: 'div.column.is-two-fifths a'
  1010. }
  1011. ],
  1012. 'entireweb': [
  1013. {
  1014. parentSelector: 'div.web-result',
  1015. linkNodeSelector: 'a.web-result-title',
  1016. textNodeSelector: 'div.web-result-domain',
  1017. updateTextWithoutOverwrite: true,
  1018. urlDisplayMethod: 3
  1019. },
  1020. {
  1021. selector: 'div#infobox-list.card div.card-body a'
  1022. },
  1023. {
  1024. parentSelector: 'div.gsc-webResult.gsc-result',
  1025. linkNodeSelector: 'a.gs-title',
  1026. textNodeSelector: 'div.gsc-url-top',
  1027. updateTextByOverwrite: true,
  1028. containProtocol: false,
  1029. urlDisplayMethod: 1
  1030. }
  1031. ],
  1032. 'tadadoo': [
  1033. {
  1034. parentSelector: 'div.web-result',
  1035. linkNodeSelector: 'a.web-result-title',
  1036. textNodeSelector: 'div.web-result-domain',
  1037. updateTextWithoutOverwrite: true,
  1038. urlDisplayMethod: 3
  1039. },
  1040. {
  1041. selector: 'div#infobox-list.card div.card-body a'
  1042. }
  1043. ],
  1044. 'gmx': [
  1045. {
  1046. selector: 'div.eMd a.eMdhl'
  1047. },
  1048. {
  1049. selector: 'div.eMd a.eMdu',
  1050. childSelector: 'span',
  1051. updateChildText: true,
  1052. containProtocol: true,
  1053. multiElementsForUrlDisplay: 2
  1054. },
  1055. ],
  1056. 'youcare': [
  1057. {
  1058. selector: 'div.search-result-item-text a.search-result-item-text__title'
  1059. },
  1060. {
  1061. selector: 'div.search-result-item-text div div a.search-result-item-text-sitename'
  1062. },
  1063. {
  1064. selector: 'div.search-result-item-text div div a.search-result-item-text__header-url',
  1065. updateTextWithoutOverwrite: true,
  1066. containProtocol: true,
  1067. urlDisplayMethod: 1
  1068. },
  1069. {
  1070. selector: "div.search-results-view__side a"
  1071. }
  1072. ],
  1073. 'lycos': [
  1074. {
  1075. parentSelector: 'div.results li.result-item',
  1076. linkNodeSelector: 'a.result-link',
  1077. textNodeSelector: 'span.result-url',
  1078. updateTextByOverwrite: true,
  1079. urlDisplayMethod: 3
  1080. },
  1081. {
  1082. selector: 'div.col-aside a'
  1083. }
  1084. ],
  1085. 'alohafind': [
  1086. {
  1087. parentSelector: 'div.gsc-webResult.gsc-result',
  1088. linkNodeSelector: 'a.gs-title',
  1089. textNodeSelector: 'div.gs-visibleUrl-short',
  1090. updateTextByOverwrite: true,
  1091. urlDisplayMethod: 3
  1092. }
  1093. ],
  1094. 'spot': [
  1095. {
  1096. selector: 'div.result h4 a'
  1097. },
  1098. {
  1099. selector: 'div.result a.external-link',
  1100. updateTextByOverwrite: true,
  1101. urlDisplayMethod: 2
  1102. },
  1103. {
  1104. selector: 'div.infobox div.footer div.links a'
  1105. }
  1106. ],
  1107. 'qmamu': [
  1108. {
  1109. selector: 'div.sc-1i4c0yr-4.cxFATD a'
  1110. },
  1111. {
  1112. selector: 'div.sc-meawca-31.liCyKS a',
  1113. childSelector: 'span.sc-meawca-10.czAks',
  1114. updateChildText: true,
  1115. containProtocol: true,
  1116. urlDisplayMethod: 1
  1117. }
  1118. ],
  1119. 'carrot2': [
  1120. {
  1121. selector: 'div.ResultList a.Result',
  1122. childSelector: 'span.url span',
  1123. updateChildText: true,
  1124. urlDisplayMethod: 2
  1125. },
  1126. {
  1127. selector: 'div.sc-meawca-31.liCyKS a',
  1128. childSelector: 'span.sc-meawca-10.czAks',
  1129. updateChildText: true,
  1130. containProtocol: true,
  1131. urlDisplayMethod: 1
  1132. }
  1133. ],
  1134. 'nona': [
  1135. {
  1136. selector: 'section.result-section article.teaser div.teaser__container a.teaser__topline',
  1137. updateTextByOverwrite: true,
  1138. urlDisplayMethod: 2
  1139. },
  1140. {
  1141. selector: 'section.result-section article.teaser div.teaser__container a.teaser__link'
  1142. },
  1143. {
  1144. selector: 'section.result-section article.entity-teaser div.entity-teaser__wrapper a'
  1145. }
  1146. ],
  1147. 'sapo': [
  1148. {
  1149. parentSelector: 'div.gs-webResult.gs-result',
  1150. linkNodeSelector: 'a.gs-title',
  1151. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-breadcrumb',
  1152. childSelector: 'span',
  1153. updateChildText: true,
  1154. containProtocol: false,
  1155. multiElementsForUrlDisplay: 1
  1156. }
  1157. ],
  1158. 'exalead': [
  1159. {
  1160. selector: 'li.media div.media-body a.ellipsis',
  1161. updateTextByOverwrite: true,
  1162. urlDisplayMethod: 3
  1163. },
  1164. {
  1165. selector: 'li.media div.media-body a'
  1166. }
  1167. ],
  1168. 'goo': [
  1169. {
  1170. parentSelector: 'div.result',
  1171. linkNodeSelector: 'p.title a',
  1172. textNodeSelector: 'p.url span.cM',
  1173. updateTextByOverwrite: true,
  1174. urlDisplayMethod: 3
  1175. },
  1176. {
  1177. selector: 'div.aside div.talentTxt a'
  1178. },
  1179. ],
  1180. 'seznam': [
  1181. {
  1182. selector: 'div.f2c528 h3 a'
  1183. },
  1184. {
  1185. selector: 'div.f2c528 a.d5e75c',
  1186. updateTextByOverwrite: true,
  1187. urlDisplayMethod: 3
  1188. },
  1189. ],
  1190. 'startsiden': [
  1191. {
  1192. selector: 'li.result a.result__link-wrapper',
  1193. childSelector: 'div.result__url',
  1194. updateChildText: true,
  1195. containProtocol: false,
  1196. urlDisplayMethod: 1
  1197. },
  1198. {
  1199. selector: 'div.f2c528 a.d5e75c',
  1200. updateTextByOverwrite: true,
  1201. urlDisplayMethod: 3
  1202. },
  1203. ],
  1204. 'marginalia': [
  1205. {
  1206. selector: 'section.card.search-result div.url a',
  1207. updateTextByOverwrite: true,
  1208. urlDisplayMethod: 2
  1209. },
  1210. {
  1211. selector: 'section.card.search-result h2 a.title'
  1212. },
  1213. {
  1214. selector: 'section.card.search-result div.additional-results li a'
  1215. }
  1216. ],
  1217. 'naver': [
  1218. {
  1219. selector: 'li.bx div.total_wrap div.source_box a.thumb'
  1220. },
  1221. {
  1222. selector: 'li.bx div.total_wrap div.source_box a.txt',
  1223. updateTextByOverwrite: true,
  1224. containProtocol: false,
  1225. urlDisplayMethod: 1
  1226. },
  1227. {
  1228. selector: 'li.bx div.total_wrap a.link_tit'
  1229. },
  1230. {
  1231. selector: 'li.bx div.snippet_rel_wrap a.link_item'
  1232. },
  1233. {
  1234. selector: 'li.bx div.source_cluster_wrap a'
  1235. },
  1236. {
  1237. selector: 'section.sc_new a'
  1238. }
  1239. ],
  1240. 'gibiru': [
  1241. {
  1242. parentSelector: 'div.gs-webResult.gs-result',
  1243. linkNodeSelector: 'a.gs-title',
  1244. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-breadcrumb',
  1245. childSelector: 'span',
  1246. updateChildText: true,
  1247. containProtocol: false,
  1248. multiElementsForUrlDisplay: 1
  1249. }
  1250. ],
  1251. 'lukol': [
  1252. {
  1253. parentSelector: 'div.gsc-webResult.gsc-result',
  1254. linkNodeSelector: 'a.gs-title',
  1255. textNodeSelector: 'div.gsc-url-bottom div.gs-visibleUrl-long',
  1256. updateTextByOverwrite: true,
  1257. urlDisplayMethod: 2
  1258. }
  1259. ],
  1260. 'draze': [
  1261. {
  1262. parentSelector: 'div.gsc-webResult.gsc-result',
  1263. linkNodeSelector: 'a.gs-title',
  1264. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-breadcrumb',
  1265. childSelector: 'span',
  1266. updateChildText: true,
  1267. containProtocol: false,
  1268. multiElementsForUrlDisplay: 1
  1269. }
  1270. ],
  1271. 'yelliot': [
  1272. {
  1273. parentSelector: 'div.gsc-webResult.gsc-result',
  1274. linkNodeSelector: 'a.gs-title',
  1275. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-breadcrumb',
  1276. childSelector: 'span',
  1277. updateChildText: true,
  1278. containProtocol: false,
  1279. multiElementsForUrlDisplay: 1
  1280. }
  1281. ],
  1282. 'efind': [
  1283. {
  1284. parentSelector: 'article.result',
  1285. linkNodeSelector: 'h3 a',
  1286. textNodeSelector: 'div.external-link div',
  1287. childSelector: 'span',
  1288. updateChildText: true,
  1289. containProtocol: false,
  1290. multiElementsForUrlDisplay: 2
  1291. },
  1292. {
  1293. selector: 'aside.infobox a'
  1294. }
  1295. ],
  1296. 'fireball': [
  1297. {
  1298. selector: 'div.search-result a.search-result-title'
  1299. },
  1300. {
  1301. selector: 'div.search-result a.search-result-url',
  1302. updateTextByOverwrite: true,
  1303. urlDisplayMethod: 2
  1304. },
  1305. {
  1306. selector: 'div.search-result a.search-result-check'
  1307. }
  1308. ],
  1309. 'freespoke': [
  1310. {
  1311. selector: 'div.result-block a.title-source-link',
  1312. childSelector: 'span.breadcrumb-container',
  1313. updateTextByOverwrite: true,
  1314. containProtocol: false,
  1315. urlDisplayMethod: 1
  1316. },
  1317. {
  1318. selector: 'div.ant-col.component-col div.WebSearchResult div.main-container a'
  1319. },
  1320. {
  1321. selector: 'div.ant-col.sidebar div.se-widget a'
  1322. },
  1323. {
  1324. selector: 'div.ant-col.sidebar div.KnowledgePanelResults div.ExpandableContainer a'
  1325. },
  1326. {
  1327. selector: 'div.ant-col.test.ant-col-xs-24 div.se-widget a'
  1328. },
  1329. {
  1330. selector: 'div.ant-col.ant-col-xs-24 div.KnowledgePanelResults div.ExpandableContainer a'
  1331. }
  1332. ],
  1333. 'gogoprivate': [
  1334. {
  1335. parentSelector: 'div.gsc-webResult.gsc-result',
  1336. linkNodeSelector: 'div.gs-title a[target="_PARENT"]',
  1337. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-breadcrumb',
  1338. childSelector: 'span',
  1339. updateChildText: true,
  1340. containProtocol: false,
  1341. multiElementsForUrlDisplay: 1
  1342. },
  1343. {
  1344. selector: 'div.vidbox#imgbox a'
  1345. }
  1346. ],
  1347. 'resulthunter': [
  1348. {
  1349. parentSelector: 'div.gsc-webResult.gsc-result',
  1350. linkNodeSelector: 'a.web-result-title',
  1351. textNodeSelector: 'div.web-result-domain',
  1352. updateTextWithoutOverwrite: true,
  1353. urlDisplayMethod: 3
  1354. },
  1355. {
  1356. parentSelector: 'div.gsc-webResult.gsc-result',
  1357. linkNodeSelector: 'a.gs-title',
  1358. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-breadcrumb',
  1359. childSelector: 'span',
  1360. updateChildText: true,
  1361. containProtocol: false,
  1362. multiElementsForUrlDisplay: 1
  1363. }
  1364. ],
  1365. 'givewater': [
  1366. {
  1367. parentSelector: 'div.web-bing__result',
  1368. linkNodeSelector: 'a.web-bing__title',
  1369. textNodeSelector: 'span.web-bing__url',
  1370. updateTextByOverwrite: true,
  1371. urlDisplayMethod: 2
  1372. }
  1373. ],
  1374. 'excite': [
  1375. {
  1376. parentSelector: 'div.web-bing__result',
  1377. linkNodeSelector: 'a.web-bing__title',
  1378. textNodeSelector: 'span.web-bing__url',
  1379. updateTextByOverwrite: true,
  1380. urlDisplayMethod: 2
  1381. }
  1382. ],
  1383. 'webcrawler': [
  1384. {
  1385. parentSelector: 'div.web-bing__result',
  1386. linkNodeSelector: 'a.web-bing__title',
  1387. textNodeSelector: 'span.web-bing__url',
  1388. updateTextByOverwrite: true,
  1389. urlDisplayMethod: 2
  1390. }
  1391. ],
  1392. 'metacrawler': [
  1393. {
  1394. parentSelector: 'div.web-bing__result',
  1395. linkNodeSelector: 'a.web-bing__title',
  1396. textNodeSelector: 'span.web-bing__url',
  1397. updateTextByOverwrite: true,
  1398. urlDisplayMethod: 2
  1399. }
  1400. ],
  1401. 'dogpile': [
  1402. {
  1403. parentSelector: 'div.web-bing__result',
  1404. linkNodeSelector: 'a.web-bing__title',
  1405. textNodeSelector: 'span.web-bing__url',
  1406. updateTextByOverwrite: true,
  1407. urlDisplayMethod: 2
  1408. }
  1409. ],
  1410. 'infospace': [
  1411. {
  1412. parentSelector: 'div.web-bing div.result',
  1413. linkNodeSelector: 'a.title',
  1414. textNodeSelector: 'span.url',
  1415. updateTextByOverwrite: true,
  1416. urlDisplayMethod: 2
  1417. }
  1418. ],
  1419. 'refseek': [
  1420. {
  1421. selector: 'div.sticky a'
  1422. },
  1423. {
  1424. parentSelector: 'div.gsc-webResult.gsc-result',
  1425. linkNodeSelector: 'a.gs-title',
  1426. textNodeSelector: 'div.gsc-url-top div.gs-visibleUrl-short',
  1427. updateTextByOverwrite: true,
  1428. urlDisplayMethod: 3
  1429. }
  1430. ],
  1431. 'zapmeta': [
  1432. {
  1433. parentSelector: 'ol.organic-results__list li',
  1434. linkNodeSelector: 'div.organic-results__title a',
  1435. textNodeSelector: 'div.organic-results__display-url',
  1436. updateTextByOverwrite: true,
  1437. useTopLevelDomain: true,
  1438. urlDisplayMethod: 3
  1439. }
  1440. ],
  1441. 'izito': [
  1442. {
  1443. parentSelector: 'ol.organic-results__list li',
  1444. linkNodeSelector: 'div.organic-results__title a',
  1445. textNodeSelector: 'div.organic-results__display-url',
  1446. updateTextByOverwrite: true,
  1447. useTopLevelDomain: true,
  1448. urlDisplayMethod: 3
  1449. }
  1450. ],
  1451. 'ask': [
  1452. {
  1453. selector: 'div.result-title a'
  1454. },
  1455. {
  1456. selector: 'div.result-url-section a',
  1457. childSelector: 'span.result-url',
  1458. updateChildText: true,
  1459. urlDisplayMethod: 3
  1460. }
  1461. ],
  1462. 'pronto': [
  1463. {
  1464. selector: 'div.result-title a'
  1465. },
  1466. {
  1467. selector: 'div.result-url-section a',
  1468. childSelector: 'span.result-url',
  1469. updateChildText: true,
  1470. urlDisplayMethod: 3
  1471. }
  1472. ],
  1473. 'anoox': [
  1474. {
  1475. selector: 'div.search_item div.ad_brief_desc a'
  1476. },
  1477. {
  1478. selector: 'div.search_item div.adv_url_con a',
  1479. updateTextByOverwrite: true,
  1480. urlDisplayMethod: 2
  1481. }
  1482. ]
  1483. // Additional search engines can be defined here...
  1484. };
  1485.  
  1486. // User-defined list of search engine instance URLs
  1487. const searchEngines = {
  1488. 'google': {
  1489. hosts: ['google.com'],
  1490. // search results container
  1491. // you can ignore this parameter if you don't want to set it, just delete it
  1492. // defult value is 'body'
  1493. resultContainerSelectors: ['div.GyAeWb#rcnt']
  1494. },
  1495. 'yahoo': {
  1496. hosts: ['search.yahoo.com'],
  1497. resultContainerSelectors: ['div#results div#cols']
  1498. },
  1499. 'yahoojp': {
  1500. hosts: ['search.yahoo.co.jp'],
  1501. resultContainerSelectors: ['div#contents div#contents__wrap']
  1502. },
  1503. 'yandex': {
  1504. hosts: [
  1505. 'yandex.com',
  1506. 'yandex.ru'
  1507. ],
  1508. resultContainerSelectors: ['div.main__container']
  1509. },
  1510. 'searx': {
  1511. hosts: [
  1512. 'search.disroot.org',
  1513. 'searx.tiekoetter.com',
  1514. 'search.bus-hit.me',
  1515. 'search.inetol.net',
  1516. 'priv.au',
  1517. 'searx.be',
  1518. 'searxng.site',
  1519. 'search.hbubli.cc',
  1520. 'search.im-in.space',
  1521. 'opnxng.com',
  1522. 'search.upinmars.com',
  1523. 'search.sapti.me',
  1524. 'freesearch.club',
  1525. 'xo.wtf',
  1526. 'www.gruble.de',
  1527. 'searx.tuxcloud.net',
  1528. 'baresearch.org',
  1529. 'searx.daetalytica.io',
  1530. 'etsi.me',
  1531. 'search.leptons.xyz',
  1532. 'search.rowie.at',
  1533. 'search.mdosch.de',
  1534. 'searx.catfluori.de',
  1535. 'searx.si',
  1536. 'searx.namejeff.xyz',
  1537. 'search.itstechtime.com',
  1538. 's.mble.dk',
  1539. 'searx.kutay.dev',
  1540. 'ooglester.com',
  1541. 'searx.ox2.fr',
  1542. 'searx.techsaviours.org',
  1543. 'searx.perennialte.ch',
  1544. 's.trung.fun',
  1545. 'search.in.projectsegfau.lt',
  1546. 'search.projectsegfau.lt',
  1547. 'darmarit.org',
  1548. 'searx.lunar.icu',
  1549. 'nyc1.sx.ggtyler.dev',
  1550. 'search.rhscz.eu',
  1551. 'paulgo.io',
  1552. 'northboot.xyz',
  1553. 'searx.zhenyapav.com',
  1554. 'searxng.ch',
  1555. 'copp.gg',
  1556. 'searx.sev.monster',
  1557. 'searx.oakleycord.dev',
  1558. 'searx.juancord.xyz',
  1559. 'searx.work',
  1560. 'search.ononoki.org',
  1561. 'search.demoniak.ch',
  1562. 'searx.cthd.icu',
  1563. 'searx.fmhy.net',
  1564. 'searx.headpat.exchange',
  1565. 'sex.finaltek.net',
  1566. 'search.gcomm.ch',
  1567. 'search.smnz.de',
  1568. 'searx.ankha.ac',
  1569. 'search.lvkaszus.pl',
  1570. 'searx.nobulart.com',
  1571. 'sx.t-1.org',
  1572. 'www.jabber-germany.de',
  1573. 'sx.catgirl.cloud'
  1574. ],
  1575. resultContainerSelectors: [
  1576. 'main#main_results'
  1577. // 'maindiv#main_results div#urls'
  1578. // 'div#sidebar div#infoboxes'
  1579. ]
  1580. },
  1581. 'startpage': {
  1582. hosts: ['startpage.com'],
  1583. resultContainerSelectors: [
  1584. 'div.show-results',
  1585. ]
  1586. },
  1587. 'brave': {
  1588. hosts: ['search.brave.com'],
  1589. resultContainerSelectors: [
  1590. 'main.main-column',
  1591. 'aside.sidebar'
  1592. ]
  1593. },
  1594. 'duckduckgo': {
  1595. hosts: ['duckduckgo.com'],
  1596. resultContainerSelectors: [
  1597. 'section[data-testid="mainline"][data-area="mainline"]',
  1598. 'section[data-testid="sidebar"][data-area="sidebar"]'
  1599. ]
  1600. },
  1601. 'ghostery': {
  1602. hosts: ['ghosterysearch.com'],
  1603. resultContainerSelectors: ['section.results']
  1604. },
  1605. 'presearch': {
  1606. hosts: ['presearch.com'],
  1607. resultContainerSelectors: ['div.w-full']
  1608. },
  1609. 'metager': {
  1610. hosts: [
  1611. 'metager.org',
  1612. 'metager.de'
  1613. ],
  1614. resultContainerSelectors: [
  1615. 'div#results',
  1616. 'div#additions-container'
  1617. ]
  1618. },
  1619. '4get': {
  1620. hosts: [
  1621. '4get.ca',
  1622. '4get.silly.computer',
  1623. '4get.plunked.party',
  1624. '4get.konakona.moe',
  1625. '4get.sijh.net',
  1626. '4get.hbubli.cc',
  1627. '4get.perennialte.ch',
  1628. '4get.zzls.xyz',
  1629. '4getus.zzls.xyz',
  1630. '4get.seitan-ayoub.lol',
  1631. '4get.dcs0.hu',
  1632. '4get.psily.garden',
  1633. '4get.lvkaszus.pl',
  1634. '4get.kizuki.lol'
  1635. ],
  1636. resultContainerSelectors: ['div#overflow']
  1637. },
  1638. 'librey': {
  1639. hosts: [
  1640. 'search.ahwx.org',
  1641. 'search2.ahwx.org',
  1642. 'search3.ahwx.org',
  1643. 'ly.owo.si',
  1644. 'librey.franklyflawless.org',
  1645. 'librey.org',
  1646. 'search.davidovski.xyz',
  1647. 'search.milivojevic.in.rs',
  1648. 'glass.prpl.wtf',
  1649. 'librex.uk.to',
  1650. 'librey.ix.tc',
  1651. 'search.funami.tech',
  1652. 'librex.retro-hax.net',
  1653. 'librex.nohost.network',
  1654. 'search.pabloferreiro.es',
  1655. 'librey.baczek.me',
  1656. 'lx.benike.me',
  1657. 'search.seitan-ayoub.lol',
  1658. 'librey.myroware.net',
  1659. 'librey.nezumi.party',
  1660. 'search.zeroish.xyz',
  1661. 'search.zeroish.xyz'
  1662. ],
  1663. resultContainerSelectors: [
  1664. 'div.text-result-container',
  1665. 'p.special-result-container'
  1666. ]
  1667. },
  1668. 'stract': {
  1669. hosts: ['stract.com'],
  1670. resultContainerSelectors: [
  1671. 'div.col-start-1',
  1672. 'div.row-start-2'
  1673. ]
  1674. },
  1675. 'etools': {
  1676. hosts: ['etools.ch'],
  1677. // resultContainerSelectors: ['table.result']
  1678. },
  1679. 'mojeek': {
  1680. hosts: ['mojeek.com'],
  1681. resultContainerSelectors: ['div.container.serp-results']
  1682. },
  1683. 'yep': {
  1684. hosts: ['yep.com']
  1685. },
  1686. 'torry': {
  1687. hosts: ['torry.io'],
  1688. resultContainerSelectors: ['div.searpListouterappend'],
  1689. attribute: 'data-target'
  1690. },
  1691. 'qwant': {
  1692. hosts: ['qwant.com'],
  1693. resultContainerSelectors: ['div._35zId']
  1694. },
  1695. 'ecosia': {
  1696. hosts: ['ecosia.org'],
  1697. resultContainerSelectors: [
  1698. 'section.mainline.web__mainline',
  1699. 'aside.sidebar.web__sidebar'
  1700. ]
  1701. },
  1702. 'oscobo': {
  1703. hosts: ['search.becovi.com'],
  1704. resultContainerSelectors: ['div#results.col']
  1705. },
  1706. 'good': {
  1707. hosts: ['good-search.org'],
  1708. resultContainerSelectors: [
  1709. 'div.grid__item.two-thirds',
  1710. 'div.grid__item.one-third'
  1711. ]
  1712. },
  1713. 'alltheinternet': {
  1714. hosts: ['alltheinternet.com']
  1715. },
  1716. 'searchalot': {
  1717. hosts: ['searchalot.com']
  1718. },
  1719. 'aol': {
  1720. hosts: ['search.aol.com'],
  1721. resultContainerSelectors: ['div#results div#cols']
  1722. },
  1723. 'onesearch': {
  1724. hosts: ['onesearch.com'],
  1725. resultContainerSelectors: ['div#results div#cols']
  1726. },
  1727. 'info': {
  1728. hosts: ['info.com'],
  1729. resultContainerSelectors: ['div.layout__body']
  1730. },
  1731. 'oceanhero': {
  1732. hosts: ['oceanhero.today']
  1733. },
  1734. 'swisscows': {
  1735. hosts: ['swisscows.com'],
  1736. resultContainerSelectors: ['section.container.page-results']
  1737. },
  1738. 'lilo': {
  1739. hosts: ['search.lilo.org'],
  1740. resultContainerSelectors: ['div.container#content']
  1741. },
  1742. 'entireweb': {
  1743. hosts: ['search.entireweb.com'],
  1744. resultContainerSelectors: ['div.container.search-container']
  1745. },
  1746. 'tadadoo': {
  1747. hosts: ['tadadoo.com']
  1748. },
  1749. 'gmx': {
  1750. hosts: ['search.gmx.com']
  1751. },
  1752. 'youcare': {
  1753. hosts: ['youcare.world']
  1754. },
  1755. 'lycos': {
  1756. hosts: ['search.lycos.com'],
  1757. resultContainerSelectors: ['div.content.con-search']
  1758. },
  1759. 'alohafind': {
  1760. hosts: ['alohafind.com'],
  1761. resultContainerSelectors: ['section.layout']
  1762. },
  1763. 'spot': {
  1764. hosts: ['spot.ecloud.global'],
  1765. resultContainerSelectors: ['div.container.contents']
  1766. },
  1767. 'qmamu': {
  1768. hosts: ['qmamu.com'],
  1769. resultContainerSelectors: ['div.sc-7aqnu-1.ffCHAv']
  1770. },
  1771. 'carrot2': {
  1772. hosts: ['search.carrot2.org'],
  1773. resultContainerSelectors: ['div.Views']
  1774. },
  1775. 'nona': {
  1776. hosts: ['nona.de'],
  1777. resultContainerSelectors: ['main.search-results div.container']
  1778. },
  1779. 'sapo': {
  1780. hosts: ['sapo.pt'],
  1781. resultContainerSelectors: ['div.content div.ink-tabs.top']
  1782. },
  1783. 'exalead': {
  1784. hosts: ['exalead.com'],
  1785. resultContainerSelectors: ['ul.media-list']
  1786. },
  1787. 'goo': {
  1788. hosts: ['search.goo.ne.jp'],
  1789. resultContainerSelectors: [
  1790. 'section[role="main"] div.section#main',
  1791. 'section[role="main"] aside[role="complementary"]'
  1792. ],
  1793. },
  1794. 'seznam': {
  1795. hosts: ['search.seznam.cz'],
  1796. resultContainerSelectors: ['div.PageWrapper.SearchPage#searchpage-root'],
  1797. },
  1798. 'startsiden': {
  1799. hosts: ['startsiden.no'],
  1800. resultContainerSelectors: ['div.results ul.results__list'],
  1801. },
  1802. 'marginalia': {
  1803. hosts: ['search.marginalia.nu'],
  1804. resultContainerSelectors: ['section.sidebar-narrow section#results'],
  1805. },
  1806. 'naver': {
  1807. hosts: ['search.naver.com'],
  1808. resultContainerSelectors: ['div#main_pack.main_pack'],
  1809. },
  1810. 'gibiru': {
  1811. hosts: ['gibiru.com'],
  1812. resultContainerSelectors: ['div.container#web-results'],
  1813. },
  1814. 'lukol': {
  1815. hosts: ['lukol.com']
  1816. },
  1817. 'draze': {
  1818. hosts: ['draze.com'],
  1819. resultContainerSelectors: ['div.container div#content'],
  1820. },
  1821. 'yelliot': {
  1822. hosts: ['yelliot.com']
  1823. },
  1824. 'efind': {
  1825. hosts: ['efind.com'],
  1826. resultContainerSelectors: ['main#main_results'],
  1827. },
  1828. 'fireball': {
  1829. hosts: ['fireball.de'],
  1830. resultContainerSelectors: ['div.search-results'],
  1831. },
  1832. 'freespoke': {
  1833. hosts: ['freespoke.com'],
  1834. resultContainerSelectors: ['div.WebSearch div.wrapper'],
  1835. },
  1836. 'gogoprivate': {
  1837. hosts: ['gogoprivate.com'],
  1838. resultContainerSelectors: ['div#cse-body'],
  1839. },
  1840. 'resulthunter': {
  1841. hosts: ['resulthunter.com'],
  1842. resultContainerSelectors: ['main.main-content#content'],
  1843. },
  1844. 'givewater': {
  1845. hosts: ['search.givewater.com'],
  1846. resultContainerSelectors: ['div.mainline-results']
  1847. },
  1848. 'excite': {
  1849. hosts: ['results.excite.com'],
  1850. resultContainerSelectors: ['div.mainline-results']
  1851. },
  1852. 'webcrawler': {
  1853. hosts: ['webcrawler.com'],
  1854. resultContainerSelectors: ['div.web-bing'],
  1855. },
  1856. 'metacrawler': {
  1857. hosts: ['metacrawler.com'],
  1858. resultContainerSelectors: ['div.web-bing'],
  1859. },
  1860. 'dogpile': {
  1861. hosts: ['dogpile.com'],
  1862. resultContainerSelectors: ['div.web-bing'],
  1863. },
  1864. 'infospace': {
  1865. hosts: ['infospace.com'],
  1866. resultContainerSelectors: ['div.layout div.layout__body'],
  1867. },
  1868. 'refseek': {
  1869. hosts: ['refseek.com'],
  1870. resultContainerSelectors: ['div.main__container div.main__content'],
  1871. },
  1872. 'zapmeta': {
  1873. hosts: ['zapmeta.com'],
  1874. resultContainerSelectors: ['div.component-container__main ol.organic-results__list'],
  1875. },
  1876. 'izito': {
  1877. hosts: ['izito.com'],
  1878. resultContainerSelectors: ['div.component-container__main ol.organic-results__list'],
  1879. },
  1880. 'ask': {
  1881. hosts: ['ask.com'],
  1882. resultContainerSelectors: ['div.search-results div.results'],
  1883. },
  1884. 'pronto': {
  1885. hosts: ['pronto.com'],
  1886. resultContainerSelectors: ['div.search-results div.results'],
  1887. },
  1888. 'anoox': {
  1889. hosts: ['anoox.com'],
  1890. resultContainerSelectors: ['div#main_srch_window div#se_holder_center'],
  1891. }
  1892. // ... more search engines
  1893. };
  1894.  
  1895. // Function to modify URLs and optionally text
  1896. const modifyUrls = (engine, observer, resultContainer, engineInfo) => {
  1897. try {
  1898. const selectors = selectorRules[engine];
  1899. if (selectors) {
  1900. // Disconnect the observer to prevent recursive triggering
  1901. observer.disconnect();
  1902.  
  1903. // Modify results
  1904. selectors.forEach(rule => {
  1905. if (rule.selector) {
  1906. processElements(rule.selector, rule, engineInfo);
  1907. } else if (rule.parentSelector) {
  1908. processParentElements(rule.parentSelector, rule, engineInfo);
  1909. }
  1910. });
  1911.  
  1912. // Reconnect the observer after DOM modifications are done
  1913. observer.observe(resultContainer, { childList: true, subtree: true });
  1914. }
  1915. } catch (error) {
  1916. console.error("URL Modification Error: ", error);
  1917. }
  1918. };
  1919.  
  1920. // Function to process elements specified by `selector`
  1921. const processElements = (selector, rule, engineInfo) => {
  1922. const elements = document.querySelectorAll(selector);
  1923. const additionalAttribute = engineInfo.attribute; // Get the additional attribute if specified
  1924. if (elements.length > 0) {
  1925. elements.forEach(element => {
  1926. for (let i = 0; i < urlModificationRules.length; i++) {
  1927. try {
  1928. const urlRule = urlModificationRules[i];
  1929. let urlToModify = additionalAttribute ? element.getAttribute(additionalAttribute) : element.href;
  1930. urlToModify = decodeURIComponent(urlToModify);
  1931. // update attribute
  1932. if (urlToModify && urlRule.matchRegex.test(urlToModify)) {
  1933. // Generate redirected URL
  1934. let newUrl = urlToModify.replace(urlRule.matchRegex, urlRule.replaceWith);
  1935. newUrl = rule.useTopLevelDomain ? extractTopLevelDomain(newUrl) : newUrl;
  1936. if (element.href) {
  1937. element.href = newUrl;
  1938. } else if (additionalAttribute) {
  1939. element.setAttribute(additionalAttribute, newUrl);
  1940. }
  1941. updateTextContent(element, rule, removeTailingSlash(removeParameters(newUrl)));
  1942. break;
  1943. }
  1944. } catch (error) {
  1945. console.error("Update Link/Text Error: ", error);
  1946. }
  1947. }
  1948. });
  1949. }
  1950. };
  1951.  
  1952. // Function to process elements specified by `parentSelector`
  1953. const processParentElements = (selector, rule, engineInfo) => {
  1954. const elements = document.querySelectorAll(selector);
  1955. const additionalAttribute = engineInfo.attribute; // Get the additional attribute if specified
  1956. if (elements.length > 0) {
  1957. elements.forEach(element => {
  1958. const linkElement = element.querySelector(rule.linkNodeSelector);
  1959. const textElement = element.querySelector(rule.textNodeSelector);
  1960.  
  1961. for (let i = 0; i < urlModificationRules.length; i++) {
  1962. try {
  1963. const urlRule = urlModificationRules[i];
  1964. let urlToModify = additionalAttribute ? element.getAttribute(additionalAttribute) : linkElement.href;
  1965. urlToModify = decodeURIComponent(urlToModify);
  1966. // update attribute
  1967. if (urlToModify && urlRule.matchRegex.test(urlToModify)) {
  1968. // Generate redirected URL
  1969. let newUrl = urlToModify.replace(urlRule.matchRegex, urlRule.replaceWith);
  1970. newUrl = rule.useTopLevelDomain ? extractTopLevelDomain(newUrl) : newUrl;
  1971. if (linkElement.href) {
  1972. linkElement.href = newUrl;
  1973. } else if (additionalAttribute) {
  1974. linkElement.setAttribute(additionalAttribute, newUrl);
  1975. }
  1976. updateTextContent(textElement, rule, removeTailingSlash(removeParameters(newUrl)));
  1977. break;
  1978. }
  1979. } catch (error) {
  1980. console.error("Update Link/Text Error: ", error);
  1981. }
  1982. }
  1983. });
  1984. }
  1985. };
  1986.  
  1987. // Function to update text content (displayed URL)
  1988. const updateTextContent = (element, rule, newUrl) => {
  1989. if (rule.updateChildText || rule.updateTextWithoutOverwrite || rule.updateTextByOverwrite) {
  1990. try {
  1991. if (rule.multiElementsForUrlDisplay) {
  1992. updateMultiElementContent(element, rule, newUrl);
  1993. } else {
  1994. const targetElement = rule.childSelector ? element.querySelector(rule.childSelector) : element;
  1995. updateSingleElementText(targetElement, rule, newUrl);
  1996. }
  1997. } catch (error) {
  1998. console.error("Update Displayed URL Error: ", error);
  1999. }
  2000. }
  2001. };
  2002.  
  2003. // Function to update text for multi elements (e.g. DuckDuckGo, Brave)
  2004. const updateMultiElementContent = (targetElement, rule, newUrl) => {
  2005. if (!targetElement) {
  2006. console.error("Target DOM Element not found for Multi-Element Text update!");
  2007. return;
  2008. }
  2009. // Remove the "https://" protocol if containProtocol is false
  2010. newUrl = rule.containProtocol ? newUrl : removeProtocol(newUrl);
  2011. let formattedUrl = breadCumbFormat(newUrl, rule.containProtocol);
  2012. let urlParts = formattedUrl.split(' › ');
  2013.  
  2014. const spans = targetElement.querySelectorAll(rule.childSelector)
  2015.  
  2016. switch (rule.multiElementsForUrlDisplay) {
  2017. case 1:
  2018. parallelElements(urlParts, spans);
  2019. break;
  2020. case 2:
  2021. mixedElements(urlParts, spans, targetElement);
  2022. break;
  2023. case 3:
  2024. mixedElementsWithoutClear(urlParts, spans, targetElement);
  2025. break;
  2026. case 4:
  2027. fourGetSearchElements(newUrl, spans, targetElement);
  2028. }
  2029. };
  2030.  
  2031. // Case where URL parts are scattered into parallel elements
  2032. const parallelElements = (urlParts, elements) => {
  2033. if (elements && elements.length >= 2) {
  2034. elements.forEach(clearElementContent);
  2035. elements[0].textContent = urlParts[0]; // Update the first part
  2036. elements[1].textContent = ' › ' + urlParts.slice(1).join(' › '); // Update the second part
  2037. } else {
  2038. console.error("Script: Expected structure not found for Multi-Element (parallel elements) URL update!");
  2039. }
  2040. };
  2041.  
  2042. // Case where URL parts are scattered into non-parallel elements
  2043. const mixedElements = (urlParts, elements, parent) => {
  2044. if (elements && elements.length >= 1) {
  2045. elements.forEach(clearElementContent);
  2046. updateTextWithoutOverwriteChildNodes(parent, urlParts[0]); // Update the first part
  2047. elements[0].textContent = ' › ' + urlParts.slice(1).join(' › '); // Update the second part
  2048. } else {
  2049. console.error("Script: Expected structure not found for Multi-Element (mixed elements) URL update!");
  2050. }
  2051. };
  2052.  
  2053. // Same as case 2, but update elements without clearing their original contents
  2054. const mixedElementsWithoutClear = (urlParts, elements, parent) => {
  2055. if (elements && elements.length >= 1) {
  2056. updateTextWithoutOverwriteChildNodes(parent, urlParts[0]); // Update the first part
  2057. elements[0].textContent = ' › ' + urlParts.slice(1).join(' › '); // Update the second part
  2058. } else {
  2059. console.error("Script: Expected structure not found for Multi-Element (mixed elements with clear) URL update!");
  2060. }
  2061. };
  2062.  
  2063. // Case where search engine is 4get
  2064. const fourGetSearchElements = (newUrl, elements, parent) => {
  2065. // Convert NodeList to Array if necessary
  2066. const elementsArray = Array.isArray(elements) ? elements : Array.from(elements);
  2067.  
  2068. // Split the new URL into parts
  2069. const urlParts = splitUrlIntoParts(newUrl);
  2070.  
  2071. // Ensure the elements array length matches the number of URL parts
  2072. matchElementNumWithPartsFor4Get(urlParts, elementsArray, parent);
  2073.  
  2074. let prevCombinedLink = '';
  2075. // Update or add new elements based on the urlParts
  2076. urlParts.forEach((part, index) => {
  2077. let element = elementsArray[index];
  2078. if (!element) {
  2079. element = createPartElementFor4Get(parent);
  2080. elementsArray.push(element);
  2081. }
  2082. prevCombinedLink += part + '/';
  2083. element.href = prevCombinedLink;
  2084. element.textContent = part;
  2085. // Handle separators
  2086. if (index < urlParts.length - 1 && (!element.nextSibling || element.nextSibling.className !== 'separator')) {
  2087. let separator = createSeparatorElementFor4Get();
  2088. parent.insertBefore(separator, element.nextSibling);
  2089. }
  2090. });
  2091.  
  2092. // Remove any extra elements if the new URL has fewer parts than existing elements
  2093. while (elementsArray.length > urlParts.length) {
  2094. const elementToRemove = elementsArray.pop();
  2095. const separator = elementToRemove.nextSibling;
  2096. if (separator && separator.className === 'separator') {
  2097. separator.remove();
  2098. }
  2099. elementToRemove.remove();
  2100. }
  2101. };
  2102.  
  2103. // 4get specific fucntion
  2104. // Ensure the elements array length matches the number of URL parts, if not, add new < a > elements
  2105. const matchElementNumWithPartsFor4Get = (urlParts, elements, parent) => {
  2106. while (elements.length < urlParts.length) {
  2107. const newElement = createPartElementFor4Get(parent);
  2108. parent.appendChild(newElement);
  2109. elements.push(newElement);
  2110. }
  2111. };
  2112.  
  2113. // 4get specific fucntion
  2114. // Create a new <a> element that represents a URL component
  2115. const createPartElementFor4Get = () => {
  2116. const element = document.createElement('a');
  2117. element.className = 'part';
  2118. element.setAttribute('rel', 'noreferrer nofollow');
  2119. element.setAttribute('tabindex', '-1');
  2120. return element;
  2121. };
  2122.  
  2123. // 4get specific fucntion
  2124. // Create a new <span> element that represents a URL separator '/'
  2125. const createSeparatorElementFor4Get = () => {
  2126. const separator = document.createElement('span');
  2127. separator.className = 'separator';
  2128. return separator;
  2129. };
  2130.  
  2131. // Function to update text for a single element
  2132. const updateSingleElementText = (targetElement, rule, newUrl) => {
  2133. if (!targetElement) {
  2134. console.error("Target DOM Element not found for Single-Element Text update!");
  2135. return;
  2136. }
  2137. let formattedUrl = '';
  2138. switch (rule.urlDisplayMethod) {
  2139. case 1:
  2140. formattedUrl = breadCumbFormat(newUrl, rule.containProtocol);
  2141. break;
  2142. case 2:
  2143. formattedUrl = newUrl; // Full URL with protocol
  2144. break;
  2145. case 3:
  2146. formattedUrl = decodeURIComponent(removeProtocol(newUrl)); // Full URL without protocol
  2147. break;
  2148. }
  2149. if (rule.updateTextWithoutOverwrite) {
  2150. updateTextWithoutOverwriteChildNodes(targetElement, formattedUrl);
  2151. } else if (rule.updateTextByOverwrite) {
  2152. updateTextByOverwriteEverything(targetElement, formattedUrl);
  2153. } else {
  2154. targetElement.textContent = formattedUrl;
  2155. }
  2156. };
  2157.  
  2158. // Format URLs into Breadcrumb style, while leaving 'https://' intact
  2159. const breadCumbFormat = (url, containProtocol) => {
  2160. if (!containProtocol) {
  2161. url = removeProtocol(url);
  2162. }
  2163.  
  2164. const urlParts = splitUrlIntoParts(url, containProtocol);
  2165.  
  2166. // Join the URL parts with ' › '
  2167. const joinedUrl = urlParts.join(' › ');
  2168.  
  2169. // Decode the URL to convert encoded characters to their original form
  2170. return decodeURIComponent(joinedUrl);
  2171. };
  2172.  
  2173. // Function to update only the text node within an element, leave the child elements, if exist, intact
  2174. const updateTextWithoutOverwriteChildNodes = (element, newContent) => {
  2175. let currentIndex = 0;
  2176. const indexObject = { currentIndex };
  2177. collectNodes(element, node => {
  2178. if (currentIndex >= newContent.length) return; // Stop if we've used all the new content
  2179. replaceTextContent(node, oldText => replaceTextBasedOnIndex(oldText, newContent, indexObject));
  2180. });
  2181. };
  2182.  
  2183. // Function to collect all text nodes within an element
  2184. const collectNodes = (node, callback) => {
  2185. // View these elements as text node
  2186. const elementsToIncludeAsText = ['B'];
  2187. // Do not view these elements as text node
  2188. const elementsToExcludeAsText = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'P'];
  2189.  
  2190. if (node.nodeType === Node.TEXT_NODE) {
  2191. callback(node);
  2192. } else if (node.nodeType === Node.ELEMENT_NODE && elementsToIncludeAsText.includes(node.tagName.toUpperCase())) {
  2193. callback(node);
  2194. } else if (node.nodeType === Node.ELEMENT_NODE && !elementsToExcludeAsText.includes(node.tagName.toUpperCase())) {
  2195. node.childNodes.forEach(child => collectNodes(child, callback));
  2196. }
  2197. };
  2198.  
  2199. // Function to replace the text content of a node
  2200. const replaceTextContent = (node, textUpdater) => {
  2201. if (node.nodeType === Node.TEXT_NODE) {
  2202. node.nodeValue = textUpdater(node.nodeValue);
  2203. } else if (node.innerHTML) { // For elements treated as text, like <b>
  2204. node.innerHTML = textUpdater(node.innerHTML);
  2205. }
  2206. };
  2207.  
  2208. // Function to replace text based on index
  2209. const replaceTextBasedOnIndex = (oldText, newContent, indexObject) => {
  2210. const newText = newContent.slice(indexObject.currentIndex, indexObject.currentIndex + oldText.length);
  2211. indexObject.currentIndex += oldText.length;
  2212. return newText;
  2213. };
  2214.  
  2215. // Function to update the content by overwriting everything
  2216. const updateTextByOverwriteEverything = (element, newContent) => {
  2217. clearElementContent(element);
  2218. element.textContent = newContent;
  2219. };
  2220.  
  2221. // Split URL into components, while preserving 'https://' in all occurrences
  2222. const splitUrlIntoParts = (url, containProtocol) => {
  2223. // Temporary replace 'https://' with a placeholder that is unlikely to be part of any URL
  2224. const placeholder = "HTTPS_PLACEHOLDER";
  2225. let tempUrl = url.replace(/https:\/\//g, placeholder);
  2226.  
  2227. // Split the URL by '/'
  2228. let parts = tempUrl.split('/');
  2229.  
  2230. // Replace the placeholder back with 'https://'
  2231. parts = parts.map(part => part.replace(new RegExp(placeholder, 'g'), 'https://'));
  2232.  
  2233. // Filter out any empty strings that may have resulted from the split
  2234. parts = parts.filter(part => part !== '');
  2235.  
  2236. // Ensure the first part always starts with 'https://', adjusting if necessary
  2237. if (containProtocol && parts.length > 0 && !parts[0].startsWith('https://')) {
  2238. parts[0] = 'https://' + parts[0];
  2239. }
  2240.  
  2241. return parts;
  2242. };
  2243.  
  2244. // Extract the top level domain from URL link
  2245. const extractTopLevelDomain = (url) => {
  2246. const parsedUrl = new URL(url);
  2247. return `${parsedUrl.protocol}//${parsedUrl.hostname}/`;
  2248. };
  2249.  
  2250. // Remove 'https://' from the URL link
  2251. const removeProtocol = (url) => {
  2252. return url.replace(/^https?:\/\//, '');
  2253. };
  2254.  
  2255. // Remove parameters (the part behind ?) in the URL link
  2256. const removeParameters = (url) => {
  2257. return url.split('?')[0];
  2258. };
  2259.  
  2260. // Remove tailing slash '/'
  2261. const removeTailingSlash = (url) => {
  2262. // Check if the URL ends with a slash and remove it if present
  2263. return url.endsWith('/') ? url.slice(0, -1) : url;
  2264. };
  2265.  
  2266. // Function to clear existing content of an element
  2267. const clearElementContent = (element) => {
  2268. element.textContent = '';
  2269. };
  2270.  
  2271. // Improved function to determine the search engine
  2272. const getSearchEngineInfo = () => {
  2273. try {
  2274. const host = window.location.host;
  2275. for (const engine in searchEngines) {
  2276. if (searchEngines[engine].hosts.some(instanceHost => host.includes(instanceHost))) {
  2277. // Default to 'body' if not specified
  2278. const selectors = searchEngines[engine].resultContainerSelectors || ['body'];
  2279. // Get the attribute if specified
  2280. const attribute = searchEngines[engine].attribute;
  2281. return {
  2282. engine,
  2283. selectors: selectors,
  2284. attribute: attribute
  2285. };
  2286. }
  2287. }
  2288. } catch (error) {
  2289. console.error("Error determining search engine: ", error);
  2290. }
  2291. };
  2292.  
  2293. // Function to observe and execute the URL modifier script
  2294. const observeToExecute = (engine, selector, engineInfo) => {
  2295. const resultContainers = document.querySelectorAll(selector);
  2296. if (resultContainers) {
  2297. resultContainers.forEach(resultContainer => {
  2298. // Observe changes in each result container
  2299. const observer = new MutationObserver(() => modifyUrls(engine, observer, resultContainer, engineInfo));
  2300. observer.observe(resultContainer, { childList: true, subtree: true });
  2301. modifyUrls(engine, observer, resultContainer, engineInfo);
  2302. });
  2303. }
  2304. };
  2305.  
  2306. // Run the script for the current search engine
  2307. try {
  2308. const engineInfo = getSearchEngineInfo();
  2309. if (engineInfo) {
  2310. engineInfo.selectors.forEach(containerSelector => {
  2311. observeToExecute(engineInfo.engine, containerSelector, engineInfo);
  2312. });
  2313. }
  2314. } catch (error) {
  2315. console.error("Error executing URL Modifier Script: ", error);
  2316. }
  2317. })();