2023-07-25 06:17:46 +00:00
const currentURL = new URL ( document . location ) ;
2023-08-04 05:50:12 +00:00
let filteredWikis = [ ] ;
2023-08-07 06:43:23 +00:00
let hiddenWikisRevealed = { } ;
2023-07-25 06:17:46 +00:00
// Create object prototypes for getting and setting attributes:
Object . prototype . get = function ( prop ) {
this [ prop ] = this [ prop ] || { } ;
return this [ prop ] ;
} ;
Object . prototype . set = function ( prop , value ) {
this [ prop ] = value ;
}
// Function to create an observer to watch for mutations on search pages
2023-11-06 02:25:47 +00:00
// This is used for search engines that paginate via JavaScript,
// or overwrite their results and remove IWB's elements
2023-07-25 06:17:46 +00:00
function addLocationObserver ( callback ) {
const config = {
attributes : false ,
childList : true ,
subtree : true
}
const observer = new MutationObserver ( callback ) ;
observer . observe ( document . body , config ) ;
}
// Load website data:
async function getData ( ) {
const LANGS = [ "DE" , "EN" , "ES" , "FR" , "IT" , "PL" , "TOK" ] ;
let sites = [ ] ;
let promises = [ ] ;
for ( let i = 0 ; i < LANGS . length ; i ++ ) {
promises . push ( fetch ( chrome . runtime . getURL ( 'data/sites' + LANGS [ i ] + '.json' ) )
. then ( ( resp ) => resp . json ( ) )
. then ( function ( jsonData ) {
jsonData . forEach ( ( site ) => {
site . origins . forEach ( ( origin ) => {
sites . push ( {
"id" : site . id ,
"origin" : origin . origin ,
2023-08-04 05:50:12 +00:00
"origin_group" : site . origins _label ,
2023-07-25 06:17:46 +00:00
"origin_base_url" : origin . origin _base _url ,
"origin_content_path" : origin . origin _content _path ,
"destination" : site . destination ,
"destination_base_url" : site . destination _base _url ,
"destination_content_path" : site . destination _content _path ,
"destination_content_prefix" : ( site . destination _content _prefix ? site . destination _content _prefix : "" ) ,
"destination_platform" : site . destination _platform ,
"destination_icon" : site . destination _icon ,
"lang" : LANGS [ i ]
} )
} )
} ) ;
} ) ) ;
}
await Promise . all ( promises ) ;
2023-08-04 05:50:12 +00:00
2023-07-25 06:17:46 +00:00
return sites ;
}
2023-08-04 05:50:12 +00:00
function insertCSS ( ) {
// Output CSS
styleString = `
. iwb - notice {
2023-08-07 06:43:23 +00:00
display : block ! important ;
2023-08-04 05:50:12 +00:00
margin : . 5 em . 5 em 1 em . 5 em ! important ;
padding : . 5 em . 5 em . 5 em 1 em ! important ;
border - left : 3 px solid # FFCC33 ! important ;
font - size : 14 px ! important ;
color : white ! important ;
mix - blend - mode : difference ! important ;
}
. iwb - notice a {
text - decoration : underline ! important ;
color : white ! important ;
mix - blend - mode : difference ! important ;
}
. iwb - notice button {
cursor : pointer ! important ;
2023-08-07 06:43:23 +00:00
display : inline - block ! important ;
2023-08-04 05:50:12 +00:00
padding : 2 px 8 px ! important ;
2023-08-07 06:43:23 +00:00
margin : 8 px 8 px 0 0 ! important ;
2023-08-04 05:50:12 +00:00
background - color : transparent ! important ;
2023-08-07 06:43:23 +00:00
border : 1 px solid ! important ;
2023-08-04 05:50:12 +00:00
border - radius : 5 px ! important ;
2023-09-18 07:41:42 +00:00
font - size : 12 px ! important ;
2023-08-04 05:50:12 +00:00
color : white ! important ;
mix - blend - mode : difference ! important ;
2023-08-07 06:43:23 +00:00
text - align : left ! important ;
}
2023-08-04 05:50:12 +00:00
. iwb - hide {
display : none ! important ;
}
. iwb - show {
display : block ! important ;
}
. iwb - notice button : hover {
outline : 1 px solid ! important ;
}
2023-11-03 09:20:45 +00:00
. iwb - new - link - container {
2023-10-16 05:47:02 +00:00
display : inline - block ;
font - size : 12 px ! important ;
text - decoration : none ;
padding - left : 5 px ;
position : relative ;
}
2023-11-03 09:20:45 +00:00
. iwb - new - link {
display : inline - block ;
text - decoration : none ;
position : relative ;
}
2023-10-16 05:47:02 +00:00
. iwb - new - link : hover {
text - decoration : none ;
z - index : 9999999 ;
}
. iwb - new - link button {
cursor : pointer ;
color : white ;
background : # 005799 ;
border : 0 px solid # fff ;
border - radius : 10 px ;
padding : 5 px 10 px ;
2023-11-02 08:35:34 +00:00
margin : . 5 em 0 ;
2023-10-16 05:47:02 +00:00
font - size : 1.2 em ;
width : fit - content ;
}
. iwb - new - link button : hover {
background : # 00467 a ;
}
. iwb - new - link button * {
vertical - align : middle ;
}
. iwb - new - link div : first - of - type {
display : inline - block ;
background : white ;
border - radius : 16 px ;
margin - right : 10 px ;
width : fit - content ;
height : fit - content ;
line - height : 12 px ;
padding : 5 px ;
}
. iwb - new - link img {
width : 12 px ;
}
2023-11-02 08:35:34 +00:00
. iwb - disavow > * : not ( [ class ^= "iwb-" ] ) {
2023-10-16 05:47:02 +00:00
opacity : 60 % ;
pointer - events : none ;
cursor : default ;
}
2023-11-02 08:35:34 +00:00
. iwb - disavow > a : not ( [ class ^= "iwb-" ] ) , . iwb - disavow > * : not ( [ class ^= "iwb-" ] ) a , . iwb - disavow > * : not ( [ class ^= "iwb-" ] ) a * {
2023-10-16 05:47:02 +00:00
text - decoration : line - through ! important ;
}
2023-11-02 08:35:34 +00:00
2023-11-03 09:20:45 +00:00
. iwb - result - controls {
display : inline - block ;
margin : . 5 em ;
2023-11-02 08:35:34 +00:00
font - size : 12 px ;
color : white ! important ;
mix - blend - mode : difference ! important ;
}
2023-11-03 09:20:45 +00:00
. iwb - result - controls > div {
2023-11-02 08:35:34 +00:00
display : inline - block ;
2023-11-03 09:20:45 +00:00
cursor : pointer ;
text - decoration : underline ;
text - decoration - style : dotted ;
text - decoration - thickness : 1 px ;
padding : 0 1 em ;
}
. iwb - notice . iwb - result - controls {
margin : 8 px 0 0 0 ;
}
2023-08-04 05:50:12 +00:00
`
style = document . createElement ( 'style' ) ;
2023-11-02 13:58:25 +00:00
style . classList . add ( 'iwb-styles' ) ;
2023-08-04 05:50:12 +00:00
style . textContent = styleString ;
document . head . append ( style ) ;
}
// Function to convert strings to consistent IDs
// Used to convert wiki names to element IDs
function stringToId ( string ) {
2023-08-31 05:16:15 +00:00
return string . replaceAll ( ' ' , '-' ) . replaceAll ( "'" , '' ) . replace ( /\W/g , '' ) . toLowerCase ( ) ;
2023-08-04 05:50:12 +00:00
}
2023-08-08 06:33:23 +00:00
// Function to escape string to use in regex
function escapeRegex ( string ) {
return string . replace ( /[.*+?^${}()|[\]\\]/g , '\\$&' ) ;
}
2023-11-02 08:35:34 +00:00
function replaceSearchResults ( searchResultContainer , site , link ) {
2023-10-16 05:47:02 +00:00
// Build new URL:
2023-11-06 00:59:24 +00:00
let article = link . split ( site [ 'origin_content_path' ] ) [ 1 ] ? . split ( '#' ) [ 0 ] . split ( '?' ) [ 0 ] . split ( '&' ) [ 0 ] ;
2023-10-16 05:47:02 +00:00
let newURL = '' ;
if ( article ) {
let searchParams = '' ;
switch ( site [ 'destination_platform' ] ) {
case 'mediawiki' :
searchParams = 'Special:Search/' + site [ 'destination_content_prefix' ] + article ;
break ;
case 'doku' :
searchParams = 'start?do=search&q=' + article ;
break ;
}
2023-11-03 09:20:45 +00:00
newURL = 'https://' + site [ 'destination_base_url' ] + site [ 'destination_content_path' ] + searchParams ;
2023-10-16 05:47:02 +00:00
} else {
2023-11-03 09:20:45 +00:00
newURL = 'https://' + site [ 'destination_base_url' ] ;
2023-10-16 05:47:02 +00:00
}
2023-11-06 00:59:24 +00:00
if ( searchResultContainer && ! searchResultContainer . querySelector ( '.iwb-new-link' ) ) {
if ( ! searchResultContainer . classList . contains ( 'iwb-detected' ) ) {
searchResultContainer . classList . add ( 'iwb-detected' ) ;
searchResultContainer . classList . add ( 'iwb-disavow' ) ;
}
2023-11-06 02:25:47 +00:00
// Using aside to avoid conflicts with website CSS and listeners:
2023-11-06 00:59:24 +00:00
let indieContainer = document . createElement ( 'aside' ) ;
2023-11-03 09:20:45 +00:00
indieContainer . classList . add ( 'iwb-new-link-container' ) ;
let indieResultLink = document . createElement ( 'a' ) ;
2023-10-16 05:47:02 +00:00
indieResultLink . href = newURL ;
indieResultLink . classList . add ( 'iwb-new-link' ) ;
2023-11-03 09:20:45 +00:00
let indieResultButton = document . createElement ( 'button' ) ;
let indieResultFaviconContainer = document . createElement ( 'div' ) ;
let indieResultFavicon = document . createElement ( 'img' ) ;
2023-10-16 05:47:02 +00:00
indieResultFavicon . alt = '' ;
indieResultFavicon . width = '12' ;
indieResultFavicon . height = '12' ;
indieResultFavicon . src = chrome . runtime . getURL ( 'favicons/' + site . lang . toLowerCase ( ) + '/' + site . destination _icon ) ;
indieResultFaviconContainer . append ( indieResultFavicon ) ;
2023-11-03 09:20:45 +00:00
let indieResultText = document . createElement ( 'span' ) ;
2023-10-16 05:47:02 +00:00
if ( article ) {
2023-11-06 00:59:24 +00:00
if ( site [ 'lang' ] === 'EN' && link . match ( /fandom\.com\/[a-z]{2}\/wiki\// ) ) {
indieResultText . innerText = 'Look up "' + decodeURIComponent ( decodeURIComponent ( article . replaceAll ( '_' , ' ' ) ) ) + '" on ' + site . destination + ' (EN)' ;
} else {
indieResultText . innerText = 'Look up "' + decodeURIComponent ( decodeURIComponent ( article . replaceAll ( '_' , ' ' ) ) ) + '" on ' + site . destination ;
}
2023-10-16 05:47:02 +00:00
} else {
2023-11-06 00:59:24 +00:00
if ( site [ 'lang' ] === 'EN' && link . match ( /fandom\.com\/[a-z]{2}\/wiki\// ) ) {
indieResultText . innerText = 'Visit ' + site . destination + ' (EN) instead' ;
} else {
indieResultText . innerText = 'Visit ' + site . destination + ' instead' ;
}
2023-10-16 05:47:02 +00:00
}
indieResultButton . append ( indieResultFaviconContainer ) ;
indieResultButton . append ( indieResultText ) ;
indieResultLink . appendChild ( indieResultButton ) ;
2023-11-03 09:20:45 +00:00
// Output container for result controls:
let resultControls = document . createElement ( 'div' ) ;
resultControls . classList . add ( 'iwb-result-controls' ) ;
2023-11-02 08:35:34 +00:00
// Output link to re-enable disabled result:
2023-11-03 09:20:45 +00:00
let enableResultButton = document . createElement ( 'div' ) ;
enableResultButton . innerText = 'Re-enable the result below' ;
resultControls . prepend ( enableResultButton ) ;
enableResultButton . addEventListener ( 'click' , function ( e ) {
2023-11-02 08:35:34 +00:00
e . target . closest ( '.iwb-disavow' ) . classList . remove ( 'iwb-disavow' ) ;
2023-11-03 09:20:45 +00:00
e . target . classList . add ( 'iwb-hide' ) ;
2023-11-02 08:35:34 +00:00
} ) ;
2023-11-03 09:20:45 +00:00
indieContainer . appendChild ( indieResultLink ) ;
indieContainer . appendChild ( resultControls ) ;
searchResultContainer . prepend ( indieContainer ) ;
2023-11-06 05:09:14 +00:00
2023-11-06 02:25:47 +00:00
return 1 ;
2023-10-16 05:47:02 +00:00
}
2023-11-06 02:25:47 +00:00
return 0 ;
2023-10-16 05:47:02 +00:00
}
function hideSearchResults ( searchResultContainer , searchEngine , site ) {
// Insert search result removal notice
if ( ! filteredWikis . includes ( site . lang + ' ' + site . origin _group ) ) {
filteredWikis . push ( site . lang + ' ' + site . origin _group ) ;
let elementId = stringToId ( site . lang + '-' + site . origin _group ) ;
hiddenWikisRevealed [ elementId ] = false ;
2023-11-06 05:09:14 +00:00
// Using aside to avoid conflicts with website CSS and listeners:
2023-10-16 05:47:02 +00:00
let searchRemovalNotice = document . createElement ( 'aside' ) ;
searchRemovalNotice . id = 'iwb-notice-' + elementId ;
searchRemovalNotice . classList . add ( 'iwb-notice' ) ;
let searchRemovalNoticeLink = document . createElement ( 'a' ) ;
searchRemovalNoticeLink . href = 'https://' + site . destination _base _url ;
searchRemovalNoticeLink . textContent = site . destination ;
searchRemovalNoticePretext = document . createTextNode ( 'Indie Wiki Buddy has filtered out results from ' + site . origin _group + ( site . lang !== 'EN' ? ' (' + site . lang + ')' : '' ) + '. Look for results from ' ) ;
2023-11-03 22:12:15 +00:00
searchRemovalNoticePosttext = document . createTextNode ( ' instead.' ) ;
2023-10-16 05:47:02 +00:00
searchRemovalNotice . appendChild ( searchRemovalNoticePretext ) ;
searchRemovalNotice . appendChild ( searchRemovalNoticeLink ) ;
searchRemovalNotice . appendChild ( searchRemovalNoticePosttext ) ;
2023-11-03 09:20:45 +00:00
// Output container for result controls:
let resultControls = document . createElement ( 'div' ) ;
resultControls . classList . add ( 'iwb-result-controls' ) ;
// Output link to show hidden results:
let showResultsButton = document . createElement ( 'div' ) ;
2023-10-16 05:47:02 +00:00
showResultsButton . setAttribute ( 'data-group' , 'iwb-search-result-' + elementId ) ;
2023-11-03 09:20:45 +00:00
showResultsButton . innerText = 'Show filtered results' ;
resultControls . appendChild ( showResultsButton )
2023-10-16 05:47:02 +00:00
showResultsButton . onclick = function ( e ) {
if ( e . target . textContent . includes ( 'Show' ) ) {
e . target . textContent = 'Re-hide filtered results' ;
hiddenWikisRevealed [ elementId ] = true ;
const selector = e . currentTarget . dataset . group ;
document . querySelectorAll ( '.' + selector ) . forEach ( el => {
el . classList . add ( 'iwb-show' ) ;
} )
} else {
e . target . textContent = 'Show filtered results' ;
hiddenWikisRevealed [ elementId ] = false ;
const selector = e . currentTarget . dataset . group ;
document . querySelectorAll ( '.' + selector ) . forEach ( el => {
el . classList . remove ( 'iwb-show' ) ;
} )
}
}
2023-11-06 05:09:14 +00:00
2023-11-03 09:20:45 +00:00
searchRemovalNotice . appendChild ( resultControls ) ;
2023-10-16 05:47:02 +00:00
switch ( searchEngine ) {
case 'google' :
if ( document . querySelector ( '#search' ) ) {
document . querySelector ( '#search' ) . prepend ( searchRemovalNotice ) ;
} else if ( document . querySelector ( '#topstuff' ) ) {
document . querySelector ( '#topstuff' ) . prepend ( searchRemovalNotice ) ;
} else if ( document . querySelector ( '#main' ) ) {
var el = document . querySelector ( '#main' ) ;
if ( el . querySelector ( '#main > div[data-hveid]' ) ) {
el . insertBefore ( searchRemovalNotice , el . querySelector ( 'div[data-hveid]' ) ) ;
} else {
el . insertBefore ( searchRemovalNotice , el . querySelector ( 'div div[data-hveid]' ) . parentElement ) ;
}
} ;
break ;
case 'bing' :
var li = document . createElement ( 'li' ) ;
li . appendChild ( searchRemovalNotice ) ;
document . querySelector ( '#b_results' ) . prepend ( li ) ;
break ;
case 'duckduckgo' :
if ( document . getElementById ( 'web_content_wrapper' ) ) {
var li = document . createElement ( 'li' ) ;
li . appendChild ( searchRemovalNotice ) ;
document . querySelector ( '#web_content_wrapper ol' ) . prepend ( li ) ;
} else {
document . getElementById ( 'links' ) . prepend ( searchRemovalNotice ) ;
}
break ;
case 'brave' :
document . querySelector ( 'body' ) . prepend ( searchRemovalNotice ) ;
break ;
case 'ecosia' :
document . querySelector ( 'body' ) . prepend ( searchRemovalNotice ) ;
break ;
case 'startpage' :
document . querySelector ( '#main' ) . prepend ( searchRemovalNotice ) ;
break ;
case 'yahoo' :
if ( document . querySelector ( '#web > ol' ) ) {
var li = document . createElement ( 'li' ) ;
li . appendChild ( searchRemovalNotice ) ;
document . querySelector ( '#web > ol' ) . prepend ( li ) ;
} else {
document . querySelector ( '#main-algo' ) . prepend ( searchRemovalNotice ) ;
}
break ;
default :
}
}
if ( ! Array . from ( searchResultContainer . classList ) . includes ( 'iwb-hide' ) ) {
let elementId = stringToId ( site . lang + '-' + site . origin _group ) ;
searchResultContainer . classList . add ( 'iwb-search-result-' + elementId ) ;
searchResultContainer . classList . add ( 'iwb-hide' ) ;
2023-11-06 02:25:47 +00:00
searchResultContainer . classList . add ( 'iwb-detected' ) ;
2023-10-16 05:47:02 +00:00
if ( hiddenWikisRevealed [ elementId ] ) {
searchResultContainer . classList . add ( 'iwb-show' ) ;
}
2023-11-06 02:25:47 +00:00
return 1 ;
2023-10-16 05:47:02 +00:00
}
2023-11-06 02:25:47 +00:00
return 0 ;
2023-10-16 05:47:02 +00:00
}
2023-08-08 06:33:23 +00:00
2023-07-25 06:17:46 +00:00
function filterSearchResults ( searchResults , searchEngine , storage ) {
getData ( ) . then ( sites => {
2023-11-06 00:59:24 +00:00
let crossLanguageSetting = storage . crossLanguage || 'off' ;
2023-08-04 05:50:12 +00:00
let countFiltered = 0 ;
2023-09-03 18:54:57 +00:00
for ( let searchResult of searchResults ) {
2023-07-25 06:17:46 +00:00
try {
2023-11-06 02:25:47 +00:00
// Check that result isn't within another result
if ( ! searchResult . closest ( '.iwb-detected' ) ) {
let searchResultLink = '' ;
if ( searchEngine === 'bing' ) {
searchResultLink = searchResult . innerHTML . replaceAll ( '<strong>' , '' ) . replaceAll ( '</strong>' , '' ) ;
} else {
searchResultLink = searchResult . closest ( 'a[href]' ) . href ;
2023-07-25 06:17:46 +00:00
}
2023-11-06 02:25:47 +00:00
let link = String ( decodeURIComponent ( searchResultLink ) ) ;
2023-09-03 18:54:57 +00:00
2023-11-06 02:25:47 +00:00
if ( searchEngine === 'google' ) {
// Break if image result:
if ( link . includes ( 'imgurl=' ) ) {
break ;
2023-08-04 05:50:12 +00:00
}
2023-11-06 02:25:47 +00:00
}
2023-08-04 05:50:12 +00:00
2023-11-06 02:25:47 +00:00
// Check if site is in our list of wikis:
if ( crossLanguageSetting === 'on' ) {
matchingSites = sites . filter ( el => link . replace ( /.*https?:\/\// , '' ) . startsWith ( el . origin _base _url ) ) ;
} else {
matchingSites = sites . filter ( el => link . replace ( /.*https?:\/\// , '' ) . startsWith ( el . origin _base _url + el . origin _content _path ) ) ;
}
if ( matchingSites . length > 0 ) {
// Select match with longest base URL
let closestMatch = "" ;
matchingSites . forEach ( site => {
if ( site . origin _base _url . length > closestMatch . length ) {
closestMatch = site . origin _base _url ;
2023-08-04 05:50:12 +00:00
}
2023-11-06 02:25:47 +00:00
} ) ;
let site = matchingSites . find ( site => site . origin _base _url === closestMatch ) ;
if ( site ) {
// Get user's settings for the wiki
let settings = storage . searchEngineSettings || { } ;
let id = site [ 'id' ] ;
let searchFilterSetting = '' ;
if ( settings . hasOwnProperty ( id ) && settings [ id ] . action ) {
searchFilterSetting = settings [ id ] . action ;
} else if ( storage . defaultSearchAction ) {
searchFilterSetting = storage . defaultSearchAction ;
} else {
searchFilterSetting = 'replace' ;
}
if ( searchFilterSetting !== 'disabled' ) {
// Output stylesheet if not already done
if ( filteredWikis . length === 0 ) {
// Wait for head to be available
const headElement = document . querySelector ( 'head' ) ;
if ( headElement && ! document . querySelector ( '.iwb-styles' ) ) {
insertCSS ( ) ;
} else {
const docObserver = new MutationObserver ( function ( mutations , mutationInstance ) {
const headElement = document . querySelector ( 'head' ) ;
if ( headElement && ! document . querySelector ( '.iwb-styles' ) ) {
insertCSS ( ) ;
mutationInstance . disconnect ( ) ;
}
} ) ;
docObserver . observe ( document , {
childList : true ,
subtree : true
} ) ;
}
}
let searchResultContainer = null ;
switch ( searchEngine ) {
case 'google' :
searchResultContainer = searchResult . closest ( 'div[data-hveid]' ) ;
break ;
case 'bing' :
searchResultContainer = searchResult . closest ( 'li.b_algo' ) ;
break ;
case 'duckduckgo' :
searchResultContainer = searchResult . closest ( 'li[data-layout], div.web-result' ) ;
break ;
case 'brave' :
searchResultContainer = searchResult . closest ( 'div.snippet' ) ;
break ;
case 'ecosia' :
searchResultContainer = searchResult . closest ( 'div.mainline__result-wrapper article div.result__body' ) ;
break ;
case 'startpage' :
searchResultContainer = searchResult . closest ( 'div.w-gl__result' ) ;
break ;
case 'yahoo' :
searchResultContainer = searchResult . closest ( '#web > ol > li div.itm .exp, #web > ol > li div.algo, #web > ol > li, section.algo' ) ;
break ;
default :
}
2023-08-04 05:50:12 +00:00
2023-11-06 02:25:47 +00:00
if ( searchResultContainer ) {
if ( searchFilterSetting === 'hide' ) {
countFiltered += hideSearchResults ( searchResultContainer , searchEngine , site ) ;
} else {
countFiltered += replaceSearchResults ( searchResultContainer , site , link ) ;
}
2023-07-25 06:17:46 +00:00
}
2023-08-07 06:43:23 +00:00
}
2023-07-25 06:17:46 +00:00
}
}
}
2023-09-03 18:54:57 +00:00
} catch ( e ) {
console . log ( 'Indie Wiki Buddy failed to properly parse search results with error: ' + e ) ;
2023-07-25 06:17:46 +00:00
}
2023-09-03 18:54:57 +00:00
} ;
2023-08-04 05:50:12 +00:00
addLocationObserver ( main ) ;
2023-07-25 06:17:46 +00:00
if ( countFiltered > 0 ) {
chrome . storage . sync . set ( { 'countSearchFilters' : ( storage . countSearchFilters ? ? 0 ) + countFiltered } ) ;
}
} ) ;
}
function main ( mutations = null , observer = null ) {
if ( observer ) {
observer . disconnect ( ) ;
}
chrome . storage . local . get ( function ( localStorage ) {
chrome . storage . sync . get ( function ( syncStorage ) {
const storage = { ... syncStorage , ... localStorage } ;
// Check if extension is on:
if ( ( storage . power ? ? 'on' ) === 'on' ) {
// Determine which search engine we're on
2023-11-02 08:12:35 +00:00
if ( ( storage . action ? ? 'replace' ) !== 'nothing' ) {
2023-07-25 06:17:46 +00:00
if ( currentURL . hostname . includes ( 'www.google.' ) ) {
2023-07-25 08:47:22 +00:00
// Function to filter search results in Google
2023-07-25 06:17:46 +00:00
function filterGoogle ( ) {
2023-09-01 06:04:15 +00:00
let searchResults = document . querySelectorAll ( "div[data-hveid] a[href*='fandom.com']:first-of-type:not([role='button']):not([target]), div[data-hveid] a[href*='fextralife.com']:first-of-type:not([role='button']):not([target])" ) ;
2023-07-25 06:17:46 +00:00
filterSearchResults ( searchResults , 'google' , storage ) ;
}
2023-07-25 08:47:22 +00:00
// Wait for document to be interactive/complete:
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
filterGoogle ( ) ;
} else {
document . addEventListener ( 'readystatechange' , e => {
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
filterGoogle ( ) ;
}
2023-08-04 05:50:12 +00:00
} , { once : true } ) ;
2023-07-25 08:47:22 +00:00
}
2023-07-25 06:17:46 +00:00
} else if ( currentURL . hostname . includes ( 'duckduckgo.com' ) && ( currentURL . search . includes ( 'q=' ) || currentURL . pathname . includes ( 'html' ) ) ) {
2023-07-25 08:47:22 +00:00
// Function to filter search results in DuckDuckGo
2023-07-25 06:17:46 +00:00
function filterDuckDuckGo ( ) {
2023-09-18 07:04:31 +00:00
let searchResults = document . querySelectorAll ( 'h2>a[href*="fandom.com"], h2>a[href*="fextralife.com"]' ) ;
2023-07-25 06:17:46 +00:00
filterSearchResults ( searchResults , 'duckduckgo' , storage ) ;
}
2023-07-25 08:47:22 +00:00
// Wait for document to be interactive/complete:
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterDuckDuckGo ( ) ;
} else {
document . addEventListener ( 'readystatechange' , e => {
2023-07-25 08:47:22 +00:00
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterDuckDuckGo ( ) ;
}
2023-08-04 05:50:12 +00:00
} , { once : true } ) ;
2023-07-25 06:17:46 +00:00
}
} else if ( currentURL . hostname . includes ( 'www.bing.com' ) ) {
2023-07-25 08:47:22 +00:00
// Function to filter search results in Bing
2023-07-25 06:17:46 +00:00
function filterBing ( ) {
2023-11-06 05:09:14 +00:00
let searchResults = Array . from ( document . querySelectorAll ( '.b_attribution>cite' ) ) . filter ( el =>
el . innerHTML . replaceAll ( '<strong>' , '' ) . replaceAll ( '</strong>' , '' ) . includes ( 'fandom.com' )
|| el . innerHTML . replaceAll ( '<strong>' , '' ) . replaceAll ( '</strong>' , '' ) . includes ( 'fextralife.com' )
) ;
2023-07-25 06:17:46 +00:00
filterSearchResults ( searchResults , 'bing' , storage ) ;
}
2023-07-25 08:47:22 +00:00
// Wait for document to be interactive/complete:
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterBing ( ) ;
} else {
document . addEventListener ( 'readystatechange' , e => {
2023-07-25 08:47:22 +00:00
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterBing ( ) ;
}
2023-08-04 05:50:12 +00:00
} , { once : true } ) ;
2023-07-25 06:17:46 +00:00
}
} else if ( currentURL . hostname . includes ( 'search.brave.com' ) ) {
2023-07-25 08:47:22 +00:00
// Function to filter search results in Brave
2023-07-25 06:17:46 +00:00
function filterBrave ( ) {
2023-09-18 07:04:31 +00:00
let searchResults = Array . from ( document . querySelectorAll ( 'div.snippet[data-type="web"] a' ) ) . filter ( el => el . innerHTML . includes ( 'fandom.com' ) || el . innerHTML . includes ( 'fextralife.com' ) ) ;
2023-07-25 06:17:46 +00:00
filterSearchResults ( searchResults , 'brave' , storage ) ;
}
2023-07-25 08:47:22 +00:00
// Wait for document to be interactive/complete:
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterBrave ( ) ;
} else {
document . addEventListener ( 'readystatechange' , e => {
2023-07-25 08:47:22 +00:00
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterBrave ( ) ;
}
2023-08-04 05:50:12 +00:00
} , { once : true } ) ;
2023-07-25 06:17:46 +00:00
}
} else if ( currentURL . hostname . includes ( 'ecosia.org' ) ) {
2023-07-25 08:47:22 +00:00
// Function to filter search results in Ecosia
2023-07-25 06:17:46 +00:00
function filterEcosia ( ) {
2023-09-18 07:04:31 +00:00
let searchResults = Array . from ( document . querySelectorAll ( 'section.mainline .result__title a.result__link' ) ) . filter ( el => el . href . includes ( 'fandom.com' ) || el . href . includes ( 'fextralife.com' ) ) ;
2023-07-25 06:17:46 +00:00
filterSearchResults ( searchResults , 'ecosia' , storage ) ;
}
2023-07-25 08:47:22 +00:00
// Wait for document to be interactive/complete:
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterEcosia ( ) ;
} else {
document . addEventListener ( 'readystatechange' , e => {
2023-07-25 08:47:22 +00:00
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterEcosia ( ) ;
}
2023-08-04 05:50:12 +00:00
} , { once : true } ) ;
2023-07-25 06:17:46 +00:00
}
} else if ( currentURL . hostname . includes ( 'startpage.com' ) ) {
2023-07-25 08:47:22 +00:00
// Function to filter search results in Startpage
2023-07-25 06:17:46 +00:00
function filterStartpage ( ) {
2023-09-18 07:04:31 +00:00
let searchResults = Array . from ( document . querySelectorAll ( 'a.result-link' ) ) . filter ( el => el . href . includes ( 'fandom.com' ) || el . href . includes ( 'fextralife.com' ) ) ;
2023-07-25 06:17:46 +00:00
filterSearchResults ( searchResults , 'startpage' , storage ) ;
}
2023-07-25 08:47:22 +00:00
// Wait for document to be interactive/complete:
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterStartpage ( ) ;
} else {
document . addEventListener ( 'readystatechange' , e => {
2023-07-25 08:47:22 +00:00
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
2023-07-25 06:17:46 +00:00
filterStartpage ( ) ;
}
2023-08-04 05:50:12 +00:00
} , { once : true } ) ;
2023-07-25 06:17:46 +00:00
}
2023-08-08 06:33:23 +00:00
} else if ( currentURL . hostname . includes ( 'yahoo.com' ) ) {
// Function to filter search results in Yahoo
function filterYahoo ( ) {
2023-09-18 07:04:31 +00:00
let searchResults = Array . from ( document . querySelectorAll ( '#web > ol > li a:not(.thmb), #main-algo section.algo a:not(.thmb)' ) ) . filter ( el => el . href . includes ( 'fandom.com' ) || el . href . includes ( 'fextralife.com' ) ) ;
2023-08-08 06:33:23 +00:00
filterSearchResults ( searchResults , 'yahoo' , storage ) ;
}
// Wait for document to be interactive/complete:
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
filterYahoo ( ) ;
} else {
document . addEventListener ( 'readystatechange' , e => {
if ( [ 'interactive' , 'complete' ] . includes ( document . readyState ) ) {
filterYahoo ( ) ;
}
} , { once : true } ) ;
}
2023-07-25 06:17:46 +00:00
}
}
}
} ) ;
} ) ;
}
main ( ) ;