infokiller / web-search-navigator

Web extension that adds keyboard shortcuts to Google, YouTube, Github, Amazon, and others (Chrome/Firefox/Edge/Safari)
MIT License
882 stars 74 forks source link

Userscript Version #564

Open Explosion-Scratch opened 1 year ago

Explosion-Scratch commented 1 year ago

Self explanatory. Installing more extensions clutters the browser, a userscript version would be pretty easy to build using CI or something right?

infokiller commented 1 year ago

Probably not too hard, but I have no personal interest in that and I doubt that many users have. Feel free to send a PR.

Explosion-Scratch commented 1 year ago

Here's the built UserScript version for anyone else wanting it:

Expand ```js // ==UserScript== // @name Web Search Navigator // @version 0.5.2 // @description Keyboard shortcuts for Google search, YouTube, Startpage, Brave Search, Google Scholar, Github, Gitlab, and Amazon. // @author Web Search Navigator // @match *://www.google.com/search* // @match *://www.google.ad/search* // @match *://www.google.ae/search* // @match *://www.google.com.af/search* // @match *://www.google.com.ag/search* // @match *://www.google.com.ai/search* // @match *://www.google.al/search* // @match *://www.google.am/search* // @match *://www.google.co.ao/search* // @match *://www.google.com.ar/search* // @match *://www.google.as/search* // @match *://www.google.at/search* // @match *://www.google.com.au/search* // @match *://www.google.az/search* // @match *://www.google.ba/search* // @match *://www.google.com.bd/search* // @match *://www.google.be/search* // @match *://www.google.bf/search* // @match *://www.google.bg/search* // @match *://www.google.com.bh/search* // @match *://www.google.bi/search* // @match *://www.google.bj/search* // @match *://www.google.com.bn/search* // @match *://www.google.com.bo/search* // @match *://www.google.com.br/search* // @match *://www.google.bs/search* // @match *://www.google.bt/search* // @match *://www.google.co.bw/search* // @match *://www.google.by/search* // @match *://www.google.com.bz/search* // @match *://www.google.ca/search* // @match *://www.google.cd/search* // @match *://www.google.cf/search* // @match *://www.google.cg/search* // @match *://www.google.ch/search* // @match *://www.google.ci/search* // @match *://www.google.co.ck/search* // @match *://www.google.cl/search* // @match *://www.google.cm/search* // @match *://www.google.cn/search* // @match *://www.google.com.co/search* // @match *://www.google.co.cr/search* // @match *://www.google.com.cu/search* // @match *://www.google.cv/search* // @match *://www.google.com.cy/search* // @match *://www.google.cz/search* // @match *://www.google.de/search* // @match *://www.google.dj/search* // @match *://www.google.dk/search* // @match *://www.google.dm/search* // @match *://www.google.com.do/search* // @match *://www.google.dz/search* // @match *://www.google.com.ec/search* // @match *://www.google.ee/search* // @match *://www.google.com.eg/search* // @match *://www.google.es/search* // @match *://www.google.com.et/search* // @match *://www.google.fi/search* // @match *://www.google.com.fj/search* // @match *://www.google.fm/search* // @match *://www.google.fr/search* // @match *://www.google.ga/search* // @match *://www.google.ge/search* // @match *://www.google.gg/search* // @match *://www.google.com.gh/search* // @match *://www.google.com.gi/search* // @match *://www.google.gl/search* // @match *://www.google.gm/search* // @match *://www.google.gp/search* // @match *://www.google.gr/search* // @match *://www.google.com.gt/search* // @match *://www.google.gy/search* // @match *://www.google.com.hk/search* // @match *://www.google.hn/search* // @match *://www.google.hr/search* // @match *://www.google.ht/search* // @match *://www.google.hu/search* // @match *://www.google.co.id/search* // @match *://www.google.ie/search* // @match *://www.google.co.il/search* // @match *://www.google.im/search* // @match *://www.google.co.in/search* // @match *://www.google.iq/search* // @match *://www.google.is/search* // @match *://www.google.it/search* // @match *://www.google.je/search* // @match *://www.google.com.jm/search* // @match *://www.google.jo/search* // @match *://www.google.co.jp/search* // @match *://www.google.co.ke/search* // @match *://www.google.com.kh/search* // @match *://www.google.ki/search* // @match *://www.google.kg/search* // @match *://www.google.co.kr/search* // @match *://www.google.com.kw/search* // @match *://www.google.kz/search* // @match *://www.google.la/search* // @match *://www.google.com.lb/search* // @match *://www.google.li/search* // @match *://www.google.lk/search* // @match *://www.google.co.ls/search* // @match *://www.google.lt/search* // @match *://www.google.lu/search* // @match *://www.google.lv/search* // @match *://www.google.com.ly/search* // @match *://www.google.co.ma/search* // @match *://www.google.md/search* // @match *://www.google.me/search* // @match *://www.google.mg/search* // @match *://www.google.mk/search* // @match *://www.google.ml/search* // @match *://www.google.com.mm/search* // @match *://www.google.mn/search* // @match *://www.google.ms/search* // @match *://www.google.com.mt/search* // @match *://www.google.mu/search* // @match *://www.google.mv/search* // @match *://www.google.mw/search* // @match *://www.google.com.mx/search* // @match *://www.google.com.my/search* // @match *://www.google.co.mz/search* // @match *://www.google.com.na/search* // @match *://www.google.com.nf/search* // @match *://www.google.com.ng/search* // @match *://www.google.com.ni/search* // @match *://www.google.ne/search* // @match *://www.google.nl/search* // @match *://www.google.no/search* // @match *://www.google.com.np/search* // @match *://www.google.nr/search* // @match *://www.google.nu/search* // @match *://www.google.co.nz/search* // @match *://www.google.com.om/search* // @match *://www.google.com.pa/search* // @match *://www.google.com.pe/search* // @match *://www.google.com.pg/search* // @match *://www.google.com.ph/search* // @match *://www.google.com.pk/search* // @match *://www.google.pl/search* // @match *://www.google.pn/search* // @match *://www.google.com.pr/search* // @match *://www.google.ps/search* // @match *://www.google.pt/search* // @match *://www.google.com.py/search* // @match *://www.google.com.qa/search* // @match *://www.google.ro/search* // @match *://www.google.ru/search* // @match *://www.google.rw/search* // @match *://www.google.com.sa/search* // @match *://www.google.com.sb/search* // @match *://www.google.sc/search* // @match *://www.google.se/search* // @match *://www.google.com.sg/search* // @match *://www.google.sh/search* // @match *://www.google.si/search* // @match *://www.google.sk/search* // @match *://www.google.com.sl/search* // @match *://www.google.sn/search* // @match *://www.google.so/search* // @match *://www.google.sm/search* // @match *://www.google.sr/search* // @match *://www.google.st/search* // @match *://www.google.com.sv/search* // @match *://www.google.td/search* // @match *://www.google.tg/search* // @match *://www.google.co.th/search* // @match *://www.google.com.tj/search* // @match *://www.google.tk/search* // @match *://www.google.tl/search* // @match *://www.google.tm/search* // @match *://www.google.tn/search* // @match *://www.google.to/search* // @match *://www.google.com.tr/search* // @match *://www.google.tt/search* // @match *://www.google.com.tw/search* // @match *://www.google.co.tz/search* // @match *://www.google.com.ua/search* // @match *://www.google.co.ug/search* // @match *://www.google.co.uk/search* // @match *://www.google.com.uy/search* // @match *://www.google.co.uz/search* // @match *://www.google.com.vc/search* // @match *://www.google.co.ve/search* // @match *://www.google.vg/search* // @match *://www.google.co.vi/search* // @match *://www.google.com.vn/search* // @match *://www.google.vu/search* // @match *://www.google.ws/search* // @match *://www.google.rs/search* // @match *://www.google.co.za/search* // @match *://www.google.co.zm/search* // @match *://www.google.co.zw/search* // @match *://www.google.cat/search* // ==/UserScript== globalThis.IS_USERSCRIPT=!0,globalThis._localStorage_browser_polyfill={get:async(...args)=>(console.log("[localStorage] Get: ",...args),[]),set:async(...args)=>{console.log("[localStorage] Set: ",...args)},clear:async()=>{console.log("[localStorage] Clear")}},globalThis._browser_userscript_polyfill={runtime:{sendMessage:msg=>{"tabsCreate"===msg.type&&window.open(msg.options.url,"_blank")},id:"093889f3-43be-45e3-bc5a-e257e75b466d"},storage:{sync:globalThis._localStorage_browser_polyfill,local:globalThis._localStorage_browser_polyfill},permissions:{remove:()=>{},add:()=>{},request:()=>{},getAll:()=>({})}},console.log(globalThis.browser,_browser_userscript_polyfill),Object.assign(globalThis,{browser:globalThis._browser_userscript_polyfill,chrome:globalThis._browser_userscript_polyfill}),function(global,factory){"function"==typeof define&&define.amd?define("webextension-polyfill",["module"],factory):"undefined"!=typeof exports?factory(module):(factory(factory={exports:{}}),global.browser=factory.exports)}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:this,function(module){"use strict";if(!globalThis.chrome?.runtime?.id)throw new Error("This script should only be loaded in a browser extension.");if(void 0===globalThis.browser||Object.getPrototypeOf(globalThis.browser)!==Object.prototype)module.exports=(extensionAPIs=>{var apiMetadata={alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getSubTree:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{disable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},openPopup:{minArgs:0,maxArgs:0},setBadgeBackgroundColor:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},browsingData:{remove:{minArgs:2,maxArgs:2},removeCache:{minArgs:1,maxArgs:1},removeCookies:{minArgs:1,maxArgs:1},removeDownloads:{minArgs:1,maxArgs:1},removeFormData:{minArgs:1,maxArgs:1},removeHistory:{minArgs:1,maxArgs:1},removeLocalStorage:{minArgs:1,maxArgs:1},removePasswords:{minArgs:1,maxArgs:1},removePluginData:{minArgs:1,maxArgs:1},settings:{minArgs:0,maxArgs:0}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},devtools:{inspectedWindow:{eval:{minArgs:1,maxArgs:2,singleCallbackArg:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0},elements:{createSidebarPane:{minArgs:1,maxArgs:1}}}},downloads:{cancel:{minArgs:1,maxArgs:1},download:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},identity:{launchWebAuthFlow:{minArgs:1,maxArgs:1}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},setEnabled:{minArgs:2,maxArgs:2},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},permissions:{contains:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},request:{minArgs:1,maxArgs:1}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},sessions:{getDevices:{minArgs:0,maxArgs:1},getRecentlyClosed:{minArgs:0,maxArgs:1},restore:{minArgs:0,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{captureVisibleTab:{minArgs:0,maxArgs:2},create:{minArgs:1,maxArgs:1},detectLanguage:{minArgs:0,maxArgs:1},discard:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},goBack:{minArgs:0,maxArgs:1},goForward:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},query:{minArgs:1,maxArgs:1},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},topSites:{get:{minArgs:0,maxArgs:0}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}};if(0===Object.keys(apiMetadata).length)throw new Error("api-metadata.json has not been included in browser-polyfill");class DefaultWeakMap extends WeakMap{constructor(createItem,items=void 0){super(items),this.createItem=createItem}get(key){return this.has(key)||this.set(key,this.createItem(key)),super.get(key)}}const makeCallback=(promise,metadata)=>(...callbackArgs)=>{extensionAPIs.runtime.lastError?promise.reject(new Error(extensionAPIs.runtime.lastError.message)):metadata.singleCallbackArg||callbackArgs.length<=1&&!1!==metadata.singleCallbackArg?promise.resolve(callbackArgs[0]):promise.resolve(callbackArgs)},pluralizeArguments=numArgs=>1==numArgs?"argument":"arguments",wrapMethod=(target,method,wrapper)=>new Proxy(method,{apply(targetMethod,thisObj,args){return wrapper.call(thisObj,target,...args)}});let hasOwnProperty=Function.call.bind(Object.prototype.hasOwnProperty);const wrapObject=(target,wrappers={},metadata={})=>{let cache=Object.create(null);var handlers={has(proxyTarget,prop){return prop in target||prop in cache},get(proxyTarget,prop,receiver){if(prop in cache)return cache[prop];if(prop in target){let value=target[prop];var wrapper;if("function"==typeof value)value="function"==typeof wrappers[prop]?wrapMethod(target,target[prop],wrappers[prop]):hasOwnProperty(metadata,prop)?(wrapper=((name,metadata)=>function(target,...args){if(args.lengthmetadata.maxArgs)throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got `+args.length);return new Promise((resolve,reject)=>{if(metadata.fallbackToNoCallback)try{target[name](...args,makeCallback({resolve:resolve,reject:reject},metadata))}catch(cbError){console.warn(name+" API method doesn't seem to support the callback parameter, falling back to call it without a callback: ",cbError),target[name](...args),metadata.fallbackToNoCallback=!1,metadata.noCallback=!0,resolve()}else metadata.noCallback?(target[name](...args),resolve()):target[name](...args,makeCallback({resolve:resolve,reject:reject},metadata))})})(prop,metadata[prop]),wrapMethod(target,target[prop],wrapper)):value.bind(target);else if("object"==typeof value&&null!==value&&(hasOwnProperty(wrappers,prop)||hasOwnProperty(metadata,prop)))value=wrapObject(value,wrappers[prop],metadata[prop]);else{if(!hasOwnProperty(metadata,"*"))return Object.defineProperty(cache,prop,{configurable:!0,enumerable:!0,get(){return target[prop]},set(value){target[prop]=value}}),value;value=wrapObject(value,wrappers[prop],metadata["*"])}return cache[prop]=value}},set(proxyTarget,prop,value,receiver){return prop in cache?cache[prop]=value:target[prop]=value,!0},defineProperty(proxyTarget,prop,desc){return Reflect.defineProperty(cache,prop,desc)},deleteProperty(proxyTarget,prop){return Reflect.deleteProperty(cache,prop)}},proxyTarget=Object.create(target);return new Proxy(proxyTarget,handlers)};var wrapEvent=wrapperMap=>({addListener(target,listener,...args){target.addListener(wrapperMap.get(listener),...args)},hasListener(target,listener){return target.hasListener(wrapperMap.get(listener))},removeListener(target,listener){target.removeListener(wrapperMap.get(listener))}}),onRequestFinishedWrappers=new DefaultWeakMap(listener=>"function"!=typeof listener?listener:function(req){req=wrapObject(req,{},{getContent:{minArgs:0,maxArgs:0}});listener(req)}),onMessageWrappers=new DefaultWeakMap(listener=>"function"!=typeof listener?listener:function(message,sender,sendResponse){let didCallSendResponse=!1,wrappedSendResponse;var sendResponsePromise=new Promise(resolve=>{wrappedSendResponse=function(response){didCallSendResponse=!0,resolve(response)}});let result;try{result=listener(message,sender,wrappedSendResponse)}catch(err){result=Promise.reject(err)}sender=!0!==result&&(message=result)&&"object"==typeof message&&"function"==typeof message.then;return!(!0!==result&&!sender&&!didCallSendResponse||((promise=>{promise.then(msg=>{sendResponse(msg)},error=>{let message;message=error&&(error instanceof Error||"string"==typeof error.message)?error.message:"An unexpected error occurred",sendResponse({__mozWebExtensionPolyfillReject__:!0,message:message})}).catch(err=>{console.error("Failed to send onMessage rejected reply",err)})})(sender?result:sendResponsePromise),0))});var wrappedSendMessage=(name,metadata,apiNamespaceObj,...args)=>{if(args.lengthmetadata.maxArgs)throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got `+args.length);return new Promise((resolve,reject)=>{resolve=(({reject,resolve},reply)=>{extensionAPIs.runtime.lastError?"The message port closed before a response was received."===extensionAPIs.runtime.lastError.message?resolve():reject(new Error(extensionAPIs.runtime.lastError.message)):reply&&reply.__mozWebExtensionPolyfillReject__?reject(new Error(reply.message)):resolve(reply)}).bind(null,{resolve:resolve,reject:reject});args.push(resolve),apiNamespaceObj.sendMessage(...args)})},onRequestFinishedWrappers={devtools:{network:{onRequestFinished:wrapEvent(onRequestFinishedWrappers)}},runtime:{onMessage:wrapEvent(onMessageWrappers),onMessageExternal:wrapEvent(onMessageWrappers),sendMessage:wrappedSendMessage.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:wrappedSendMessage.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},wrapEvent={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return apiMetadata.privacy={network:{"*":wrapEvent},services:{"*":wrapEvent},websites:{"*":wrapEvent}},wrapObject(extensionAPIs,onRequestFinishedWrappers,apiMetadata)})(chrome);else module.exports=globalThis.browser}),function(window,document){if(window){for(var _REVERSE_MAP,_MAP={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},_KEYCODE_MAP={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},_SHIFT_MAP={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},_SPECIAL_ALIASES={option:"alt",command:"meta",return:"enter",escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},i=1;i<20;++i)_MAP[111+i]="f"+i;for(i=0;i<=9;++i)_MAP[i+96]=i.toString();Mousetrap.prototype.bind=function(keys,callback,action){return keys=keys instanceof Array?keys:[keys],this._bindMultiple.call(this,keys,callback,action),this},Mousetrap.prototype.unbind=function(keys,action){return this.bind.call(this,keys,function(){},action)},Mousetrap.prototype.trigger=function(keys,action){return this._directMap[keys+":"+action]&&this._directMap[keys+":"+action]({},keys),this},Mousetrap.prototype.reset=function(){return this._callbacks={},this._directMap={},this},Mousetrap.prototype.stopCallback=function(e,element){var initialEventTarget;return!(-1<(" "+element.className+" ").indexOf(" mousetrap ")||function _belongsTo(element,ancestor){return null!==element&&element!==document&&(element===ancestor||_belongsTo(element.parentNode,ancestor))}(element,this.target))&&("INPUT"==(element="composedPath"in e&&"function"==typeof e.composedPath&&(initialEventTarget=e.composedPath()[0])!==e.target?initialEventTarget:element).tagName||"SELECT"==element.tagName||"TEXTAREA"==element.tagName||element.isContentEditable)},Mousetrap.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)},Mousetrap.addKeycodes=function(object){for(var key in object)object.hasOwnProperty(key)&&(_MAP[key]=object[key]);_REVERSE_MAP=null},(Mousetrap.init=function(){var method,documentMousetrap=Mousetrap(document);for(method in documentMousetrap)"_"!==method.charAt(0)&&(Mousetrap[method]=function(method){return function(){return documentMousetrap[method].apply(documentMousetrap,arguments)}}(method))})(),window.Mousetrap=Mousetrap,"undefined"!=typeof module&&module.exports&&(module.exports=Mousetrap),"function"==typeof define&&define.amd&&define(function(){return Mousetrap})}function _addEvent(object,type,callback){object.addEventListener?object.addEventListener(type,callback,!1):object.attachEvent("on"+type,callback)}function _characterFromEvent(e){var character;return"keypress"==e.type?(character=String.fromCharCode(e.which),e.shiftKey?character:character.toLowerCase()):_MAP[e.which]||_KEYCODE_MAP[e.which]||String.fromCharCode(e.which).toLowerCase()}function _isModifier(key){return"shift"==key||"ctrl"==key||"alt"==key||"meta"==key}function _pickBestAction(key,modifiers,action){return action="keypress"==(action=action||(function(){if(!_REVERSE_MAP)for(var key in _REVERSE_MAP={},_MAP)95kb.split(",").map(t=>t.trim()),keybindingArrayToString=kb=>kb.join(", ");class BrowserStorage{constructor(storage,defaultValues){this.storage=storage,this.values={},this.defaultValues=defaultValues}load(){return this.storage.get(null).then(values=>{this.values=values;let migrated=!1;for(var[key,value]of Object.entries(this.values))key in DEFAULT_KEYBINDINGS&&!Array.isArray(value)&&(migrated=!0,this.values[key]=keybindingStringToArray(value));if(migrated)return this.save()})}save(){return this.storage.set(this.values)}get(key){var value=this.values[key];return null!=value?value:this.defaultValues[key]}set(key,value){this.values[key]=value}clear(){return this.storage.clear().then(()=>{this.values={}})}getAll(){return{...this.defaultValues,...this.values}}}const STORAGE_KEY="webSearchNavigator";class LocalStorage{constructor(defaultValues){this.values={},this.defaultValues=defaultValues,this.load()}load(){var storedData=localStorage.getItem(STORAGE_KEY);storedData?this.values=JSON.parse(storedData):(this.values={...this.defaultValues},this.save())}save(){localStorage.setItem(STORAGE_KEY,JSON.stringify(this.values))}get(key){var value=this.values[key];return null!=value?value:this.defaultValues[key]}set(key,value){this.values[key]=value,this.save()}clear(){localStorage.removeItem(STORAGE_KEY),this.values={...this.defaultValues}}getAll(){return{...this.defaultValues,...this.values}}}const createSyncedOptions=()=>globalThis.IS_USERSCRIPT?new LocalStorage(DEFAULT_OPTIONS):new BrowserStorage(browser.storage.sync,DEFAULT_OPTIONS);class ExtensionOptions{constructor(){this.sync=createSyncedOptions(),globalThis.IS_USERSCRIPT?this.local=createSyncedOptions():this.local=new BrowserStorage(browser.storage.local,{lastQueryUrl:null,lastFocusedIndex:0})}load(){return Promise.all([this.local.load(),this.sync.load()])}}class SearchResult{#element;#anchorSelector;#highlightedElementSelector;#containerSelector;constructor(element,anchorSelector,highlightClass,highlightedElementSelector,containerSelector){this.#element=element,this.#anchorSelector=anchorSelector,this.highlightClass=highlightClass,this.#highlightedElementSelector=highlightedElementSelector,this.#containerSelector=containerSelector}get anchor(){return this.#anchorSelector?this.#anchorSelector(this.#element):this.#element}get container(){return this.#containerSelector?this.#containerSelector(this.#element):this.#element}get highlightedElement(){return this.#highlightedElementSelector?this.#highlightedElementSelector(this.#element):this.#element}}const getSortedSearchResults=(includedSearchResults,excludedNodeList=[])=>{var excludedResultsSet=new Set;for(const node of excludedNodeList)excludedResultsSet.add(node);var searchResults=[];for(const results of includedSearchResults)for(const node of results.nodes){var searchResult=new SearchResult(node,results.anchorSelector,results.highlightClass,results.highlightedElementSelector,results.containerSelector),anchor=searchResult.anchor;null==anchor||excludedResultsSet.has(anchor)||null===anchor.offsetParent||(excludedResultsSet.add(anchor),searchResults.push(searchResult))}return searchResults.sort((a,b)=>{a=a.anchor.compareDocumentPosition(b.anchor);return a&Node.DOCUMENT_POSITION_FOLLOWING?-1:a&Node.DOCUMENT_POSITION_PRECEDING?1:0}),searchResults},getFixedSearchBoxTopMargin=(searchBoxContainer,element)=>!searchBoxContainer||searchBoxContainer.contains(element)?0:searchBoxContainer.getBoundingClientRect().height,isFirefox=()=>0<=navigator.userAgent.toLowerCase().indexOf("firefox"),getDefaultBottomMargin=element=>28,selectorElementGetter=selector=>()=>document.querySelector(selector),nParent=(element,n)=>{for(;0{let timeoutId;return(...args)=>{clearTimeout(timeoutId),timeoutId=setTimeout(()=>callback(...args),delayMs)}};class GoogleSearch{constructor(options){this.options=options}get urlPattern(){return/^https:\/\/(www\.)?google\./}get searchBoxSelector(){return"form[role=search] [name=q]"}getTopMargin(element){return getFixedSearchBoxTopMargin(document.querySelector("#searchform.minidiv"),element)}getBottomMargin(element){return isFirefox()?0:getDefaultBottomMargin()}onChangedResults(callback){var container;return GoogleSearch.#isImagesTab()?GoogleSearch.#onImageSearchResults(callback):this.options.googleIncludeMemex?GoogleSearch.#onMemexResults(callback):void((container=document.querySelector("#rcnt"))&&new MutationObserver(debounce((mutationsList,observer)=>{callback(!0)},50)).observe(container,{attributes:!1,childList:!0,subtree:!0}))}static#isImagesTab(){return"isch"===new URLSearchParams(window.location.search).get("tbm")}static#getImagesTabResults(){var includedElements=[{nodes:document.querySelectorAll('.islrc a[data-nav="1"]'),highlightClass:"wsn-google-focused-image"},{nodes:document.querySelectorAll('#islmp [type="button"]'),highlightClass:"wsn-google-focused-image"}];return getSortedSearchResults(includedElements,[])}static#regularResults(){return[{nodes:document.querySelectorAll("#search .r > a:first-of-type"),highlightClass:"wsn-google-focused-link",containerSelector:n=>n.parentElement.parentElement},{nodes:document.querySelectorAll("#search .r g-link > a:first-of-type"),highlightClass:"wsn-google-focused-link",containerSelector:n=>n.parentElement.parentElement},{nodes:document.querySelectorAll('#botstuff a[href^="/search"][href*="start="] h3'),highlightClass:"wsn-google-focused-link",anchorSelector:n=>n.closest("a")},{nodes:document.querySelectorAll("#botstuff a h3"),highlightClass:"wsn-google-focused-link",containerSelector:n=>nParent(n,5),highlightedElementSelector:n=>nParent(n,5),anchorSelector:n=>n.closest("a")},{nodes:document.querySelectorAll(".xpdopen .g a"),highlightClass:"wsn-google-focused-link",highlightedElementSelector:n=>n.querySelector("h3")},{nodes:document.querySelectorAll('h3 a[href*="youtube.com"]'),highlightClass:"wsn-google-focused-link",highlightedElementSelector:n=>n.closest("h3")},{nodes:document.querySelectorAll("#search h3 a:first-of-type"),highlightClass:"wsn-google-focused-link",highlightedElementSelector:n=>n.closest("h3"),containerSelector:n=>n.closest("tr")},{nodes:document.querySelectorAll("#rso a h4"),anchorSelector:n=>n.closest("a"),highlightClass:"wsn-google-focused-card",highlightedElementSelector:n=>n.closest(".sh-dgr__content")},{nodes:document.querySelectorAll("#search g-card a"),highlightClass:"wsn-google-focused-link"},{nodes:document.querySelectorAll('#search a:is([href*="ibp=htl;jobs"],[href*="htivrt=jobs"]) [role=heading][aria-level="2"]'),anchorSelector:n=>n.closest("a"),highlightClass:"wsn-google-focused-job-card"},{nodes:document.querySelectorAll('#search li a[href*="htivrt=jobs"]'),highlightedElementSelector:n=>n.closest("li"),highlightClass:"wsn-google-focused-job-card"},{nodes:document.querySelectorAll("#search [data-hveid] a h3"),anchorSelector:n=>n.closest("a"),containerSelector:n=>n.closest("[data-hveid]"),highlightedElementSelector:n=>n.closest("[data-hveid]"),highlightClass:"wsn-google-focused-link"},{nodes:document.querySelectorAll("#pnprev, #pnnext"),highlightClass:"wsn-google-card-item"}]}static#cardResults(){var nearestChildOrSiblingOrParentAnchor=element=>{var childAnchor=element.querySelector("a");return childAnchor&&childAnchor.href||(childAnchor=element.parentElement.querySelector("a"))&&childAnchor.href?childAnchor:element.closest("a")},nearestCardContainer=element=>element.closest("g-inner-card");return[{nodes:document.querySelectorAll("#search [data-init-vis=true] [role=heading]"),anchorSelector:nearestChildOrSiblingOrParentAnchor,highlightedElementSelector:nearestCardContainer,highlightClass:"wsn-google-focused-card"},{nodes:document.querySelectorAll("#search [role=text] [role=heading]"),anchorSelector:nearestChildOrSiblingOrParentAnchor,highlightClass:"wsn-google-focused-link"},{nodes:document.querySelectorAll("#search video-voyager a [role=heading]"),anchorSelector:nearestChildOrSiblingOrParentAnchor,containerSelector:nearestChildOrSiblingOrParentAnchor,highlightedElementSelector:nearestChildOrSiblingOrParentAnchor,highlightClass:"wsn-google-focused-link"},{nodes:document.querySelectorAll("#search g-scrolling-carousel g-inner-card a [role=heading]"),anchorSelector:nearestChildOrSiblingOrParentAnchor,containerSelector:nearestCardContainer,highlightedElementSelector:nearestCardContainer,highlightClass:"wsn-google-card-item"},{nodes:document.querySelectorAll("#search a.a-no-hover-decoration [role=heading]"),anchorSelector:nearestChildOrSiblingOrParentAnchor,containerSelector:nearestChildOrSiblingOrParentAnchor,highlightedElementSelector:nearestChildOrSiblingOrParentAnchor,highlightClass:"wsn-google-focused-link"},{nodes:document.querySelectorAll("td a [role=heading]"),anchorSelector:nearestChildOrSiblingOrParentAnchor,containerSelector:n=>n.closest("td"),highlightedElementSelector:n=>n.closest("td"),highlightClass:"wsn-google-card-item"},{nodes:document.querySelectorAll("a [role=heading]"),anchorSelector:nearestChildOrSiblingOrParentAnchor,containerSelector:nearestChildOrSiblingOrParentAnchor,highlightedElementSelector:nearestChildOrSiblingOrParentAnchor,highlightClass:"wsn-google-card-item"}]}static#placesResults(){var nodes=document.querySelectorAll(".vk_c a");let map,links=nodes;null!=nodes[0]&&nodes[0].querySelector("img")&&(map=nodes[0],links=Array.from(nodes).slice(1));nodes=[];return null!=map&&nodes.push({nodes:[map],highlightedElementSelector:n=>n.parentElement,highlightClass:"wsn-google-focused-map"}),nodes.push({nodes:links,highlightClass:"wsn-google-focused-link"}),nodes}static#memexResults(){return[{nodes:document.querySelectorAll("#memexResults ._3d3zwUrsb4CVi1Li4H6CBw a"),highlightClass:"wsn-google-focused-memex-result"}]}getSearchResults(){var includedElements,excludedElements;return GoogleSearch.#isImagesTab()?GoogleSearch.#getImagesTabResults():(includedElements=GoogleSearch.#regularResults(),this.options.googleIncludeCards&&includedElements.push(...GoogleSearch.#cardResults()),this.options.googleIncludePlaces&&includedElements.push(...GoogleSearch.#placesResults()),this.options.googleIncludeMemex&&includedElements.push(...GoogleSearch.#memexResults()),excludedElements=document.querySelectorAll([".related-question-pair a","#search .kp-blk:not(.c2xzTb) .r > a:first-of-type","#rhs a"].join(", ")),getSortedSearchResults(includedElements,excludedElements))}static#onImageSearchResults(callback){var container=document.querySelector(".islrc");container&&new MutationObserver(debounce((mutationsList,observer)=>{callback(!0)},50)).observe(container,{attributes:!1,childList:!0,subtree:!1})}static#onMemexResults(callback){var container=document.querySelector("#rhs");container&&new MutationObserver(debounce((mutationsList,observer)=>{null!=document.querySelector("#memexResults")&&callback(!0)},50)).observe(container,{attributes:!1,childList:!0,subtree:!0})}static#imageSearchTabs(){return{navigateSearchTab:document.querySelectorAll(".T47uwc > a")[0],navigateMapsTab:selectorElementGetter('.T47uwc > a[href*="maps.google."]'),navigateVideosTab:selectorElementGetter('.T47uwc > a[href*="&tbm=vid"]'),navigateNewsTab:selectorElementGetter('.T47uwc > a[href*="&tbm=nws"]'),navigateShoppingTab:selectorElementGetter('a[role="menuitem"][href*="&tbm=shop"]'),navigateBooksTab:selectorElementGetter('a[role="menuitem"][href*="&tbm=bks"]'),navigateFlightsTab:selectorElementGetter('a[role="menuitem"][href*="&tbm=flm"]'),navigateFinancialTab:selectorElementGetter('a[role="menuitem"][href*="/finance?"]')}}get previousPageButton(){return GoogleSearch.#isImagesTab()?null:selectorElementGetter("#pnprev")}get nextPageButton(){return GoogleSearch.#isImagesTab()?null:selectorElementGetter("#pnnext")}get tabs(){return GoogleSearch.#isImagesTab()?GoogleSearch.#imageSearchTabs():{navigateSearchTab:selectorElementGetter('a[href*="/search?q="]:not([href*="&tbm="]):not([href*="maps.google."])'),navigateImagesTab:selectorElementGetter('a[href*="&tbm=isch"]'),navigateVideosTab:selectorElementGetter('a[href*="&tbm=vid"]'),navigateMapsTab:selectorElementGetter('a[href*="maps.google."]'),navigateNewsTab:selectorElementGetter('a[href*="&tbm=nws"]'),navigateShoppingTab:selectorElementGetter('a[href*="&tbm=shop"]'),navigateBooksTab:selectorElementGetter('a[href*="&tbm=bks"]'),navigateFlightsTab:selectorElementGetter('a[href*="&tbm=flm"]'),navigateFinancialTab:selectorElementGetter('[href*="/finance?"]')}}changeTools(period){var searchParams=new URLSearchParams(window.location.search),allTbsValues=searchParams.getAll("tbs"),allTbsValues=allTbsValues[allTbsValues.length-1]||"",allTbsValues=/(qdr:.|li:1)(,sbd:.)?/.exec(allTbsValues),currentPeriod=allTbsValues&&allTbsValues[1]||"",allTbsValues=allTbsValues&&allTbsValues[2]||"";if("a"===period)searchParams.delete("tbs");else if(period){let newTbs="";newTbs="v"===period?"li:1"===currentPeriod?"":"li:1":"qdr:"+period,searchParams.set("tbs",""+newTbs+allTbsValues)}else currentPeriod&&searchParams.set("tbs",currentPeriod+(allTbsValues?"":",sbd:1"));period="?"+searchParams.toString();return period!==window.location.search&&(window.location.search=period),!1}changeImageSize(size){const sizeOptions_LARGE={value:0,name:"Large",code:"l"},sizeOptions_MEDIUM={value:1,name:"Medium",code:"e"},sizeOptions_ICON={value:2,name:"Icon",code:"i"};var openTool=document.querySelector('[class="PNyWAd ZXJQ7c"][jsname="I4bIT"]'),openTool=(null!=openTool&&openTool.click(),document.querySelector('[aria-label="Size"]')),dropDownWithSize=(null!=openTool&&openTool.click(),document.querySelector('[class="xFo9P r9PaP Fmo8N"][jsname="wLFV5d"]'));const getButton=selector=>{let button;return button=null!=document.querySelector(selector)?document.querySelector(selector):null};var setImageSize=(dropDownWithSize,buttonSelector)=>{let button=getButton(buttonSelector);null==dropDownWithSize&&null!=button?button.click():null!=dropDownWithSize&&null==button?(dropDownWithSize.click(),(button=getButton(buttonSelector)).click()):null!=dropDownWithSize&&null!=button&&button.click()};switch(size){case sizeOptions_LARGE.code:null!=dropDownWithSize&&dropDownWithSize.getAttribute("aria-label")==sizeOptions_LARGE.name||setImageSize(dropDownWithSize,'[class="MfLWbb"][aria-label="Large"]');break;case sizeOptions_MEDIUM.code:null!=dropDownWithSize&&dropDownWithSize.getAttribute("aria-label")==sizeOptions_MEDIUM.name||setImageSize(dropDownWithSize,'[class="MfLWbb"][aria-label="Medium"]');break;case sizeOptions_ICON.code:null!=dropDownWithSize&&dropDownWithSize.getAttribute("aria-label")==sizeOptions_ICON.name||setImageSize(dropDownWithSize,'[class="MfLWbb"][aria-label="Icon"]')}}}class BraveSearch{constructor(options){this.options=options}get urlPattern(){return/^https:\/\/search\.brave\.com/}get searchBoxSelector(){return".form-input, input[id=searchbox]"}getTopMargin(element){return getFixedSearchBoxTopMargin(document.querySelector("header.navbar"),element)}onChangedResults(callback){var containers=document.querySelectorAll("#results"),observer=new MutationObserver(debounce((mutationsList,observer)=>{callback(!0)},50));for(const container of containers)observer.observe(container,{attributes:!1,childList:!0,subtree:!0})}static#getNewsTabResults(){var includedElements=[{nodes:document.querySelectorAll(".snippet a"),highlightClass:"wsn-brave-search-focused-news",containerSelector:n=>n.parentElement}];return getSortedSearchResults(includedElements)}static#getVideosTabResults(){var includedElements=[{nodes:document.querySelectorAll(".card a"),highlightClass:"wsn-brave-search-focused-card",highlightedElementSelector:n=>n.closest(".card"),containerSelector:n=>n.parentElement}];return getSortedSearchResults(includedElements)}getSearchResults(){var includedElements;return BraveSearch.#isTabActive(this.tabs.navigateNewsTab)?BraveSearch.#getNewsTabResults():BraveSearch.#isTabActive(this.tabs.navigateVideosTab)?BraveSearch.#getVideosTabResults():(includedElements=[{nodes:document.querySelectorAll(".snippet.fdb > a"),highlightClass:"wsn-brave-search-focused-link",containerSelector:n=>n.parentElement},{nodes:document.querySelectorAll('.card[data-type="news"]:nth-child(-n+3)'),highlightClass:"wsn-brave-search-focused-card"},{nodes:document.querySelectorAll('.card[data-type="videos"]:nth-child(-n+3)'),highlightClass:"wsn-brave-search-focused-card"}],getSortedSearchResults(includedElements))}static#isTabActive(tab){return tab&&tab.parentElement.classList.contains("active")}get tabs(){return{navigateSearchTab:document.querySelector('a[href*="/search?q="]'),navigateImagesTab:document.querySelector("#tab-images > a:first-of-type"),navigateNewsTab:document.querySelector('a[href*="/news?q="]'),navigateVideosTab:document.querySelector("#tab-videos > a:first-of-type")}}}class StartPage{constructor(options){this.options=options}get urlPattern(){return/^https:\/\/(www\.)?startpage\./}get searchBoxSelector(){return"#q"}getTopMargin(element){return getFixedSearchBoxTopMargin(document.querySelector("div.layout-web__header"),element)}getBottomMargin(element){return isFirefox()?0:getDefaultBottomMargin()}static#isSearchTab(){return null!=document.querySelector("div.layout-web")}static#isImagesTab(){return null!=document.querySelector("div.layout-images")}getSearchResults(){var containerSelector,excludedElements;return StartPage.#isImagesTab()?[]:(containerSelector=element=>StartPage.#isSearchTab()?element.closest(".w-gl__result"):element,containerSelector=[{nodes:document.querySelectorAll("a.w-gl__result-url"),highlightedElementSelector:containerSelector,highlightClass:"wsn-startpage-focused-link",containerSelector:containerSelector},{nodes:document.querySelectorAll(".pagination--desktop button"),highlightClass:"wsn-startpage-focused-link"},{nodes:document.querySelectorAll(".vo-sp.vo-sp--default > a.vo-sp__link"),highlightedElementSelector:containerSelector,highlightClass:"wsn-startpage-focused-link"}],excludedElements=document.querySelectorAll("button[disabled]"),getSortedSearchResults(containerSelector,excludedElements))}get previousPageButton(){var menuLinks=document.querySelectorAll(".inline-nav-menu__link");return!menuLinks||menuLinks.length<4?null:document.querySelector("form.pagination__form.next-prev-form--desktop:first-of-type")}get nextPageButton(){var menuLinks=document.querySelectorAll(".inline-nav-menu__link");return!menuLinks||menuLinks.length<4?null:document.querySelector("form.pagination__form.next-prev-form--desktop:last-of-type")}get tabs(){var menuLinks=document.querySelectorAll(".inline-nav-menu__link");return!menuLinks||menuLinks.length<4?{}:{navigateSearchTab:menuLinks[0],navigateImagesTab:menuLinks[1],navigateVideosTab:menuLinks[2],navigateNewsTab:menuLinks[3]}}changeTools(period){var forms=document.forms;let timeForm;for(let i=0;i{callback(!0)},50));let lastLoadedURL=null;new MutationObserver(debounce((mutationsList,observer)=>{var url=window.location.pathname+window.location.search;if(url!==lastLoadedURL){resultsObserver.disconnect();var containers=document.querySelectorAll(YT_CONTAINER_SELECTOR);if(0!=containers.length){lastLoadedURL=url,callback(!1);for(const container of containers)resultsObserver.observe(container,{attributes:!1,childList:!0,subtree:!0})}}},50)).observe(document.querySelector("#page-manager"),{attributes:!1,childList:!0,subtree:!0})}getSearchResults(){var includedElements=[{nodes:document.querySelectorAll("a#video-title.ytd-video-renderer"),highlightClass:"wsn-youtube-focused-video",highlightedElementSelector:n=>n.closest("ytd-video-renderer"),containerSelector:n=>n.closest("ytd-video-renderer")},{nodes:document.querySelectorAll('ytd-playlist-renderer a[href*="/playlist"]'),highlightClass:"wsn-youtube-focused-video",highlightedElementSelector:n=>n.closest("ytd-playlist-renderer"),containerSelector:n=>n.closest("ytd-playlist-renderer")},{nodes:document.querySelectorAll("a.ytd-playlist-video-renderer"),highlightClass:"wsn-youtube-focused-video",highlightedElementSelector:n=>n.closest("ytd-playlist-video-renderer"),containerSelector:n=>n.closest("ytd-playlist-video-renderer")},{nodes:document.querySelectorAll("div#content a.ytd-radio-renderer"),highlightClass:"wsn-youtube-focused-video"},{nodes:document.querySelectorAll('ytd-grid-video-renderer a#video-title:not([aria-hidden="true"])'),highlightClass:"wsn-youtube-focused-grid-video",highlightedElementSelector:n=>n.closest("ytd-grid-video-renderer"),containerSelector:n=>n.closest("ytd-grid-video-renderer")}],homePageElements={nodes:document.querySelectorAll("ytd-rich-item-renderer a#video-title-link"),highlightClass:"wsn-youtube-focused-video",highlightedElementSelector:n=>n.closest("ytd-rich-item-renderer"),containerSelector:n=>n.closest("ytd-rich-item-renderer")},includedElements=getSortedSearchResults([...includedElements,homePageElements],[]),homePageElements=Array.from(homePageElements.nodes).some(n=>null!=n.offsetParent),gridRow=document.querySelector("ytd-rich-grid-row");return homePageElements&&null!=gridRow&&(includedElements.itemsPerRow=gridRow.getElementsByTagName("ytd-rich-item-renderer").length,includedElements.gridNavigation=0 *:first-of-type ytd-search-filter-renderer");let neededForm=null;switch(period){case"h":neededForm=forms[0];break;case"d":neededForm=forms[1];break;case"w":neededForm=forms[2];break;case"m":neededForm=forms[3];break;case"y":neededForm=forms[4]}neededForm&&neededForm.childNodes[1].click()}}class GoogleScholar{constructor(options){this.options=options}get urlPattern(){return/^https:\/\/scholar\.google\./}get searchBoxSelector(){return"#gs_hdr_tsi"}getSearchResults(){var includedElements=[{nodes:document.querySelectorAll(".gs_rt a"),highlightClass:"wsn-google-focused-link",highlightedElementSelector:n=>n.closest(".gs_rt"),containerSelector:n=>n.parentElement.parentElement},{nodes:document.querySelectorAll(".gs_ico_nav_previous, .gs_ico_nav_next"),anchorSelector:n=>n.parentElement,highlightClass:"wsn-google-scholar-next-page",highlightedElementSelector:n=>n.parentElement.children[1],containerSelector:n=>n.parentElement.children[1]}];return getSortedSearchResults(includedElements,[])}get previousPageButton(){var previousPageElement=document.querySelector(".gs_ico_nav_previous");return null!==previousPageElement?previousPageElement.parentElement:null}get nextPageButton(){var nextPageElement=document.querySelector(".gs_ico_nav_next");return null!==nextPageElement?nextPageElement.parentElement:null}}class Amazon{constructor(options){this.options=options}get urlPattern(){return/^https:\/\/(www\.)?amazon\./}get searchBoxSelector(){return"#twotabsearchtextbox"}onChangedResults(callback){var container=document.querySelector(".s-main-slot");container&&new MutationObserver(debounce((mutationsList,observer)=>{callback(!1)},50)).observe(container,{attributes:!1,childList:!0,subtree:!1})}getSearchResults(){var includedElements=[{nodes:document.querySelectorAll(".s-main-slot .a-carousel-card h2 .a-link-normal.a-text-normal"),highlightedElementSelector:n=>n.closest(".a-carousel-card"),highlightClass:"wsn-amazon-focused-carousel-item",containerSelector:n=>n.closest(".a-carousel-card")},{nodes:document.querySelectorAll(".s-main-slot h2 .a-link-normal.a-text-normal"),highlightedElementSelector:n=>n.closest(".a-section").parentElement.closest(".a-section"),highlightClass:"wsn-amazon-focused-item",containerSelector:n=>n.closest(".a-section").parentElement.closest(".a-section")},{nodes:document.querySelectorAll("a.s-pagination-item"),highlightClass:"wsn-amazon-focused-item"},{nodes:document.querySelectorAll(".sc-list-item-content .a-list-item .a-link-normal"),highlightClass:"wsn-amazon-focused-cart-item",highlightedElementSelector:n=>n.closest(".sc-list-item-content"),containerSelector:n=>n.closest(".sc-list-item-content")}],excludedElements=document.querySelectorAll('.a-pagination .a-selected a, .a-carousel-card[aria-hidden="true"] a');return getSortedSearchResults(includedElements,excludedElements)}get previousPageButton(){return document.querySelector("a.s-pagination-previous")}get nextPageButton(){return document.querySelector("a.s-pagination-next")}}class Github{constructor(options){this.options=options}get urlPattern(){return/^https:\/\/(www\.)?github\.com/}get searchBoxSelector(){return'input[name="q"]'}static#getCommitSearchLinks(){var commits=[];for(const con of document.querySelectorAll("#commit_search_results .text-normal")){var links=con.querySelectorAll("a");0!==links.length&&(1===links.length?commits.push(links[0]):null!=(links=con.querySelector('a[data-hovercard-type="pull_request"]'))&&commits.push(links))}return commits}getSearchResults(){var includedElements=[{nodes:document.querySelectorAll(".repo-list a"),highlightClass:"wsn-github-focused-item",containerSelector:n=>n.closest(".mt-n1")},{nodes:document.querySelectorAll("#code_search_results .text-normal a"),highlightClass:"wsn-github-focused-item"},{nodes:Github.#getCommitSearchLinks(),highlightClass:"wsn-github-focused-item"},{nodes:document.querySelectorAll("#issue_search_results .text-normal a"),highlightClass:"wsn-github-focused-item"},{nodes:document.querySelectorAll("#marketplace_search_results .text-normal a"),highlightClass:"wsn-github-focused-item"},{nodes:document.querySelectorAll("#topic_search_results .text-normal a"),highlightClass:"wsn-github-focused-item"},{nodes:document.querySelectorAll("#wiki_search_results .text-normal a"),highlightClass:"wsn-github-focused-item"},{nodes:document.querySelectorAll("#user_search_results .text-normal a"),highlightClass:"wsn-github-focused-item"},{nodes:document.querySelectorAll(".pinned-item-list-item-content span.repo"),highlightClass:"wsn-github-focused-item",highlightedElementSelector:n=>n.closest("a"),containerSelector:n=>n.closest("a"),anchorSelector:n=>n.closest("a")},{nodes:document.querySelectorAll('#user-repositories-list a[itemprop*="codeRepository"]'),highlightClass:"wsn-github-focused-item",containerSelector:n=>n.closest("li")||n},{nodes:document.querySelectorAll(".paginate-container a"),highlightClass:"wsn-github-focused-pagination"}],excludedElements=("stars"===new URLSearchParams(window.location.search).get("tab")&&includedElements.push({nodes:document.querySelectorAll("h3 a"),highlightClass:"wsn-github-focused-item"}),[...document.querySelectorAll(".muted-link, .Link--muted"),...document.querySelectorAll(".topic-tag")]);return getSortedSearchResults(includedElements,excludedElements)}onChangedResults(callback){var container=document.querySelector("body");if(container){let lastURL=window.location.href;new MutationObserver(debounce((mutationsList,observer)=>{let appendOnly=!0;window.location.href!==lastURL&&(lastURL=window.location.href,appendOnly=!1),callback(appendOnly)},50)).observe(container,{attributes:!1,childList:!0,subtree:!1})}}get tabs(){return{}}}class Gitlab{constructor(options){this.options=options}get urlPattern(){return/^https:\/\/(www\.)?gitlab\.com/}get searchBoxSelector(){return".form-input, input[id=search]"}getTopMargin(element){return getFixedSearchBoxTopMargin(document.querySelector("header.navbar"),element)}onChangedResults(callback){var containers=document.querySelectorAll(".projects-list, .groups-list, #content-body"),observer=new MutationObserver(async(mutationsList,observer)=>{callback(!0)});for(const container of containers)observer.observe(container,{attributes:!1,childList:!0,subtree:!0})}getSearchResults(){var includedElements=[{nodes:document.querySelectorAll("li.project-row h2 a"),containerSelector:n=>n.closest("li.project-row"),highlightedElementSelector:n=>n.closest("li.project-row"),highlightClass:"wsn-gitlab-focused-group-row"},{nodes:document.querySelectorAll("ul.groups-list li.group-row a[aria-label]"),containerSelector:n=>n.closest("li.group-row"),highlightedElementSelector:n=>n.closest("li.group-row"),highlightClass:"wsn-gitlab-focused-group-row"},{nodes:document.querySelectorAll("li.page-item a.page-link"),containerSelector:n=>n.closest("li.page-item"),highlightedElementSelector:n=>n.closest("li.group-row"),highlightClass:"wsn-gitlab-focused-group-row"}];return getSortedSearchResults(includedElements)}}class CustomGitlab extends Gitlab{get urlPattern(){return new RegExp(this.options.customGitlabUrl)}}const getSearchEngine=options=>{var searchEngines=[new GoogleSearch(options),new BraveSearch(options),new StartPage(options),new YouTube(options),new GoogleScholar(options),new Amazon(options),new Github(options),new Gitlab(options),new CustomGitlab(options)],href=window.location.href;for(let i=0;i{if(null!=element){let topMargin=0,bottomMargin=(searchEngine.getTopMargin&&(topMargin=searchEngine.getTopMargin(element)),getDefaultBottomMargin());searchEngine.getBottomMargin&&(bottomMargin=searchEngine.getBottomMargin(element));var searchEngine=element.getBoundingClientRect(),scrollY=window.scrollY;return searchEngine.topwindow.innerHeight&&(element.scrollIntoView(!1),window.scrollBy(0,bottomMargin)),.01{bindings.sort((a,b)=>b[0].split(" ").length-a[0].split(" ").length);let lastEvent,lastHandlerResult;for(const[shortcut,element,global,callback]of bindings){var wrappedCallback=event=>!toggle.active||(event!==lastEvent||lastHandlerResult?(lastEvent=event,lastHandlerResult=callback(event)):void 0);global?Mousetrap(element).bindGlobal(shortcut,wrappedCallback):Mousetrap(element).bind(shortcut,wrappedCallback)}};class SearchResultsManager{constructor(searchEngine,options){this.searchEngine=searchEngine,this.options=options,this.focusedIndex=-1,this.isInitialFocusSet=!1}reloadSearchResults(){this.searchResults=this.searchEngine.getSearchResults(),this.isInitialFocusSet||this.setInitialFocus()}setInitialFocus(){var lastNavigation;0!==this.searchResults.length&&(lastNavigation=this.options.local.values,location.href===lastNavigation.lastQueryUrl&&0<=lastNavigation.lastFocusedIndex&&lastNavigation.lastFocusedIndex=this.searchResults.length?null:this.searchResults[this.focusedIndex].anchor:(isLink="a"===focusedElement.localName&&focusedElement.hasAttribute("href"),!linkOnly||isLink?focusedElement:void 0)}highlight(searchResult){var highlighted=searchResult.highlightedElement;null==highlighted?console.error("No element to highlight: %o",highlighted):(highlighted.classList.add(searchResult.highlightClass),!this.options.sync.get("hideOutline")&&searchResult.anchor===highlighted||searchResult.anchor.classList.add("wsn-no-outline"))}unhighlight(searchResult){var highlighted=searchResult.highlightedElement;null==highlighted?console.error("No element to unhighlight: %o",highlighted):(highlighted.classList.remove(searchResult.highlightClass),highlighted.classList.remove("wsn-no-outline"))}focus(index,scroll=FOCUS_SCROLL_ONLY){if(0<=this.focusedIndex){const searchResult=this.searchResults[this.focusedIndex];if(scroll===FOCUS_SCROLL_ONLY&&scrollToElement(this.searchEngine,searchResult.container))return;this.unhighlight(searchResult)}const searchResult=this.searchResults[index];searchResult?(this.highlight(searchResult),searchResult.anchor.focus({preventScroll:!0}),scroll!==FOCUS_SCROLL_OFF&&scrollToElement(this.searchEngine,searchResult.container),this.focusedIndex=index,this.isInitialFocusSet=!0):this.focusedIndex=-1}focusNext(shouldWrap){this.focusedIndexsetTimeout(resolve,milliseconds)),this.injectCSS(),this.initKeybindings())}injectCSS(){var style=document.createElement("style");style.textContent=this.options.sync.get("customCSS"),document.head.append(style)}initKeybindings(){this.bindingsToggle.active=!1;for(var[shortcut,element,,]of this.bindings){element=Mousetrap(element);element.unbind(shortcut),element.reset()}var isFirstCall=0===this.bindings.length;this.bindings=[],window.location.href.match(/^https:\/\/(www)\.youtube\.com\/watch/)||this.initResultsNavigation(isFirstCall),this.initTabsNavigation(),this.initChangeToolsNavigation(),this.initSearchInputNavigation(),this.bindingsToggle={active:!0},bindKeys(this.bindings,this.bindingsToggle)}initSearchInputNavigation(){let searchInput=document.querySelector(this.searchEngine.searchBoxSelector);if(null!=searchInput){const shouldHandleSearchInputKey=event=>event.ctrlKey||event.metaKey||"Escape"===event.key,detectSearchInput=()=>null!=searchInput&&null!=searchInput.offsetParent||null!=(searchInput=document.querySelector(this.searchEngine.searchBoxSelector))&&null!=searchInput.offsetParent;let lastEvent;this.register(this.options.sync.get("focusSearchInput"),event=>{if(detectSearchInput())return event===lastEvent?!shouldHandleSearchInputKey(event):!(!(event=document.activeElement).isContentEditable&&!["textarea","input"].includes(event.tagName.toLowerCase())&&(scrollToElement(this.searchEngine,searchInput),searchInput.select(),1))}),this.register(this.options.sync.get("focusSearchInput"),event=>{if(detectSearchInput()){if(lastEvent=event,shouldHandleSearchInputKey(event)){if(0===searchInput.selectionStart&&searchInput.selectionEnd===searchInput.value.length)return scrollToElement(this.searchEngine,searchInput),searchInput.setSelectionRange(searchInput.value.length,searchInput.value.length),!1;window.setTimeout(()=>searchInput.blur())}return!0}},searchInput,!0)}}registerObject(obj){for(const[optionName,elementOrGetter]of Object.entries(obj))this.register(this.options.sync.get(optionName),()=>{if(null==elementOrGetter)return!0;let element;return null==(element=elementOrGetter instanceof HTMLElement?elementOrGetter:elementOrGetter())||("FORM"==element.tagName?element.submit():element.click(),!1)})}initTabsNavigation(){var tabs=this.searchEngine.tabs||{};this.registerObject(tabs)}initResultsNavigation(isFirstCall){this.registerObject({navigatePreviousResultPage:this.searchEngine.previousPageButton,navigateNextResultPage:this.searchEngine.nextPageButton}),this.resetResultsManager();let gridNavigation=this.resultsManager.searchResults.gridNavigation;this.registerResultsNavigationKeybindings(gridNavigation),isFirstCall&&this.searchEngine.onChangedResults&&this.searchEngine.onChangedResults(appendedOnly=>{appendedOnly?this.resultsManager.reloadSearchResults():this.resetResultsManager(),gridNavigation!=this.resultsManager.searchResults.gridNavigation&&(gridNavigation=this.resultsManager.searchResults.gridNavigation,this.initKeybindings())})}resetResultsManager(){var searchResult;null!=this.resultsManager&&0<=this.resultsManager.focusedIndex&&null!=(searchResult=this.resultsManager.searchResults[this.resultsManager.focusedIndex])&&this.resultsManager.unhighlight(searchResult),this.resultsManager=new SearchResultsManager(this.searchEngine,this.options),this.resultsManager.reloadSearchResults()}registerResultsNavigationKeybindings(gridNavigation){const getOpt=key=>this.options.sync.get(key);var onFocusChange=callback=>()=>{return this.resultsManager.isInitialFocusSet?callback.bind(this.resultsManager)(getOpt("wrapNavigation")):this.resultsManager.focus(0),!1};gridNavigation?(this.register(getOpt("nextKey"),onFocusChange(this.resultsManager.focusDown)),this.register(getOpt("previousKey"),onFocusChange(this.resultsManager.focusUp)),this.register(getOpt("navigatePreviousResultPage"),onFocusChange(this.resultsManager.focusPrevious)),this.register(getOpt("navigateNextResultPage"),onFocusChange(this.resultsManager.focusNext))):(this.register(getOpt("nextKey"),onFocusChange(this.resultsManager.focusNext)),this.register(getOpt("previousKey"),onFocusChange(this.resultsManager.focusPrevious))),this.register(getOpt("navigateKey"),()=>{var lastNavigation,link=this.resultsManager.getElementToNavigate();return null==link||((lastNavigation=this.options.local.values).lastQueryUrl=location.href,lastNavigation.lastFocusedIndex=this.resultsManager.focusedIndex,this.options.local.save(),"a"===link.localName&&link.href?window.location.href=link.href:link.click(),!1)}),this.register(getOpt("navigateNewTabKey"),()=>{var link=this.resultsManager.getElementToNavigate(!0);return null==link||(browser.runtime.sendMessage({type:"tabsCreate",options:{url:link.href,active:!0}}),!1)}),this.register(getOpt("navigateNewTabBackgroundKey"),()=>{var mouseEventParams,middleClickMousedown,link=this.resultsManager.getElementToNavigate(!0);return null==link||(getOpt("simulateMiddleClick")&&(mouseEventParams={bubbles:!0,cancelable:!1,view:window,button:1,which:2,buttons:0,clientX:link.getBoundingClientRect().x,clientY:link.getBoundingClientRect().y},middleClickMousedown=new MouseEvent("mousedown",mouseEventParams),link.dispatchEvent(middleClickMousedown),middleClickMousedown=new MouseEvent("mouseup",mouseEventParams),link.dispatchEvent(middleClickMousedown)),browser.runtime.sendMessage({type:"tabsCreate",options:{url:link.href,active:!1}}),!1)})}initChangeToolsNavigation(){var getOpt;null!=this.searchEngine.changeTools&&(this.register((getOpt=key=>this.options.sync.get(key))("navigateShowAll"),()=>this.searchEngine.changeTools("a")),this.register(getOpt("navigateShowHour"),()=>this.searchEngine.changeTools("h")),this.register(getOpt("navigateShowDay"),()=>this.searchEngine.changeTools("d")),this.register(getOpt("navigateShowWeek"),()=>this.searchEngine.changeTools("w")),this.register(getOpt("navigateShowMonth"),()=>this.searchEngine.changeTools("m")),this.register(getOpt("navigateShowYear"),()=>this.searchEngine.changeTools("y")),this.register(getOpt("toggleVerbatimSearch"),()=>this.searchEngine.changeTools("v")),this.register(getOpt("toggleSort"),()=>this.searchEngine.changeTools(null)),this.register(getOpt("showImagesLarge"),()=>this.searchEngine.changeImageSize("l")),this.register(getOpt("showImagesMedium"),()=>this.searchEngine.changeImageSize("e")),this.register(getOpt("showImagesIcon"),()=>this.searchEngine.changeImageSize("i")))}register(shortcuts,callback,element=document,global=!1){for(const shortcut of shortcuts)this.bindings.push([shortcut,element,global,callback])}}const extension=new WebSearchNavigator;extension.init(); ```
eggbean commented 3 months ago

@Explosion-Scratch Just tried this and I'm surprised how well it works. Have you got an updated version that fixes the issue with 'i' for the Images tab?

eslint in Tampermonkey shows a lot of warnings and errors?