├── .github └── workflows │ └── main.yml ├── .gitignore ├── README.md ├── RogueDex.png ├── background.js ├── content.js ├── inject.js ├── injected.js ├── libs ├── crypto-js.min.js ├── enums │ ├── Nature.js │ ├── Stat.js │ ├── Types.js │ └── WeatherType.js ├── httpjsutils.js ├── httputils.js ├── localstorageutils.js ├── lodash.js ├── pokeapi.js ├── pokerogueutils.js └── utils.js ├── manifest_chrome.json ├── manifest_firefox.json ├── roguedex_chrome.zip ├── roguedex_firefox.zip ├── service_worker.js └── styles.css /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build RogueDex 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | 7 | jobs: 8 | build_chrome: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - name: Create Zip File 13 | run: | 14 | mv manifest_chrome.json manifest.json 15 | zip -r roguedex.zip *.js *.css *.html manifest.json 16 | - name: Upload Artifact 17 | uses: actions/upload-artifact@v3 18 | with: 19 | name: roguedex_chrome 20 | path: roguedex_chrome.zip 21 | 22 | build_firefox: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v3 26 | - name: Create Zip File 27 | run: | 28 | mv manifest_firefox.json manifest.json 29 | zip -r roguedex.zip *.js *.css *.html manifest.json 30 | - name: Upload Artifact 31 | uses: actions/upload-artifact@v3 32 | with: 33 | name: roguedex_firefox 34 | path: roguedex_firefox.zip 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | manifest.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rogue Dex Browser Extension 2 | 3 | ## Description 4 | Rogue Dex is a browser extension that connects to Pokerogue and uses PokeAPI to show information about Pokemon weaknesses, immunities, and resistances for each round. 5 | 6 | ## Features 7 | - Displays Pokemon weaknesses, immunities, and resistances in real-time during gameplay. 8 | - Enhances the Pokerogue experience by providing valuable Pokemon information. 9 | 10 | ## Installation 11 | - Clone this repository to your local machine. 12 | - Load the extension in developer mode in your browser. 13 | - Launch Pokerogue and start playing to see Pokemon data in action. 14 | 15 | ## Usage 16 | - Start a new game or load a saved game in Pokerogue. 17 | - The extension will display Pokemon information for each round. 18 | - Use the data to strategize your gameplay effectively. 19 | 20 | ## Contribution 21 | Feel free to contribute to this project by forking the repository, making changes, and submitting pull requests. 22 | 23 | ## Credits 24 | [PokeAPI](https://github.com/PokeAPI/pokeapi) for various pokemon-related assets 25 | 26 | ## Policy 27 | RogueDex License 28 | 29 | This software is licensed under the MIT License. 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 32 | 33 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 34 | 35 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | Privacy Notice 38 | 39 | This software does not collect or transmit any user data to external servers. All data analysis is performed locally on the user's browser. There is no server component that interacts with or processes this data. Your privacy is paramount and we are committed to protecting it. 40 | -------------------------------------------------------------------------------- /RogueDex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roguedex-dev/roguedex/dfb5c85222ce7a7e3918ee03bb5e415efdfbf10b/RogueDex.png -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | const browserApi = typeof browser !== "undefined" ? browser : chrome; 2 | let slotId = -1 3 | 4 | function updateDiv(pokemon, weather, message) { 5 | browserApi.tabs.query({ active: true, currentWindow: true }, function (tabs) { 6 | browserApi.tabs.sendMessage(tabs[0].id, { type: message, pokemon: pokemon, weather: weather, slotId: slotId }, (response) => { 7 | if (response && response.success) { 8 | console.log('Div updated successfully'); 9 | } else { 10 | console.error('Failed to update div'); 11 | } 12 | }); 13 | }); 14 | } 15 | 16 | function sortById(a, b) { 17 | if (a.id > b.id) return 1 18 | else if (a.id < b.id) return -1 19 | else return 0 20 | } 21 | 22 | // message can be either "UPDATE_ALLIES_DIV" or "UPDATE_ENEMIES_DIV" 23 | function appendPokemonArrayToDiv(pokemonArray, arena, message) { 24 | let frontendPokemonArray = [] 25 | let itemsProcessed = 0; 26 | pokemonArray.forEach((pokemon, index, array) => { 27 | const pokemonId = Utils.convertPokemonId(pokemon.species) 28 | let weather = {} 29 | if (arena.weather && arena.weather.weatherType) { 30 | weather = { 31 | 'type': WeatherType[arena.weather.weatherType], 32 | 'turnsLeft': arena.weather.turnsLeft || 0 33 | } 34 | } 35 | PokeApi.getAbility(pokemonId, pokemon.abilityIndex).then((ability) => { 36 | Utils.getPokemonTypeEffectiveness(pokemonId).then((typeEffectiveness) => { 37 | console.log("Got pokemon", pokemonId, "ability", ability, "type effectiveness", typeEffectiveness) 38 | frontendPokemonArray.push({ 39 | 'id': pokemonId, 40 | 'typeEffectiveness': { 41 | 'weaknesses': Array.from(typeEffectiveness.weaknesses), 42 | 'resistances': Array.from(typeEffectiveness.resistances), 43 | 'immunities': Array.from(typeEffectiveness.immunities) 44 | }, 45 | 'ivs': pokemon.ivs, 46 | 'ability': ability, 47 | 'nature': { 48 | name: Nature[pokemon.nature], 49 | description: PokeRogueUtils.getNatureDescription(pokemon.nature) 50 | } 51 | }) 52 | itemsProcessed++; 53 | if (itemsProcessed === array.length) 54 | updateDiv(frontendPokemonArray.sort(sortById), weather, message) 55 | }) 56 | }) 57 | }) 58 | } 59 | 60 | browserApi.runtime.onMessage.addListener(function(request, sender, sendResponse) { 61 | // Happens when loading a savegame or continuing an old run 62 | if (request.type == 'BG_GET_SAVEDATA') { 63 | const savedata = request.data 64 | slotId = request.slotId 65 | console.log("Received save data", savedata) 66 | appendPokemonArrayToDiv(Utils.mapPartyToPokemonArray(savedata.enemyParty), savedata.arena, "UPDATE_ENEMIES_DIV") 67 | appendPokemonArrayToDiv(Utils.mapPartyToPokemonArray(savedata.party), savedata.arena, "UPDATE_ALLIES_DIV") 68 | } 69 | }); 70 | 71 | browserApi.webRequest.onBeforeRequest.addListener( 72 | function(details) { 73 | if (details.method === 'POST') { 74 | try { 75 | let sessionData = JSON.parse(new TextDecoder().decode(details.requestBody.raw[0].bytes)) 76 | console.log("POST Session data:", sessionData) 77 | if (details.url.includes("updateall")) sessionData = sessionData.session 78 | appendPokemonArrayToDiv(Utils.mapPartyToPokemonArray(sessionData.enemyParty), sessionData.arena, "UPDATE_ENEMIES_DIV") 79 | appendPokemonArrayToDiv(Utils.mapPartyToPokemonArray(sessionData.party), sessionData.arena, "UPDATE_ALLIES_DIV") 80 | } catch (e) { 81 | console.error("Error while intercepting web request: ", e) 82 | } 83 | } 84 | }, 85 | { 86 | urls: ['https://api.pokerogue.net/savedata/update?datatype=1*', 'https://api.pokerogue.net/savedata/updateall'] 87 | }, 88 | ["requestBody"] 89 | ) 90 | -------------------------------------------------------------------------------- /content.js: -------------------------------------------------------------------------------- 1 | HttpUtils.createTopBannerDiv() 2 | 3 | HttpUtils.createWrapperDivs() 4 | 5 | chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { 6 | console.log("Got message:", message, "from", sender, "current message:", document.getElementById('touchControls').getAttribute('data-ui-mode')) 7 | const uiMode = touchControlsElement.getAttribute('data-ui-mode') 8 | console.log("Current ui mode: ", uiMode) 9 | if (message.type === 'UPDATE_ENEMIES_DIV' || message.type === 'UPDATE_ALLIES_DIV') { 10 | LocalStorageUtils.slotId = message.slotId 11 | if (uiMode === 'SAVE_SLOT') LocalStorageUtils.cleanSessionData() 12 | if (uiMode === 'TITLE' || uiMode === 'SAVE_SLOT') return sendResponse({ success: true }) 13 | 14 | let divId = message.type === 'UPDATE_ENEMIES_DIV' ? 'enemies' : 'allies' 15 | HttpUtils.updateFromMessage(message) 16 | HttpUtils.createCardsDiv(divId) 17 | sendResponse({ success: true }); 18 | } 19 | }); 20 | 21 | const touchControlsElement = document.getElementById('touchControls') 22 | if (touchControlsElement) { 23 | const observer = new MutationObserver((mutations) => { 24 | mutations.forEach(async (mutation) => { 25 | if (!(mutation.type === 'attributes' && mutation.attributeName === 'data-ui-mode')) return 26 | const newValue = touchControlsElement.getAttribute('data-ui-mode'); 27 | console.log('New data-ui-mode:', newValue); 28 | if(newValue === "MESSAGE" || newValue === "COMMAND" || newValue === "CONFIRM") { 29 | browserApi.runtime.sendMessage({ 30 | type: 'BG_GET_SAVEDATA', 31 | data: LocalStorageUtils.getCurrentSessionData(localStorage), 32 | slotId: LocalStorageUtils.slotId 33 | }) 34 | } else { 35 | if (newValue === "SAVE_SLOT") { 36 | //TODO: Perhaps observe changes in local storage? 37 | setTimeout(LocalStorageUtils.cleanSessionData, 1000) 38 | } 39 | HttpUtils.deleteWrapperDivs() 40 | } 41 | }); 42 | }); 43 | 44 | observer.observe(touchControlsElement, { attributes: true }); 45 | } -------------------------------------------------------------------------------- /inject.js: -------------------------------------------------------------------------------- 1 | console.log('content script start'); 2 | 3 | const browserApi = typeof browser !== "undefined" ? browser : chrome; 4 | 5 | // inject injected script 6 | var s = document.createElement('script'); 7 | s.src = browserApi.runtime.getURL('injected.js'); 8 | s.onload = function () { 9 | this.remove(); 10 | }; 11 | (document.head || document.documentElement).appendChild(s); 12 | 13 | // receive message from injected script 14 | window.addEventListener('message', function (e) { 15 | if (e.data.type === 'GET_SAVEDATA') { 16 | browserApi.runtime.sendMessage({ type: 'BG_GET_SAVEDATA', data: e.data.data, slotId: e.data.slotId }, function(response) { 17 | if (response && response.success) { 18 | console.log('Successfully updated game info'); 19 | } else { 20 | console.error('Failed to update game info'); 21 | } 22 | }); 23 | } 24 | }); -------------------------------------------------------------------------------- /injected.js: -------------------------------------------------------------------------------- 1 | // This is a hack because in background.js we cannot read web request response's body. 2 | // When we need to do that, we intercept the web request here, and send a message to background.js with the response data, elaborate there and send back to content.js 3 | (function (xhr) { 4 | 5 | var XHR = XMLHttpRequest.prototype; 6 | 7 | var open = XHR.open; 8 | var send = XHR.send; 9 | 10 | XHR.open = function (method, url) { 11 | this._method = method; 12 | this._url = url; 13 | return open.apply(this, arguments); 14 | }; 15 | 16 | XHR.send = function (postData) { 17 | //console.log('injected script xhr request:', this._method, this._url, this.getAllResponseHeaders(), postData); 18 | this.addEventListener('load', function () { 19 | //window.postMessage({ type: 'xhr', data: this.response }, '*'); // send to content script 20 | }); 21 | return send.apply(this, arguments); 22 | }; 23 | })(XMLHttpRequest); 24 | 25 | const { fetch: origFetch } = window; 26 | window.fetch = async (...args) => { 27 | const response = await origFetch(...args); 28 | if (!response.url.includes('api.pokerogue.net/savedata/session?slot') && 29 | !response.url.includes('api.pokerogue.net/savedata/updateall')) return response 30 | 31 | let sessionSlotRegex = /.*\/session\?slot=(\d+).*/ 32 | let slotId = -1 33 | if (sessionSlotRegex.test(response.url)){ 34 | slotId = sessionSlotRegex.exec(response.url)[1] 35 | } 36 | response 37 | .clone() 38 | .json() // maybe json(), text(), blob() 39 | .then(data => { 40 | window.postMessage({ type: 'GET_SAVEDATA', data: data, slotId: slotId }, '*'); // send to content script 41 | //window.postMessage({ type: 'fetch', data: URL.createObjectURL(data) }, '*'); // if a big media file, can createObjectURL before send to content script 42 | }) 43 | .catch(err => console.error(err)); 44 | return response; 45 | }; -------------------------------------------------------------------------------- /libs/crypto-js.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports?module.exports=exports=e():"function"==typeof define&&define.amd?define([],e):t.CryptoJS=e()}(this,function(){var n,o,s,a,h,t,e,l,r,i,c,f,d,u,p,S,x,b,A,H,z,_,v,g,y,B,w,k,m,C,D,E,R,M,F,P,W,O,I,U=U||function(h){var i;if("undefined"!=typeof window&&window.crypto&&(i=window.crypto),"undefined"!=typeof self&&self.crypto&&(i=self.crypto),!(i=!(i=!(i="undefined"!=typeof globalThis&&globalThis.crypto?globalThis.crypto:i)&&"undefined"!=typeof window&&window.msCrypto?window.msCrypto:i)&&"undefined"!=typeof global&&global.crypto?global.crypto:i)&&"function"==typeof require)try{i=require("crypto")}catch(t){}var r=Object.create||function(t){return e.prototype=t,t=new e,e.prototype=null,t};function e(){}var t={},n=t.lib={},o=n.Base={extend:function(t){var e=r(this);return t&&e.mixIn(t),e.hasOwnProperty("init")&&this.init!==e.init||(e.init=function(){e.$super.init.apply(this,arguments)}),(e.init.prototype=e).$super=this,e},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},l=n.WordArray=o.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:4*t.length},toString:function(t){return(t||c).stringify(this)},concat:function(t){var e=this.words,r=t.words,i=this.sigBytes,n=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o>>2]>>>24-o%4*8&255;e[i+o>>>2]|=s<<24-(i+o)%4*8}else for(var c=0;c>>2]=r[c>>>2];return this.sigBytes+=n,this},clamp:function(){var t=this.words,e=this.sigBytes;t[e>>>2]&=4294967295<<32-e%4*8,t.length=h.ceil(e/4)},clone:function(){var t=o.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var e=[],r=0;r>>2]>>>24-n%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new l.init(r,e/2)}},a=s.Latin1={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>24-n%4*8&255;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new l.init(r,e)}},f=s.Utf8={stringify:function(t){try{return decodeURIComponent(escape(a.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return a.parse(unescape(encodeURIComponent(t)))}},d=n.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new l.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=f.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(t){var e,r=this._data,i=r.words,n=r.sigBytes,o=this.blockSize,s=n/(4*o),c=(s=t?h.ceil(s):h.max((0|s)-this._minBufferSize,0))*o,n=h.min(4*c,n);if(c){for(var a=0;a>>32-e}function j(t,e,r,i){var n,o=this._iv;o?(n=o.slice(0),this._iv=void 0):n=this._prevBlock,i.encryptBlock(n,0);for(var s=0;s>24&255)?(r=t>>8&255,i=255&t,255===(e=t>>16&255)?(e=0,255===r?(r=0,255===i?i=0:++i):++r):++e,t=0,t+=e<<16,t+=r<<8,t+=i):t+=1<<24,t}function N(){for(var t=this._X,e=this._C,r=0;r<8;r++)E[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16;R[r]=((n*n>>>17)+n*o>>>15)+o*o^((4294901760&i)*i|0)+((65535&i)*i|0)}t[0]=R[0]+(R[7]<<16|R[7]>>>16)+(R[6]<<16|R[6]>>>16)|0,t[1]=R[1]+(R[0]<<8|R[0]>>>24)+R[7]|0,t[2]=R[2]+(R[1]<<16|R[1]>>>16)+(R[0]<<16|R[0]>>>16)|0,t[3]=R[3]+(R[2]<<8|R[2]>>>24)+R[1]|0,t[4]=R[4]+(R[3]<<16|R[3]>>>16)+(R[2]<<16|R[2]>>>16)|0,t[5]=R[5]+(R[4]<<8|R[4]>>>24)+R[3]|0,t[6]=R[6]+(R[5]<<16|R[5]>>>16)+(R[4]<<16|R[4]>>>16)|0,t[7]=R[7]+(R[6]<<8|R[6]>>>24)+R[5]|0}function q(){for(var t=this._X,e=this._C,r=0;r<8;r++)O[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16;I[r]=((n*n>>>17)+n*o>>>15)+o*o^((4294901760&i)*i|0)+((65535&i)*i|0)}t[0]=I[0]+(I[7]<<16|I[7]>>>16)+(I[6]<<16|I[6]>>>16)|0,t[1]=I[1]+(I[0]<<8|I[0]>>>24)+I[7]|0,t[2]=I[2]+(I[1]<<16|I[1]>>>16)+(I[0]<<16|I[0]>>>16)|0,t[3]=I[3]+(I[2]<<8|I[2]>>>24)+I[1]|0,t[4]=I[4]+(I[3]<<16|I[3]>>>16)+(I[2]<<16|I[2]>>>16)|0,t[5]=I[5]+(I[4]<<8|I[4]>>>24)+I[3]|0,t[6]=I[6]+(I[5]<<16|I[5]>>>16)+(I[4]<<16|I[4]>>>16)|0,t[7]=I[7]+(I[6]<<8|I[6]>>>24)+I[5]|0}return F=(M=U).lib,n=F.Base,o=F.WordArray,(M=M.x64={}).Word=n.extend({init:function(t,e){this.high=t,this.low=e}}),M.WordArray=n.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:8*t.length},toX32:function(){for(var t=this.words,e=t.length,r=[],i=0;i>>2]|=t[i]<<24-i%4*8;s.call(this,r,e)}else s.apply(this,arguments)}).prototype=P),function(){var t=U,n=t.lib.WordArray,t=t.enc;t.Utf16=t.Utf16BE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>16-n%4*8&65535;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>1]|=t.charCodeAt(i)<<16-i%2*16;return n.create(r,2*e)}};function s(t){return t<<8&4278255360|t>>>8&16711935}t.Utf16LE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>16-n%4*8&65535);i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>1]|=s(t.charCodeAt(i)<<16-i%2*16);return n.create(r,2*e)}}}(),a=(w=U).lib.WordArray,w.enc.Base64={stringify:function(t){var e=t.words,r=t.sigBytes,i=this._map;t.clamp();for(var n=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(e[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|e[o+2>>>2]>>>24-(o+2)%4*8&255,c=0;c<4&&o+.75*c>>6*(3-c)&63));var a=i.charAt(64);if(a)for(;n.length%4;)n.push(a);return n.join("")},parse:function(t){var e=t.length,r=this._map;if(!(i=this._reverseMap))for(var i=this._reverseMap=[],n=0;n>>6-o%4*2,c=s|c,i[n>>>2]|=c<<24-n%4*8,n++)}return a.create(i,n)}(t,e,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},h=(F=U).lib.WordArray,F.enc.Base64url={stringify:function(t,e=!0){var r=t.words,i=t.sigBytes,n=e?this._safe_map:this._map;t.clamp();for(var o=[],s=0;s>>2]>>>24-s%4*8&255)<<16|(r[s+1>>>2]>>>24-(s+1)%4*8&255)<<8|r[s+2>>>2]>>>24-(s+2)%4*8&255,a=0;a<4&&s+.75*a>>6*(3-a)&63));var h=n.charAt(64);if(h)for(;o.length%4;)o.push(h);return o.join("")},parse:function(t,e=!0){var r=t.length,i=e?this._safe_map:this._map;if(!(n=this._reverseMap))for(var n=this._reverseMap=[],o=0;o>>6-o%4*2,c=s|c,i[n>>>2]|=c<<24-n%4*8,n++)}return h.create(i,n)}(t,r,n)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",_safe_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"},function(a){var t=U,e=t.lib,r=e.WordArray,i=e.Hasher,e=t.algo,A=[];!function(){for(var t=0;t<64;t++)A[t]=4294967296*a.abs(a.sin(t+1))|0}();e=e.MD5=i.extend({_doReset:function(){this._hash=new r.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}var o=this._hash.words,s=t[e+0],c=t[e+1],a=t[e+2],h=t[e+3],l=t[e+4],f=t[e+5],d=t[e+6],u=t[e+7],p=t[e+8],_=t[e+9],y=t[e+10],v=t[e+11],g=t[e+12],B=t[e+13],w=t[e+14],k=t[e+15],m=H(m=o[0],b=o[1],x=o[2],S=o[3],s,7,A[0]),S=H(S,m,b,x,c,12,A[1]),x=H(x,S,m,b,a,17,A[2]),b=H(b,x,S,m,h,22,A[3]);m=H(m,b,x,S,l,7,A[4]),S=H(S,m,b,x,f,12,A[5]),x=H(x,S,m,b,d,17,A[6]),b=H(b,x,S,m,u,22,A[7]),m=H(m,b,x,S,p,7,A[8]),S=H(S,m,b,x,_,12,A[9]),x=H(x,S,m,b,y,17,A[10]),b=H(b,x,S,m,v,22,A[11]),m=H(m,b,x,S,g,7,A[12]),S=H(S,m,b,x,B,12,A[13]),x=H(x,S,m,b,w,17,A[14]),m=z(m,b=H(b,x,S,m,k,22,A[15]),x,S,c,5,A[16]),S=z(S,m,b,x,d,9,A[17]),x=z(x,S,m,b,v,14,A[18]),b=z(b,x,S,m,s,20,A[19]),m=z(m,b,x,S,f,5,A[20]),S=z(S,m,b,x,y,9,A[21]),x=z(x,S,m,b,k,14,A[22]),b=z(b,x,S,m,l,20,A[23]),m=z(m,b,x,S,_,5,A[24]),S=z(S,m,b,x,w,9,A[25]),x=z(x,S,m,b,h,14,A[26]),b=z(b,x,S,m,p,20,A[27]),m=z(m,b,x,S,B,5,A[28]),S=z(S,m,b,x,a,9,A[29]),x=z(x,S,m,b,u,14,A[30]),m=C(m,b=z(b,x,S,m,g,20,A[31]),x,S,f,4,A[32]),S=C(S,m,b,x,p,11,A[33]),x=C(x,S,m,b,v,16,A[34]),b=C(b,x,S,m,w,23,A[35]),m=C(m,b,x,S,c,4,A[36]),S=C(S,m,b,x,l,11,A[37]),x=C(x,S,m,b,u,16,A[38]),b=C(b,x,S,m,y,23,A[39]),m=C(m,b,x,S,B,4,A[40]),S=C(S,m,b,x,s,11,A[41]),x=C(x,S,m,b,h,16,A[42]),b=C(b,x,S,m,d,23,A[43]),m=C(m,b,x,S,_,4,A[44]),S=C(S,m,b,x,g,11,A[45]),x=C(x,S,m,b,k,16,A[46]),m=D(m,b=C(b,x,S,m,a,23,A[47]),x,S,s,6,A[48]),S=D(S,m,b,x,u,10,A[49]),x=D(x,S,m,b,w,15,A[50]),b=D(b,x,S,m,f,21,A[51]),m=D(m,b,x,S,g,6,A[52]),S=D(S,m,b,x,h,10,A[53]),x=D(x,S,m,b,y,15,A[54]),b=D(b,x,S,m,c,21,A[55]),m=D(m,b,x,S,p,6,A[56]),S=D(S,m,b,x,k,10,A[57]),x=D(x,S,m,b,d,15,A[58]),b=D(b,x,S,m,B,21,A[59]),m=D(m,b,x,S,l,6,A[60]),S=D(S,m,b,x,v,10,A[61]),x=D(x,S,m,b,a,15,A[62]),b=D(b,x,S,m,_,21,A[63]),o[0]=o[0]+m|0,o[1]=o[1]+b|0,o[2]=o[2]+x|0,o[3]=o[3]+S|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32;var n=a.floor(r/4294967296),r=r;e[15+(64+i>>>9<<4)]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8),e[14+(64+i>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),t.sigBytes=4*(e.length+1),this._process();for(var e=this._hash,o=e.words,s=0;s<4;s++){var c=o[s];o[s]=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8)}return e},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function H(t,e,r,i,n,o,s){s=t+(e&r|~e&i)+n+s;return(s<>>32-o)+e}function z(t,e,r,i,n,o,s){s=t+(e&i|r&~i)+n+s;return(s<>>32-o)+e}function C(t,e,r,i,n,o,s){s=t+(e^r^i)+n+s;return(s<>>32-o)+e}function D(t,e,r,i,n,o,s){s=t+(r^(e|~i))+n+s;return(s<>>32-o)+e}t.MD5=i._createHelper(e),t.HmacMD5=i._createHmacHelper(e)}(Math),P=(M=U).lib,t=P.WordArray,e=P.Hasher,P=M.algo,l=[],P=P.SHA1=e.extend({_doReset:function(){this._hash=new t.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=0;a<80;a++){a<16?l[a]=0|t[e+a]:(h=l[a-3]^l[a-8]^l[a-14]^l[a-16],l[a]=h<<1|h>>>31);var h=(i<<5|i>>>27)+c+l[a];h+=a<20?1518500249+(n&o|~n&s):a<40?1859775393+(n^o^s):a<60?(n&o|n&s|o&s)-1894007588:(n^o^s)-899497514,c=s,s=o,o=n<<30|n>>>2,n=i,i=h}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+c|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=Math.floor(r/4294967296),e[15+(64+i>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=e.clone.call(this);return t._hash=this._hash.clone(),t}}),M.SHA1=e._createHelper(P),M.HmacSHA1=e._createHmacHelper(P),function(n){var t=U,e=t.lib,r=e.WordArray,i=e.Hasher,e=t.algo,o=[],p=[];!function(){function t(t){return 4294967296*(t-(0|t))|0}for(var e=2,r=0;r<64;)!function(t){for(var e=n.sqrt(t),r=2;r<=e;r++)if(!(t%r))return;return 1}(e)||(r<8&&(o[r]=t(n.pow(e,.5))),p[r]=t(n.pow(e,1/3)),r++),e++}();var _=[],e=e.SHA256=i.extend({_doReset:function(){this._hash=new r.init(o.slice(0))},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=r[5],h=r[6],l=r[7],f=0;f<64;f++){f<16?_[f]=0|t[e+f]:(d=_[f-15],u=_[f-2],_[f]=((d<<25|d>>>7)^(d<<14|d>>>18)^d>>>3)+_[f-7]+((u<<15|u>>>17)^(u<<13|u>>>19)^u>>>10)+_[f-16]);var d=i&n^i&o^n&o,u=l+((c<<26|c>>>6)^(c<<21|c>>>11)^(c<<7|c>>>25))+(c&a^~c&h)+p[f]+_[f],l=h,h=a,a=c,c=s+u|0,s=o,o=n,n=i,i=u+(((i<<30|i>>>2)^(i<<19|i>>>13)^(i<<10|i>>>22))+d)|0}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+c|0,r[5]=r[5]+a|0,r[6]=r[6]+h|0,r[7]=r[7]+l|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=n.floor(r/4294967296),e[15+(64+i>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});t.SHA256=i._createHelper(e),t.HmacSHA256=i._createHmacHelper(e)}(Math),r=(w=U).lib.WordArray,F=w.algo,i=F.SHA256,F=F.SHA224=i.extend({_doReset:function(){this._hash=new r.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var t=i._doFinalize.call(this);return t.sigBytes-=4,t}}),w.SHA224=i._createHelper(F),w.HmacSHA224=i._createHmacHelper(F),function(){var t=U,e=t.lib.Hasher,r=t.x64,i=r.Word,n=r.WordArray,r=t.algo;function o(){return i.create.apply(i,arguments)}var t1=[o(1116352408,3609767458),o(1899447441,602891725),o(3049323471,3964484399),o(3921009573,2173295548),o(961987163,4081628472),o(1508970993,3053834265),o(2453635748,2937671579),o(2870763221,3664609560),o(3624381080,2734883394),o(310598401,1164996542),o(607225278,1323610764),o(1426881987,3590304994),o(1925078388,4068182383),o(2162078206,991336113),o(2614888103,633803317),o(3248222580,3479774868),o(3835390401,2666613458),o(4022224774,944711139),o(264347078,2341262773),o(604807628,2007800933),o(770255983,1495990901),o(1249150122,1856431235),o(1555081692,3175218132),o(1996064986,2198950837),o(2554220882,3999719339),o(2821834349,766784016),o(2952996808,2566594879),o(3210313671,3203337956),o(3336571891,1034457026),o(3584528711,2466948901),o(113926993,3758326383),o(338241895,168717936),o(666307205,1188179964),o(773529912,1546045734),o(1294757372,1522805485),o(1396182291,2643833823),o(1695183700,2343527390),o(1986661051,1014477480),o(2177026350,1206759142),o(2456956037,344077627),o(2730485921,1290863460),o(2820302411,3158454273),o(3259730800,3505952657),o(3345764771,106217008),o(3516065817,3606008344),o(3600352804,1432725776),o(4094571909,1467031594),o(275423344,851169720),o(430227734,3100823752),o(506948616,1363258195),o(659060556,3750685593),o(883997877,3785050280),o(958139571,3318307427),o(1322822218,3812723403),o(1537002063,2003034995),o(1747873779,3602036899),o(1955562222,1575990012),o(2024104815,1125592928),o(2227730452,2716904306),o(2361852424,442776044),o(2428436474,593698344),o(2756734187,3733110249),o(3204031479,2999351573),o(3329325298,3815920427),o(3391569614,3928383900),o(3515267271,566280711),o(3940187606,3454069534),o(4118630271,4000239992),o(116418474,1914138554),o(174292421,2731055270),o(289380356,3203993006),o(460393269,320620315),o(685471733,587496836),o(852142971,1086792851),o(1017036298,365543100),o(1126000580,2618297676),o(1288033470,3409855158),o(1501505948,4234509866),o(1607167915,987167468),o(1816402316,1246189591)],e1=[];!function(){for(var t=0;t<80;t++)e1[t]=o()}();r=r.SHA512=e.extend({_doReset:function(){this._hash=new n.init([new i.init(1779033703,4089235720),new i.init(3144134277,2227873595),new i.init(1013904242,4271175723),new i.init(2773480762,1595750129),new i.init(1359893119,2917565137),new i.init(2600822924,725511199),new i.init(528734635,4215389547),new i.init(1541459225,327033209)])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=r[5],h=r[6],l=r[7],f=i.high,d=i.low,u=n.high,p=n.low,_=o.high,y=o.low,v=s.high,g=s.low,B=c.high,w=c.low,k=a.high,m=a.low,S=h.high,x=h.low,b=l.high,r=l.low,A=f,H=d,z=u,C=p,D=_,E=y,R=v,M=g,F=B,P=w,W=k,O=m,I=S,U=x,K=b,X=r,L=0;L<80;L++){var j,T,N=e1[L];L<16?(T=N.high=0|t[e+2*L],j=N.low=0|t[e+2*L+1]):($=(q=e1[L-15]).high,J=q.low,G=(Q=e1[L-2]).high,V=Q.low,Z=(Y=e1[L-7]).high,q=Y.low,Y=(Q=e1[L-16]).high,T=(T=(($>>>1|J<<31)^($>>>8|J<<24)^$>>>7)+Z+((j=(Z=(J>>>1|$<<31)^(J>>>8|$<<24)^(J>>>7|$<<25))+q)>>>0>>0?1:0))+((G>>>19|V<<13)^(G<<3|V>>>29)^G>>>6)+((j+=J=(V>>>19|G<<13)^(V<<3|G>>>29)^(V>>>6|G<<26))>>>0>>0?1:0),j+=$=Q.low,N.high=T=T+Y+(j>>>0<$>>>0?1:0),N.low=j);var q=F&W^~F&I,Z=P&O^~P&U,V=A&z^A&D^z&D,G=(H>>>28|A<<4)^(H<<30|A>>>2)^(H<<25|A>>>7),J=t1[L],Q=J.high,Y=J.low,$=X+((P>>>14|F<<18)^(P>>>18|F<<14)^(P<<23|F>>>9)),N=K+((F>>>14|P<<18)^(F>>>18|P<<14)^(F<<23|P>>>9))+($>>>0>>0?1:0),J=G+(H&C^H&E^C&E),K=I,X=U,I=W,U=O,W=F,O=P,F=R+(N=(N=(N=N+q+(($=$+Z)>>>0>>0?1:0))+Q+(($=$+Y)>>>0>>0?1:0))+T+(($=$+j)>>>0>>0?1:0))+((P=M+$|0)>>>0>>0?1:0)|0,R=D,M=E,D=z,E=C,z=A,C=H,A=N+(((A>>>28|H<<4)^(A<<30|H>>>2)^(A<<25|H>>>7))+V+(J>>>0>>0?1:0))+((H=$+J|0)>>>0<$>>>0?1:0)|0}d=i.low=d+H,i.high=f+A+(d>>>0>>0?1:0),p=n.low=p+C,n.high=u+z+(p>>>0>>0?1:0),y=o.low=y+E,o.high=_+D+(y>>>0>>0?1:0),g=s.low=g+M,s.high=v+R+(g>>>0>>0?1:0),w=c.low=w+P,c.high=B+F+(w>>>0

>>0?1:0),m=a.low=m+O,a.high=k+W+(m>>>0>>0?1:0),x=h.low=x+U,h.high=S+I+(x>>>0>>0?1:0),r=l.low=r+X,l.high=b+K+(r>>>0>>0?1:0)},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[30+(128+i>>>10<<5)]=Math.floor(r/4294967296),e[31+(128+i>>>10<<5)]=r,t.sigBytes=4*e.length,this._process(),this._hash.toX32()},clone:function(){var t=e.clone.call(this);return t._hash=this._hash.clone(),t},blockSize:32});t.SHA512=e._createHelper(r),t.HmacSHA512=e._createHmacHelper(r)}(),P=(M=U).x64,c=P.Word,f=P.WordArray,P=M.algo,d=P.SHA512,P=P.SHA384=d.extend({_doReset:function(){this._hash=new f.init([new c.init(3418070365,3238371032),new c.init(1654270250,914150663),new c.init(2438529370,812702999),new c.init(355462360,4144912697),new c.init(1731405415,4290775857),new c.init(2394180231,1750603025),new c.init(3675008525,1694076839),new c.init(1203062813,3204075428)])},_doFinalize:function(){var t=d._doFinalize.call(this);return t.sigBytes-=16,t}}),M.SHA384=d._createHelper(P),M.HmacSHA384=d._createHmacHelper(P),function(l){var t=U,e=t.lib,f=e.WordArray,i=e.Hasher,d=t.x64.Word,e=t.algo,A=[],H=[],z=[];!function(){for(var t=1,e=0,r=0;r<24;r++){A[t+5*e]=(r+1)*(r+2)/2%64;var i=(2*t+3*e)%5;t=e%5,e=i}for(t=0;t<5;t++)for(e=0;e<5;e++)H[t+5*e]=e+(2*t+3*e)%5*5;for(var n=1,o=0;o<24;o++){for(var s,c=0,a=0,h=0;h<7;h++)1&n&&((s=(1<>>24)|4278255360&(o<<24|o>>>8);(m=r[n]).high^=s=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),m.low^=o}for(var c=0;c<24;c++){for(var a=0;a<5;a++){for(var h=0,l=0,f=0;f<5;f++)h^=(m=r[a+5*f]).high,l^=m.low;var d=C[a];d.high=h,d.low=l}for(a=0;a<5;a++)for(var u=C[(a+4)%5],p=C[(a+1)%5],_=p.high,p=p.low,h=u.high^(_<<1|p>>>31),l=u.low^(p<<1|_>>>31),f=0;f<5;f++)(m=r[a+5*f]).high^=h,m.low^=l;for(var y=1;y<25;y++){var v=(m=r[y]).high,g=m.low,B=A[y];l=B<32?(h=v<>>32-B,g<>>32-B):(h=g<>>64-B,v<>>64-B);B=C[H[y]];B.high=h,B.low=l}var w=C[0],k=r[0];w.high=k.high,w.low=k.low;for(a=0;a<5;a++)for(f=0;f<5;f++){var m=r[y=a+5*f],S=C[y],x=C[(a+1)%5+5*f],b=C[(a+2)%5+5*f];m.high=S.high^~x.high&b.high,m.low=S.low^~x.low&b.low}m=r[0],k=z[c];m.high^=k.high,m.low^=k.low}},_doFinalize:function(){var t=this._data,e=t.words,r=(this._nDataBytes,8*t.sigBytes),i=32*this.blockSize;e[r>>>5]|=1<<24-r%32,e[(l.ceil((1+r)/i)*i>>>5)-1]|=128,t.sigBytes=4*e.length,this._process();for(var n=this._state,e=this.cfg.outputLength/8,o=e/8,s=[],c=0;c>>24)|4278255360&(h<<24|h>>>8);s.push(a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8)),s.push(h)}return new f.init(s,e)},clone:function(){for(var t=i.clone.call(this),e=t._state=this._state.slice(0),r=0;r<25;r++)e[r]=e[r].clone();return t}});t.SHA3=i._createHelper(e),t.HmacSHA3=i._createHmacHelper(e)}(Math),Math,F=(w=U).lib,u=F.WordArray,p=F.Hasher,F=w.algo,S=u.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),x=u.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),b=u.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),A=u.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),H=u.create([0,1518500249,1859775393,2400959708,2840853838]),z=u.create([1352829926,1548603684,1836072691,2053994217,0]),F=F.RIPEMD160=p.extend({_doReset:function(){this._hash=u.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}for(var o,s,c,a,h,l,f=this._hash.words,d=H.words,u=z.words,p=S.words,_=x.words,y=b.words,v=A.words,g=o=f[0],B=s=f[1],w=c=f[2],k=a=f[3],m=h=f[4],r=0;r<80;r+=1)l=o+t[e+p[r]]|0,l+=r<16?(s^c^a)+d[0]:r<32?K(s,c,a)+d[1]:r<48?((s|~c)^a)+d[2]:r<64?X(s,c,a)+d[3]:(s^(c|~a))+d[4],l=(l=L(l|=0,y[r]))+h|0,o=h,h=a,a=L(c,10),c=s,s=l,l=g+t[e+_[r]]|0,l+=r<16?(B^(w|~k))+u[0]:r<32?X(B,w,k)+u[1]:r<48?((B|~w)^k)+u[2]:r<64?K(B,w,k)+u[3]:(B^w^k)+u[4],l=(l=L(l|=0,v[r]))+m|0,g=m,m=k,k=L(w,10),w=B,B=l;l=f[1]+c+k|0,f[1]=f[2]+a+m|0,f[2]=f[3]+h+g|0,f[3]=f[4]+o+B|0,f[4]=f[0]+s+w|0,f[0]=l},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),t.sigBytes=4*(e.length+1),this._process();for(var e=this._hash,n=e.words,o=0;o<5;o++){var s=n[o];n[o]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8)}return e},clone:function(){var t=p.clone.call(this);return t._hash=this._hash.clone(),t}}),w.RIPEMD160=p._createHelper(F),w.HmacRIPEMD160=p._createHmacHelper(F),P=(M=U).lib.Base,_=M.enc.Utf8,M.algo.HMAC=P.extend({init:function(t,e){t=this._hasher=new t.init,"string"==typeof e&&(e=_.parse(e));var r=t.blockSize,i=4*r;(e=e.sigBytes>i?t.finalize(e):e).clamp();for(var t=this._oKey=e.clone(),e=this._iKey=e.clone(),n=t.words,o=e.words,s=0;s>>2];t.sigBytes-=e}},d=(e.BlockCipher=a.extend({cfg:a.cfg.extend({mode:n,padding:l}),reset:function(){var t;a.reset.call(this);var e=this.cfg,r=e.iv,e=e.mode;this._xformMode==this._ENC_XFORM_MODE?t=e.createEncryptor:(t=e.createDecryptor,this._minBufferSize=1),this._mode&&this._mode.__creator==t?this._mode.init(this,r&&r.words):(this._mode=t.call(e,this,r&&r.words),this._mode.__creator=t)},_doProcessBlock:function(t,e){this._mode.processBlock(t,e)},_doFinalize:function(){var t,e=this.cfg.padding;return this._xformMode==this._ENC_XFORM_MODE?(e.pad(this._data,this.blockSize),t=this._process(!0)):(t=this._process(!0),e.unpad(t)),t},blockSize:4}),e.CipherParams=r.extend({init:function(t){this.mixIn(t)},toString:function(t){return(t||this.formatter).stringify(this)}})),l=(t.format={}).OpenSSL={stringify:function(t){var e=t.ciphertext,t=t.salt,e=t?s.create([1398893684,1701076831]).concat(t).concat(e):e;return e.toString(o)},parse:function(t){var e,r=o.parse(t),t=r.words;return 1398893684==t[0]&&1701076831==t[1]&&(e=s.create(t.slice(2,4)),t.splice(0,4),r.sigBytes-=16),d.create({ciphertext:r,salt:e})}},u=e.SerializableCipher=r.extend({cfg:r.extend({format:l}),encrypt:function(t,e,r,i){i=this.cfg.extend(i);var n=t.createEncryptor(r,i),e=n.finalize(e),n=n.cfg;return d.create({ciphertext:e,key:r,iv:n.iv,algorithm:t,mode:n.mode,padding:n.padding,blockSize:t.blockSize,formatter:i.format})},decrypt:function(t,e,r,i){return i=this.cfg.extend(i),e=this._parse(e,i.format),t.createDecryptor(r,i).finalize(e.ciphertext)},_parse:function(t,e){return"string"==typeof t?e.parse(t,this):t}}),t=(t.kdf={}).OpenSSL={execute:function(t,e,r,i){i=i||s.random(8);t=c.create({keySize:e+r}).compute(t,i),r=s.create(t.words.slice(e),4*r);return t.sigBytes=4*e,d.create({key:t,iv:r,salt:i})}},p=e.PasswordBasedCipher=u.extend({cfg:u.cfg.extend({kdf:t}),encrypt:function(t,e,r,i){r=(i=this.cfg.extend(i)).kdf.execute(r,t.keySize,t.ivSize);i.iv=r.iv;i=u.encrypt.call(this,t,e,r.key,i);return i.mixIn(r),i},decrypt:function(t,e,r,i){i=this.cfg.extend(i),e=this._parse(e,i.format);r=i.kdf.execute(r,t.keySize,t.ivSize,e.salt);return i.iv=r.iv,u.decrypt.call(this,t,e,r.key,i)}})}(),U.mode.CFB=((F=U.lib.BlockCipherMode.extend()).Encryptor=F.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize;j.call(this,t,e,i,r),this._prevBlock=t.slice(e,e+i)}}),F.Decryptor=F.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=t.slice(e,e+i);j.call(this,t,e,i,r),this._prevBlock=n}}),F),U.mode.CTR=(M=U.lib.BlockCipherMode.extend(),P=M.Encryptor=M.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._counter;n&&(o=this._counter=n.slice(0),this._iv=void 0);var s=o.slice(0);r.encryptBlock(s,0),o[i-1]=o[i-1]+1|0;for(var c=0;c>>2]|=e<<24-r%4*8,t.sigBytes+=e},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},U.pad.Iso10126={pad:function(t,e){e*=4,e-=t.sigBytes%e;t.concat(U.lib.WordArray.random(e-1)).concat(U.lib.WordArray.create([e<<24],1))},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},U.pad.Iso97971={pad:function(t,e){t.concat(U.lib.WordArray.create([2147483648],1)),U.pad.ZeroPadding.pad(t,e)},unpad:function(t){U.pad.ZeroPadding.unpad(t),t.sigBytes--}},U.pad.ZeroPadding={pad:function(t,e){e*=4;t.clamp(),t.sigBytes+=e-(t.sigBytes%e||e)},unpad:function(t){for(var e=t.words,r=t.sigBytes-1,r=t.sigBytes-1;0<=r;r--)if(e[r>>>2]>>>24-r%4*8&255){t.sigBytes=r+1;break}}},U.pad.NoPadding={pad:function(){},unpad:function(){}},m=(P=U).lib.CipherParams,C=P.enc.Hex,P.format.Hex={stringify:function(t){return t.ciphertext.toString(C)},parse:function(t){t=C.parse(t);return m.create({ciphertext:t})}},function(){var t=U,e=t.lib.BlockCipher,r=t.algo,h=[],l=[],f=[],d=[],u=[],p=[],_=[],y=[],v=[],g=[];!function(){for(var t=[],e=0;e<256;e++)t[e]=e<128?e<<1:e<<1^283;for(var r=0,i=0,e=0;e<256;e++){var n=i^i<<1^i<<2^i<<3^i<<4;h[r]=n=n>>>8^255&n^99;var o=t[l[n]=r],s=t[o],c=t[s],a=257*t[n]^16843008*n;f[r]=a<<24|a>>>8,d[r]=a<<16|a>>>16,u[r]=a<<8|a>>>24,p[r]=a,_[n]=(a=16843009*c^65537*s^257*o^16843008*r)<<24|a>>>8,y[n]=a<<16|a>>>16,v[n]=a<<8|a>>>24,g[n]=a,r?(r=o^t[t[t[c^o]]],i^=t[t[i]]):r=i=1}}();var B=[0,1,2,4,8,16,32,64,128,27,54],r=r.AES=e.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var t=this._keyPriorReset=this._key,e=t.words,r=t.sigBytes/4,i=4*(1+(this._nRounds=6+r)),n=this._keySchedule=[],o=0;o>>24]<<24|h[a>>>16&255]<<16|h[a>>>8&255]<<8|h[255&a]):(a=h[(a=a<<8|a>>>24)>>>24]<<24|h[a>>>16&255]<<16|h[a>>>8&255]<<8|h[255&a],a^=B[o/r|0]<<24),n[o]=n[o-r]^a);for(var s=this._invKeySchedule=[],c=0;c>>24]]^y[h[a>>>16&255]]^v[h[a>>>8&255]]^g[h[255&a]]}}},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._keySchedule,f,d,u,p,h)},decryptBlock:function(t,e){var r=t[e+1];t[e+1]=t[e+3],t[e+3]=r,this._doCryptBlock(t,e,this._invKeySchedule,_,y,v,g,l);r=t[e+1];t[e+1]=t[e+3],t[e+3]=r},_doCryptBlock:function(t,e,r,i,n,o,s,c){for(var a=this._nRounds,h=t[e]^r[0],l=t[e+1]^r[1],f=t[e+2]^r[2],d=t[e+3]^r[3],u=4,p=1;p>>24]^n[l>>>16&255]^o[f>>>8&255]^s[255&d]^r[u++],y=i[l>>>24]^n[f>>>16&255]^o[d>>>8&255]^s[255&h]^r[u++],v=i[f>>>24]^n[d>>>16&255]^o[h>>>8&255]^s[255&l]^r[u++],g=i[d>>>24]^n[h>>>16&255]^o[l>>>8&255]^s[255&f]^r[u++],h=_,l=y,f=v,d=g;_=(c[h>>>24]<<24|c[l>>>16&255]<<16|c[f>>>8&255]<<8|c[255&d])^r[u++],y=(c[l>>>24]<<24|c[f>>>16&255]<<16|c[d>>>8&255]<<8|c[255&h])^r[u++],v=(c[f>>>24]<<24|c[d>>>16&255]<<16|c[h>>>8&255]<<8|c[255&l])^r[u++],g=(c[d>>>24]<<24|c[h>>>16&255]<<16|c[l>>>8&255]<<8|c[255&f])^r[u++];t[e]=_,t[e+1]=y,t[e+2]=v,t[e+3]=g},keySize:8});t.AES=e._createHelper(r)}(),function(){var t=U,e=t.lib,i=e.WordArray,r=e.BlockCipher,e=t.algo,h=[57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4],l=[14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32],f=[1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28],d=[{0:8421888,268435456:32768,536870912:8421378,805306368:2,1073741824:512,1342177280:8421890,1610612736:8389122,1879048192:8388608,2147483648:514,2415919104:8389120,2684354560:33280,2952790016:8421376,3221225472:32770,3489660928:8388610,3758096384:0,4026531840:33282,134217728:0,402653184:8421890,671088640:33282,939524096:32768,1207959552:8421888,1476395008:512,1744830464:8421378,2013265920:2,2281701376:8389120,2550136832:33280,2818572288:8421376,3087007744:8389122,3355443200:8388610,3623878656:32770,3892314112:514,4160749568:8388608,1:32768,268435457:2,536870913:8421888,805306369:8388608,1073741825:8421378,1342177281:33280,1610612737:512,1879048193:8389122,2147483649:8421890,2415919105:8421376,2684354561:8388610,2952790017:33282,3221225473:514,3489660929:8389120,3758096385:32770,4026531841:0,134217729:8421890,402653185:8421376,671088641:8388608,939524097:512,1207959553:32768,1476395009:8388610,1744830465:2,2013265921:33282,2281701377:32770,2550136833:8389122,2818572289:514,3087007745:8421888,3355443201:8389120,3623878657:0,3892314113:33280,4160749569:8421378},{0:1074282512,16777216:16384,33554432:524288,50331648:1074266128,67108864:1073741840,83886080:1074282496,100663296:1073758208,117440512:16,134217728:540672,150994944:1073758224,167772160:1073741824,184549376:540688,201326592:524304,218103808:0,234881024:16400,251658240:1074266112,8388608:1073758208,25165824:540688,41943040:16,58720256:1073758224,75497472:1074282512,92274688:1073741824,109051904:524288,125829120:1074266128,142606336:524304,159383552:0,176160768:16384,192937984:1074266112,209715200:1073741840,226492416:540672,243269632:1074282496,260046848:16400,268435456:0,285212672:1074266128,301989888:1073758224,318767104:1074282496,335544320:1074266112,352321536:16,369098752:540688,385875968:16384,402653184:16400,419430400:524288,436207616:524304,452984832:1073741840,469762048:540672,486539264:1073758208,503316480:1073741824,520093696:1074282512,276824064:540688,293601280:524288,310378496:1074266112,327155712:16384,343932928:1073758208,360710144:1074282512,377487360:16,394264576:1073741824,411041792:1074282496,427819008:1073741840,444596224:1073758224,461373440:524304,478150656:0,494927872:16400,511705088:1074266128,528482304:540672},{0:260,1048576:0,2097152:67109120,3145728:65796,4194304:65540,5242880:67108868,6291456:67174660,7340032:67174400,8388608:67108864,9437184:67174656,10485760:65792,11534336:67174404,12582912:67109124,13631488:65536,14680064:4,15728640:256,524288:67174656,1572864:67174404,2621440:0,3670016:67109120,4718592:67108868,5767168:65536,6815744:65540,7864320:260,8912896:4,9961472:256,11010048:67174400,12058624:65796,13107200:65792,14155776:67109124,15204352:67174660,16252928:67108864,16777216:67174656,17825792:65540,18874368:65536,19922944:67109120,20971520:256,22020096:67174660,23068672:67108868,24117248:0,25165824:67109124,26214400:67108864,27262976:4,28311552:65792,29360128:67174400,30408704:260,31457280:65796,32505856:67174404,17301504:67108864,18350080:260,19398656:67174656,20447232:0,21495808:65540,22544384:67109120,23592960:256,24641536:67174404,25690112:65536,26738688:67174660,27787264:65796,28835840:67108868,29884416:67109124,30932992:67174400,31981568:4,33030144:65792},{0:2151682048,65536:2147487808,131072:4198464,196608:2151677952,262144:0,327680:4198400,393216:2147483712,458752:4194368,524288:2147483648,589824:4194304,655360:64,720896:2147487744,786432:2151678016,851968:4160,917504:4096,983040:2151682112,32768:2147487808,98304:64,163840:2151678016,229376:2147487744,294912:4198400,360448:2151682112,425984:0,491520:2151677952,557056:4096,622592:2151682048,688128:4194304,753664:4160,819200:2147483648,884736:4194368,950272:4198464,1015808:2147483712,1048576:4194368,1114112:4198400,1179648:2147483712,1245184:0,1310720:4160,1376256:2151678016,1441792:2151682048,1507328:2147487808,1572864:2151682112,1638400:2147483648,1703936:2151677952,1769472:4198464,1835008:2147487744,1900544:4194304,1966080:64,2031616:4096,1081344:2151677952,1146880:2151682112,1212416:0,1277952:4198400,1343488:4194368,1409024:2147483648,1474560:2147487808,1540096:64,1605632:2147483712,1671168:4096,1736704:2147487744,1802240:2151678016,1867776:4160,1933312:2151682048,1998848:4194304,2064384:4198464},{0:128,4096:17039360,8192:262144,12288:536870912,16384:537133184,20480:16777344,24576:553648256,28672:262272,32768:16777216,36864:537133056,40960:536871040,45056:553910400,49152:553910272,53248:0,57344:17039488,61440:553648128,2048:17039488,6144:553648256,10240:128,14336:17039360,18432:262144,22528:537133184,26624:553910272,30720:536870912,34816:537133056,38912:0,43008:553910400,47104:16777344,51200:536871040,55296:553648128,59392:16777216,63488:262272,65536:262144,69632:128,73728:536870912,77824:553648256,81920:16777344,86016:553910272,90112:537133184,94208:16777216,98304:553910400,102400:553648128,106496:17039360,110592:537133056,114688:262272,118784:536871040,122880:0,126976:17039488,67584:553648256,71680:16777216,75776:17039360,79872:537133184,83968:536870912,88064:17039488,92160:128,96256:553910272,100352:262272,104448:553910400,108544:0,112640:553648128,116736:16777344,120832:262144,124928:537133056,129024:536871040},{0:268435464,256:8192,512:270532608,768:270540808,1024:268443648,1280:2097152,1536:2097160,1792:268435456,2048:0,2304:268443656,2560:2105344,2816:8,3072:270532616,3328:2105352,3584:8200,3840:270540800,128:270532608,384:270540808,640:8,896:2097152,1152:2105352,1408:268435464,1664:268443648,1920:8200,2176:2097160,2432:8192,2688:268443656,2944:270532616,3200:0,3456:270540800,3712:2105344,3968:268435456,4096:268443648,4352:270532616,4608:270540808,4864:8200,5120:2097152,5376:268435456,5632:268435464,5888:2105344,6144:2105352,6400:0,6656:8,6912:270532608,7168:8192,7424:268443656,7680:270540800,7936:2097160,4224:8,4480:2105344,4736:2097152,4992:268435464,5248:268443648,5504:8200,5760:270540808,6016:270532608,6272:270540800,6528:270532616,6784:8192,7040:2105352,7296:2097160,7552:0,7808:268435456,8064:268443656},{0:1048576,16:33555457,32:1024,48:1049601,64:34604033,80:0,96:1,112:34603009,128:33555456,144:1048577,160:33554433,176:34604032,192:34603008,208:1025,224:1049600,240:33554432,8:34603009,24:0,40:33555457,56:34604032,72:1048576,88:33554433,104:33554432,120:1025,136:1049601,152:33555456,168:34603008,184:1048577,200:1024,216:34604033,232:1,248:1049600,256:33554432,272:1048576,288:33555457,304:34603009,320:1048577,336:33555456,352:34604032,368:1049601,384:1025,400:34604033,416:1049600,432:1,448:0,464:34603008,480:33554433,496:1024,264:1049600,280:33555457,296:34603009,312:1,328:33554432,344:1048576,360:1025,376:34604032,392:33554433,408:34603008,424:0,440:34604033,456:1049601,472:1024,488:33555456,504:1048577},{0:134219808,1:131072,2:134217728,3:32,4:131104,5:134350880,6:134350848,7:2048,8:134348800,9:134219776,10:133120,11:134348832,12:2080,13:0,14:134217760,15:133152,2147483648:2048,2147483649:134350880,2147483650:134219808,2147483651:134217728,2147483652:134348800,2147483653:133120,2147483654:133152,2147483655:32,2147483656:134217760,2147483657:2080,2147483658:131104,2147483659:134350848,2147483660:0,2147483661:134348832,2147483662:134219776,2147483663:131072,16:133152,17:134350848,18:32,19:2048,20:134219776,21:134217760,22:134348832,23:131072,24:0,25:131104,26:134348800,27:134219808,28:134350880,29:133120,30:2080,31:134217728,2147483664:131072,2147483665:2048,2147483666:134348832,2147483667:133152,2147483668:32,2147483669:134348800,2147483670:134217728,2147483671:134219808,2147483672:134350880,2147483673:134217760,2147483674:134219776,2147483675:0,2147483676:133120,2147483677:2080,2147483678:131104,2147483679:134350848}],u=[4160749569,528482304,33030144,2064384,129024,8064,504,2147483679],n=e.DES=r.extend({_doReset:function(){for(var t=this._key.words,e=[],r=0;r<56;r++){var i=h[r]-1;e[r]=t[i>>>5]>>>31-i%32&1}for(var n=this._subKeys=[],o=0;o<16;o++){for(var s=n[o]=[],c=f[o],r=0;r<24;r++)s[r/6|0]|=e[(l[r]-1+c)%28]<<31-r%6,s[4+(r/6|0)]|=e[28+(l[r+24]-1+c)%28]<<31-r%6;s[0]=s[0]<<1|s[0]>>>31;for(r=1;r<7;r++)s[r]=s[r]>>>4*(r-1)+3;s[7]=s[7]<<5|s[7]>>>27}for(var a=this._invSubKeys=[],r=0;r<16;r++)a[r]=n[15-r]},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._subKeys)},decryptBlock:function(t,e){this._doCryptBlock(t,e,this._invSubKeys)},_doCryptBlock:function(t,e,r){this._lBlock=t[e],this._rBlock=t[e+1],p.call(this,4,252645135),p.call(this,16,65535),_.call(this,2,858993459),_.call(this,8,16711935),p.call(this,1,1431655765);for(var i=0;i<16;i++){for(var n=r[i],o=this._lBlock,s=this._rBlock,c=0,a=0;a<8;a++)c|=d[a][((s^n[a])&u[a])>>>0];this._lBlock=s,this._rBlock=o^c}var h=this._lBlock;this._lBlock=this._rBlock,this._rBlock=h,p.call(this,1,1431655765),_.call(this,8,16711935),_.call(this,2,858993459),p.call(this,16,65535),p.call(this,4,252645135),t[e]=this._lBlock,t[e+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});function p(t,e){e=(this._lBlock>>>t^this._rBlock)&e;this._rBlock^=e,this._lBlock^=e<>>t^this._lBlock)&e;this._lBlock^=e,this._rBlock^=e<192.");var e=t.slice(0,2),r=t.length<4?t.slice(0,2):t.slice(2,4),t=t.length<6?t.slice(0,2):t.slice(4,6);this._des1=n.createEncryptor(i.create(e)),this._des2=n.createEncryptor(i.create(r)),this._des3=n.createEncryptor(i.create(t))},encryptBlock:function(t,e){this._des1.encryptBlock(t,e),this._des2.decryptBlock(t,e),this._des3.encryptBlock(t,e)},decryptBlock:function(t,e){this._des3.decryptBlock(t,e),this._des2.encryptBlock(t,e),this._des1.decryptBlock(t,e)},keySize:6,ivSize:2,blockSize:2});t.TripleDES=r._createHelper(e)}(),function(){var t=U,e=t.lib.StreamCipher,r=t.algo,i=r.RC4=e.extend({_doReset:function(){for(var t=this._key,e=t.words,r=t.sigBytes,i=this._S=[],n=0;n<256;n++)i[n]=n;for(var n=0,o=0;n<256;n++){var s=n%r,s=e[s>>>2]>>>24-s%4*8&255,o=(o+i[n]+s)%256,s=i[n];i[n]=i[o],i[o]=s}this._i=this._j=0},_doProcessBlock:function(t,e){t[e]^=n.call(this)},keySize:8,ivSize:0});function n(){for(var t=this._S,e=this._i,r=this._j,i=0,n=0;n<4;n++){var r=(r+t[e=(e+1)%256])%256,o=t[e];t[e]=t[r],t[r]=o,i|=t[(t[e]+t[r])%256]<<24-8*n}return this._i=e,this._j=r,i}t.RC4=e._createHelper(i);r=r.RC4Drop=i.extend({cfg:i.cfg.extend({drop:192}),_doReset:function(){i._doReset.call(this);for(var t=this.cfg.drop;0>>24)|4278255360&(t[r]<<24|t[r]>>>8);for(var i=this._X=[t[0],t[3]<<16|t[2]>>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],n=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]],r=this._b=0;r<4;r++)N.call(this);for(r=0;r<8;r++)n[r]^=i[r+4&7];if(e){var o=e.words,s=o[0],c=o[1],e=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),o=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8),s=e>>>16|4294901760&o,c=o<<16|65535&e;n[0]^=e,n[1]^=s,n[2]^=o,n[3]^=c,n[4]^=e,n[5]^=s,n[6]^=o,n[7]^=c;for(r=0;r<4;r++)N.call(this)}},_doProcessBlock:function(t,e){var r=this._X;N.call(this),D[0]=r[0]^r[5]>>>16^r[3]<<16,D[1]=r[2]^r[7]>>>16^r[5]<<16,D[2]=r[4]^r[1]>>>16^r[7]<<16,D[3]=r[6]^r[3]>>>16^r[1]<<16;for(var i=0;i<4;i++)D[i]=16711935&(D[i]<<8|D[i]>>>24)|4278255360&(D[i]<<24|D[i]>>>8),t[e+i]^=D[i]},blockSize:4,ivSize:2}),M.Rabbit=F._createHelper(P),F=(M=U).lib.StreamCipher,P=M.algo,W=[],O=[],I=[],P=P.RabbitLegacy=F.extend({_doReset:function(){for(var t=this._key.words,e=this.cfg.iv,r=this._X=[t[0],t[3]<<16|t[2]>>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],i=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]],n=this._b=0;n<4;n++)q.call(this);for(n=0;n<8;n++)i[n]^=r[n+4&7];if(e){var o=e.words,s=o[0],t=o[1],e=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),o=16711935&(t<<8|t>>>24)|4278255360&(t<<24|t>>>8),s=e>>>16|4294901760&o,t=o<<16|65535&e;i[0]^=e,i[1]^=s,i[2]^=o,i[3]^=t,i[4]^=e,i[5]^=s,i[6]^=o,i[7]^=t;for(n=0;n<4;n++)q.call(this)}},_doProcessBlock:function(t,e){var r=this._X;q.call(this),W[0]=r[0]^r[5]>>>16^r[3]<<16,W[1]=r[2]^r[7]>>>16^r[5]<<16,W[2]=r[4]^r[1]>>>16^r[7]<<16,W[3]=r[6]^r[3]>>>16^r[1]<<16;for(var i=0;i<4;i++)W[i]=16711935&(W[i]<<8|W[i]>>>24)|4278255360&(W[i]<<24|W[i]>>>8),t[e+i]^=W[i]},blockSize:4,ivSize:2}),M.RabbitLegacy=F._createHelper(P),U}); -------------------------------------------------------------------------------- /libs/enums/Nature.js: -------------------------------------------------------------------------------- 1 | var Nature; 2 | (function (Nature) { 3 | Nature[Nature["HARDY"] = 0] = "HARDY"; 4 | Nature[Nature["LONELY"] = 1] = "LONELY"; 5 | Nature[Nature["BRAVE"] = 2] = "BRAVE"; 6 | Nature[Nature["ADAMANT"] = 3] = "ADAMANT"; 7 | Nature[Nature["NAUGHTY"] = 4] = "NAUGHTY"; 8 | Nature[Nature["BOLD"] = 5] = "BOLD"; 9 | Nature[Nature["DOCILE"] = 6] = "DOCILE"; 10 | Nature[Nature["RELAXED"] = 7] = "RELAXED"; 11 | Nature[Nature["IMPISH"] = 8] = "IMPISH"; 12 | Nature[Nature["LAX"] = 9] = "LAX"; 13 | Nature[Nature["TIMID"] = 10] = "TIMID"; 14 | Nature[Nature["HASTY"] = 11] = "HASTY"; 15 | Nature[Nature["SERIOUS"] = 12] = "SERIOUS"; 16 | Nature[Nature["JOLLY"] = 13] = "JOLLY"; 17 | Nature[Nature["NAIVE"] = 14] = "NAIVE"; 18 | Nature[Nature["MODEST"] = 15] = "MODEST"; 19 | Nature[Nature["MILD"] = 16] = "MILD"; 20 | Nature[Nature["QUIET"] = 17] = "QUIET"; 21 | Nature[Nature["BASHFUL"] = 18] = "BASHFUL"; 22 | Nature[Nature["RASH"] = 19] = "RASH"; 23 | Nature[Nature["CALM"] = 20] = "CALM"; 24 | Nature[Nature["GENTLE"] = 21] = "GENTLE"; 25 | Nature[Nature["SASSY"] = 22] = "SASSY"; 26 | Nature[Nature["CAREFUL"] = 23] = "CAREFUL"; 27 | Nature[Nature["QUIRKY"] = 24] = "QUIRKY"; 28 | })(Nature || (Nature = {})); -------------------------------------------------------------------------------- /libs/enums/Stat.js: -------------------------------------------------------------------------------- 1 | var Stat; 2 | (function (Stat) { 3 | Stat[Stat["HP"] = 0] = "HP"; 4 | Stat[Stat["ATK"] = 1] = "ATK"; 5 | Stat[Stat["DEF"] = 2] = "DEF"; 6 | Stat[Stat["SPATK"] = 3] = "SPATK"; 7 | Stat[Stat["SPDEF"] = 4] = "SPDEF"; 8 | Stat[Stat["SPD"] = 5] = "SPD"; 9 | })(Stat || (Stat = {})); -------------------------------------------------------------------------------- /libs/enums/Types.js: -------------------------------------------------------------------------------- 1 | var Types 2 | (function (Types) { 3 | Types[Types["normal"] = 1] = 1; 4 | Types[Types["fighting"] = 2] = 2; 5 | Types[Types["flying"] = 3] = 3; 6 | Types[Types["poison"] = 4] = 4; 7 | Types[Types["ground"] = 5] = 5; 8 | Types[Types["rock"] = 6] = 6; 9 | Types[Types["bug"] = 7] = 7; 10 | Types[Types["ghost"] = 8] = 8; 11 | Types[Types["steel"] = 9] = 9; 12 | Types[Types["fire"] = 10] = 10; 13 | Types[Types["water"] = 11] = 11; 14 | Types[Types["grass"] = 12] = 12; 15 | Types[Types["electric"] = 13] = 13; 16 | Types[Types["psychic"] = 14] = 14; 17 | Types[Types["ice"] = 15] = 15; 18 | Types[Types["dragon"] = 16] = 16; 19 | Types[Types["dark"] = 17] = 17; 20 | Types[Types["fairy"] = 18] = 18; 21 | })(Types || (Types = {})); -------------------------------------------------------------------------------- /libs/enums/WeatherType.js: -------------------------------------------------------------------------------- 1 | var WeatherType; 2 | (function (WeatherType) { 3 | WeatherType[WeatherType["NONE"] = 0] = "NONE"; 4 | WeatherType[WeatherType["SUNNY"] = 1] = "SUNNY"; 5 | WeatherType[WeatherType["RAIN"] = 2] = "RAIN"; 6 | WeatherType[WeatherType["SANDSTORM"] = 3] = "SANDSTORM"; 7 | WeatherType[WeatherType["HAIL"] = 4] = "HAIL"; 8 | WeatherType[WeatherType["SNOW"] = 5] = "SNOW"; 9 | WeatherType[WeatherType["FOG"] = 6] = "FOG"; 10 | WeatherType[WeatherType["HEAVY_RAIN"] = 7] = "HEAVY_RAIN"; 11 | WeatherType[WeatherType["HARSH_SUN"] = 8] = "HARSH_SUN"; 12 | WeatherType[WeatherType["STRONG_WINDS"] = 9] = "STRONG_WINDS"; 13 | })(WeatherType || (WeatherType = {})); 14 | -------------------------------------------------------------------------------- /libs/httpjsutils.js: -------------------------------------------------------------------------------- 1 | function _changeOpacity(e) { 2 | const divId = e.target.id.split("-")[0] 3 | const div = document.getElementById(divId) 4 | _wrapperDivPositions[divId].opacity = e.target.value 5 | div.style.opacity = `${e.target.value / 100}` 6 | } 7 | 8 | function _changePage(click) { 9 | const buttonId = click.target.id 10 | const divId = buttonId.split("-")[0] 11 | const direction = buttonId.split("-")[1] 12 | if (direction === 'up') { 13 | if (divId === 'enemies') { 14 | if (_currentEnemyPage > 0) { 15 | _currentEnemyPage -= 1 16 | } else { 17 | _currentEnemyPage = _enemiesPokemon.length - 1 18 | } 19 | } else if (divId === 'allies') { 20 | if (_currentAllyPage > 0) { 21 | _currentAllyPage -= 1 22 | } else { 23 | _currentAllyPage = _alliesPokemon.length - 1 24 | } 25 | } 26 | } else if (direction === 'down') { 27 | if (divId === 'enemies') { 28 | if ((_currentEnemyPage + 1) < _enemiesPokemon.length) { 29 | _currentEnemyPage += 1 30 | } else { 31 | _currentEnemyPage = 0 32 | } 33 | } else if (divId === 'allies') { 34 | if ((_currentAllyPage + 1) < _alliesPokemon.length) { 35 | _currentAllyPage += 1 36 | } else { 37 | _currentAllyPage = 0 38 | } 39 | } 40 | } 41 | HttpUtils.createCardsDiv(divId) 42 | } 43 | 44 | // Enables drag-and-drop functionality on an element 45 | function _enableDragElement(elmnt) { 46 | let pos1 = 0, 47 | pos2 = 0, 48 | pos3 = 0, 49 | pos4 = 0; 50 | const dragStartElement = elmnt; 51 | 52 | // Attach the mousedown event handler 53 | dragStartElement.onpointerdown = dragMouseDown; 54 | function dragMouseDown(e) { 55 | e = e || window.event; 56 | if (e.target.type === 'submit' || e.target.type === 'range') return 57 | e.preventDefault(); 58 | pos3 = e.clientX; 59 | pos4 = e.clientY; 60 | document.onpointerup = stopDragging; 61 | document.onpointermove = dragElement; 62 | } 63 | 64 | // Handles dragging movement 65 | function dragElement(e) { 66 | e = e || window.event; 67 | if (e.target.type === 'submit' || e.target.type === 'range') return 68 | e.preventDefault(); 69 | pos1 = pos3 - e.clientX; 70 | pos2 = pos4 - e.clientY; 71 | pos3 = e.clientX; 72 | pos4 = e.clientY; 73 | elmnt.style.top = elmnt.offsetTop - pos2 + "px"; 74 | elmnt.style.left = elmnt.offsetLeft - pos1 + "px"; 75 | } 76 | 77 | // Stops dragging on mouse release 78 | function stopDragging() { 79 | document.onpointerup = null; 80 | document.onpointermove = null; 81 | } 82 | } -------------------------------------------------------------------------------- /libs/httputils.js: -------------------------------------------------------------------------------- 1 | function _createPokemonCardDiv(cardclass, cardId, pokemon) { 2 | let opacityRangeMin = 10; 3 | let opacityRangeMax = 100; 4 | let pokemonImageUrl = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemon.id}.png`; 5 | 6 | const opacitySlider = _createOpacitySliderDiv(cardId, _wrapperDivPositions[cardId].opacity, opacityRangeMin, opacityRangeMax) 7 | const typeEffectivenessHTML = _createTypeEffectivenessWrapper(pokemon.typeEffectiveness) 8 | 9 | let cardHTML = ` 10 |

11 |
12 | ${opacitySlider.html} 13 |
14 |
15 | 16 |
17 | 18 | ${/* Displays the 3 type effectiveness segemtns (weaknesses, resistances, immunities). */''} 19 | ${typeEffectivenessHTML} 20 | 21 |
22 | 23 |
24 |
25 | Ability: ${pokemon.ability.name} 26 | ${_createTooltipDiv(pokemon.ability.description)} 27 |
28 |  -  29 |
30 | Nature: ${pokemon.nature.name} 31 | ${_createTooltipDiv(pokemon.nature.description)} 32 |
33 |
34 |
35 | HP: ${pokemon.ivs[Stat["HP"]]}, ATK: ${pokemon.ivs[Stat["ATK"]]}, DEF: ${pokemon.ivs[Stat["DEF"]]} 36 |
37 |
38 | SPE: ${pokemon.ivs[Stat["SPD"]]}, SPD: ${pokemon.ivs[Stat["SPDEF"]]}, SPA: ${pokemon.ivs[Stat["SPATK"]]} 39 |
40 | 41 | ${(_weather.type && _weather.turnsLeft) ? 42 | `
_weather: ${_weather.type}, Turns Left: ${_weather.turnsLeft}
` 43 | : ''} 44 |
45 |
46 | ` 47 | 48 | const cardObj = {} 49 | cardObj.html = cardHTML; 50 | cardObj.slider = opacitySlider.id; 51 | 52 | return cardObj 53 | } 54 | 55 | // Current values: weaknesses, resistances, immunities 56 | function _createTypeEffectivenessWrapper(typeEffectivenesses) { 57 | let typesHTML = ` 58 | ${Object.keys(typeEffectivenesses).map((effectiveness) => { 59 | if (typeEffectivenesses[effectiveness].length === 0) return '' 60 | const tooltipMap = { 61 | weaknesses: "Weak to", 62 | resistances: "Resists", 63 | immunities: "Immune to" 64 | }; 65 | return ` 66 |
67 | 68 | ${typeEffectivenesses[effectiveness].map((type, counter) => ` 69 | ${/* The current html structure requires to wrap every third element in a div, the implementation here gets a bit ugly. */''} 70 | ${ ((counter + 1) % 3 === 1) ? 71 | `
` 72 | : ''} 73 | 74 |
75 | 76 | ${/* Closing div, after every third element or when the arrays max length is reached. */''} 77 | ${ ((counter + 1) % 3 === 0) || ((counter + 1) === typeEffectivenesses[effectiveness].length) ? 78 | `
` 79 | : ''} 80 | `).join('')} 81 | ${_createTooltipDiv(tooltipMap[effectiveness] || "")} 82 |
83 | `}).join('')} 84 | ` 85 | 86 | return typesHTML 87 | } 88 | 89 | function _createOpacitySliderDiv(divId, initialValue = "100", min = "10", max = "100") { 90 | let result = {}; 91 | result.id = `${divId}-slider` 92 | 93 | result.html = ` 94 |
95 |
Opacity:
96 | 97 |
98 | ` 99 | return result 100 | } 101 | 102 | function _updateWrapperDivPositions(oldDiv, divId) { 103 | _wrapperDivPositions[divId].top = oldDiv.style.top; 104 | _wrapperDivPositions[divId].left = oldDiv.style.left; 105 | } 106 | 107 | function _createWrapperDiv(divId) { 108 | const oldDiv = document.getElementById(divId) 109 | if (oldDiv) { 110 | _updateWrapperDivPositions(oldDiv, divId) 111 | oldDiv.remove(); 112 | } 113 | const newDiv = divId === 'enemies' ? _createEnemyDiv() : _createAlliesDiv() 114 | _enableDragElement(newDiv) 115 | newDiv.style.top = _wrapperDivPositions[divId].top 116 | newDiv.style.left = _wrapperDivPositions[divId].left 117 | newDiv.style.opacity = "" + (Number(_wrapperDivPositions[divId].opacity) / 100) 118 | return newDiv; 119 | } 120 | 121 | function _createArrowButtonsDiv(divId, upString, downString) { 122 | let result = {}; 123 | result.idUp = `${divId}-up` 124 | result.idDown = `${divId}-down` 125 | result.html = ` 126 |
127 | 128 | 129 |
130 | ` 131 | return result 132 | } 133 | 134 | function _createTooltipDiv(tip) { 135 | const tooltipHtml = ` 136 |
${tip}
137 | ` 138 | return tooltipHtml 139 | } 140 | 141 | function _createEnemyDiv() { 142 | const divId = "enemies" 143 | const div = document.createElement("div") 144 | div.className = `${divId}-team` 145 | div.id = divId 146 | _enableDragElement(div) 147 | document.body.appendChild(div) 148 | return div 149 | } 150 | 151 | function _createAlliesDiv() { 152 | const divId = "allies" 153 | const div = document.createElement("div") 154 | div.className = `${divId}-team` 155 | div.id = divId 156 | _enableDragElement(div) 157 | document.body.appendChild(div) 158 | return div 159 | } 160 | 161 | function _updatePokemonArray(oldParty, newParty) { 162 | if (!_.isEqual(oldParty, newParty)) { 163 | oldParty = newParty 164 | } 165 | } 166 | 167 | let _wrapperDivPositions = { 168 | 'enemies': { 169 | 'top' : '0', 170 | 'left': '0', 171 | 'opacity': '100' 172 | }, 173 | 'allies': { 174 | 'top': '0', 175 | 'left': '0', 176 | 'opacity': '100' 177 | } 178 | } 179 | 180 | let _currentEnemyPage = 0; 181 | let _currentAllyPage = 0; 182 | let _enemiesPokemon = []; 183 | let _alliesPokemon = []; 184 | let _weather = {}; 185 | 186 | class HttpUtils { 187 | 188 | static updateFromMessage(message) { 189 | if (message.type === 'UPDATE_ENEMIES_DIV') { 190 | if (!_.isEqual(_enemiesPokemon, message.pokemon)) { 191 | _enemiesPokemon = message.pokemon 192 | } 193 | } 194 | else { 195 | if (!_.isEqual(_alliesPokemon, message.pokemon)) { 196 | _alliesPokemon = message.pokemon 197 | } 198 | } 199 | _weather = message.weather; 200 | if (_weather.turnsLeft === 0) _weather.turnsLeft = 'N/A' 201 | } 202 | 203 | static createTopBannerDiv() { 204 | const div = document.createElement('div') 205 | div.textContent = 'RogueDex is running!' 206 | div.classList.add('text-base') 207 | div.classList.add('running-status') 208 | document.body.insertBefore(div, document.body.firstChild) 209 | } 210 | 211 | static createCardsDiv(divId) { 212 | let newDiv = _createWrapperDiv(divId) 213 | let pokemon = {} 214 | if (divId === 'enemies') { 215 | if (_currentEnemyPage >= _enemiesPokemon.length) _currentEnemyPage = 0 216 | pokemon = _enemiesPokemon[_currentEnemyPage] 217 | } 218 | else { 219 | if (_currentAllyPage >= _alliesPokemon.length) _currentAllyPage = 0 220 | pokemon = _alliesPokemon[_currentAllyPage] 221 | } 222 | 223 | let divClass = `${divId}-team` 224 | 225 | const cardObj = _createPokemonCardDiv(divClass, divId, pokemon) 226 | const buttonsObj = _createArrowButtonsDiv(divId, "↑", "↓") 227 | 228 | /* 229 | Assemble the wrapper DIVs inner html. 230 | */ 231 | const cardsHTML = ` 232 | ${buttonsObj.html} 233 | ${cardObj.html} 234 | ` 235 | 236 | /* 237 | Insert the parsed nodes into the DOM tree just inside the element, before its first child. 238 | "newDiv.innerHTML = cardsHTML" also works instead of using ".insertAdjacentHTML()" 239 | */ 240 | newDiv.insertAdjacentHTML("afterbegin", cardsHTML) 241 | document.body.appendChild(newDiv) 242 | 243 | /* 244 | Add event listeners after all elements are properly added to the DOM and initialized. 245 | */ 246 | document.getElementById(cardObj.slider).addEventListener('input', _changeOpacity) 247 | document.getElementById(buttonsObj.idUp).addEventListener('click', _changePage) 248 | document.getElementById(buttonsObj.idDown).addEventListener('click', _changePage) 249 | 250 | return newDiv 251 | } 252 | 253 | static createWrapperDivs() { 254 | try { 255 | ['allies', 'enemies'].forEach((divId) => { 256 | const div = document.createElement("div") 257 | div.className = `${divId}-team` 258 | div.id = divId 259 | _enableDragElement(div) 260 | document.body.appendChild(div) 261 | }) 262 | } catch (e) { 263 | console.error("Error while creating wrapper divs: ", e) 264 | } 265 | } 266 | 267 | static deleteWrapperDivs() { 268 | try { 269 | ['allies', 'enemies'].forEach((divId) => { 270 | const div = document.getElementById(divId) 271 | if (div === null) return 272 | _updateWrapperDivPositions(div, divId) 273 | document.body.removeChild(div) 274 | }) 275 | } catch (e) { 276 | console.error("Error while deleting wrapper divs: ", e) 277 | } 278 | } 279 | } -------------------------------------------------------------------------------- /libs/localstorageutils.js: -------------------------------------------------------------------------------- 1 | const saveKey = 'x0i2O7WRiANTqPmZ' 2 | let currentSessionData = {} 3 | 4 | class LocalStorageUtils { 5 | static slotId = -1 6 | 7 | static getCurrentSessionData(localStorage) { 8 | Object.keys(localStorage).some((key) => { 9 | if ((this.slotId > 0 && key.includes(`sessionData${this.slotId}`)) || key.includes('sessionData')) { 10 | currentSessionData = localStorage.getItem(key) 11 | } 12 | }) 13 | return JSON.parse(CryptoJS.AES.decrypt(currentSessionData, saveKey).toString(CryptoJS.enc.Utf8)) 14 | } 15 | 16 | static cleanSessionData() { 17 | let removeKeys = [] 18 | Object.keys(localStorage).some((key) => { 19 | if (key.includes('sessionData')) 20 | removeKeys.push(key) 21 | }) 22 | console.log("Found the following keys in localStorage:", removeKeys) 23 | Object.keys(removeKeys).some((key) => { 24 | console.log("Removing key", removeKeys[key]) 25 | localStorage.removeItem(removeKeys[key]) 26 | }) 27 | return removeKeys.length > 0 28 | } 29 | } -------------------------------------------------------------------------------- /libs/lodash.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Lodash (Custom Build) 4 | * Build: `lodash core -o ./dist/lodash.core.js` 5 | * Copyright OpenJS Foundation and other contributors 6 | * Released under MIT license 7 | * Based on Underscore.js 1.8.3 8 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 9 | */ 10 | ;(function() { 11 | 12 | /** Used as a safe reference for `undefined` in pre-ES5 environments. */ 13 | var undefined; 14 | 15 | /** Used as the semantic version number. */ 16 | var VERSION = '4.17.15'; 17 | 18 | /** Error message constants. */ 19 | var FUNC_ERROR_TEXT = 'Expected a function'; 20 | 21 | /** Used to compose bitmasks for value comparisons. */ 22 | var COMPARE_PARTIAL_FLAG = 1, 23 | COMPARE_UNORDERED_FLAG = 2; 24 | 25 | /** Used to compose bitmasks for function metadata. */ 26 | var WRAP_BIND_FLAG = 1, 27 | WRAP_PARTIAL_FLAG = 32; 28 | 29 | /** Used as references for various `Number` constants. */ 30 | var INFINITY = 1 / 0, 31 | MAX_SAFE_INTEGER = 9007199254740991; 32 | 33 | /** `Object#toString` result references. */ 34 | var argsTag = '[object Arguments]', 35 | arrayTag = '[object Array]', 36 | asyncTag = '[object AsyncFunction]', 37 | boolTag = '[object Boolean]', 38 | dateTag = '[object Date]', 39 | errorTag = '[object Error]', 40 | funcTag = '[object Function]', 41 | genTag = '[object GeneratorFunction]', 42 | numberTag = '[object Number]', 43 | objectTag = '[object Object]', 44 | proxyTag = '[object Proxy]', 45 | regexpTag = '[object RegExp]', 46 | stringTag = '[object String]'; 47 | 48 | /** Used to match HTML entities and HTML characters. */ 49 | var reUnescapedHtml = /[&<>"']/g, 50 | reHasUnescapedHtml = RegExp(reUnescapedHtml.source); 51 | 52 | /** Used to detect unsigned integer values. */ 53 | var reIsUint = /^(?:0|[1-9]\d*)$/; 54 | 55 | /** Used to map characters to HTML entities. */ 56 | var htmlEscapes = { 57 | '&': '&', 58 | '<': '<', 59 | '>': '>', 60 | '"': '"', 61 | "'": ''' 62 | }; 63 | 64 | /** Detect free variable `global` from Node.js. */ 65 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; 66 | 67 | /** Detect free variable `self`. */ 68 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self; 69 | 70 | /** Used as a reference to the global object. */ 71 | var root = freeGlobal || freeSelf || Function('return this')(); 72 | 73 | /** Detect free variable `exports`. */ 74 | var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; 75 | 76 | /** Detect free variable `module`. */ 77 | var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; 78 | 79 | /*--------------------------------------------------------------------------*/ 80 | 81 | /** 82 | * Appends the elements of `values` to `array`. 83 | * 84 | * @private 85 | * @param {Array} array The array to modify. 86 | * @param {Array} values The values to append. 87 | * @returns {Array} Returns `array`. 88 | */ 89 | function arrayPush(array, values) { 90 | array.push.apply(array, values); 91 | return array; 92 | } 93 | 94 | /** 95 | * The base implementation of `_.findIndex` and `_.findLastIndex` without 96 | * support for iteratee shorthands. 97 | * 98 | * @private 99 | * @param {Array} array The array to inspect. 100 | * @param {Function} predicate The function invoked per iteration. 101 | * @param {number} fromIndex The index to search from. 102 | * @param {boolean} [fromRight] Specify iterating from right to left. 103 | * @returns {number} Returns the index of the matched value, else `-1`. 104 | */ 105 | function baseFindIndex(array, predicate, fromIndex, fromRight) { 106 | var length = array.length, 107 | index = fromIndex + (fromRight ? 1 : -1); 108 | 109 | while ((fromRight ? index-- : ++index < length)) { 110 | if (predicate(array[index], index, array)) { 111 | return index; 112 | } 113 | } 114 | return -1; 115 | } 116 | 117 | /** 118 | * The base implementation of `_.property` without support for deep paths. 119 | * 120 | * @private 121 | * @param {string} key The key of the property to get. 122 | * @returns {Function} Returns the new accessor function. 123 | */ 124 | function baseProperty(key) { 125 | return function(object) { 126 | return object == null ? undefined : object[key]; 127 | }; 128 | } 129 | 130 | /** 131 | * The base implementation of `_.propertyOf` without support for deep paths. 132 | * 133 | * @private 134 | * @param {Object} object The object to query. 135 | * @returns {Function} Returns the new accessor function. 136 | */ 137 | function basePropertyOf(object) { 138 | return function(key) { 139 | return object == null ? undefined : object[key]; 140 | }; 141 | } 142 | 143 | /** 144 | * The base implementation of `_.reduce` and `_.reduceRight`, without support 145 | * for iteratee shorthands, which iterates over `collection` using `eachFunc`. 146 | * 147 | * @private 148 | * @param {Array|Object} collection The collection to iterate over. 149 | * @param {Function} iteratee The function invoked per iteration. 150 | * @param {*} accumulator The initial value. 151 | * @param {boolean} initAccum Specify using the first or last element of 152 | * `collection` as the initial value. 153 | * @param {Function} eachFunc The function to iterate over `collection`. 154 | * @returns {*} Returns the accumulated value. 155 | */ 156 | function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { 157 | eachFunc(collection, function(value, index, collection) { 158 | accumulator = initAccum 159 | ? (initAccum = false, value) 160 | : iteratee(accumulator, value, index, collection); 161 | }); 162 | return accumulator; 163 | } 164 | 165 | /** 166 | * The base implementation of `_.values` and `_.valuesIn` which creates an 167 | * array of `object` property values corresponding to the property names 168 | * of `props`. 169 | * 170 | * @private 171 | * @param {Object} object The object to query. 172 | * @param {Array} props The property names to get values for. 173 | * @returns {Object} Returns the array of property values. 174 | */ 175 | function baseValues(object, props) { 176 | return baseMap(props, function(key) { 177 | return object[key]; 178 | }); 179 | } 180 | 181 | /** 182 | * Used by `_.escape` to convert characters to HTML entities. 183 | * 184 | * @private 185 | * @param {string} chr The matched character to escape. 186 | * @returns {string} Returns the escaped character. 187 | */ 188 | var escapeHtmlChar = basePropertyOf(htmlEscapes); 189 | 190 | /** 191 | * Creates a unary function that invokes `func` with its argument transformed. 192 | * 193 | * @private 194 | * @param {Function} func The function to wrap. 195 | * @param {Function} transform The argument transform. 196 | * @returns {Function} Returns the new function. 197 | */ 198 | function overArg(func, transform) { 199 | return function(arg) { 200 | return func(transform(arg)); 201 | }; 202 | } 203 | 204 | /*--------------------------------------------------------------------------*/ 205 | 206 | /** Used for built-in method references. */ 207 | var arrayProto = Array.prototype, 208 | objectProto = Object.prototype; 209 | 210 | /** Used to check objects for own properties. */ 211 | var hasOwnProperty = objectProto.hasOwnProperty; 212 | 213 | /** Used to generate unique IDs. */ 214 | var idCounter = 0; 215 | 216 | /** 217 | * Used to resolve the 218 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) 219 | * of values. 220 | */ 221 | var nativeObjectToString = objectProto.toString; 222 | 223 | /** Used to restore the original `_` reference in `_.noConflict`. */ 224 | var oldDash = root._; 225 | 226 | /** Built-in value references. */ 227 | var objectCreate = Object.create, 228 | propertyIsEnumerable = objectProto.propertyIsEnumerable; 229 | 230 | /* Built-in method references for those with the same name as other `lodash` methods. */ 231 | var nativeIsFinite = root.isFinite, 232 | nativeKeys = overArg(Object.keys, Object), 233 | nativeMax = Math.max; 234 | 235 | /*------------------------------------------------------------------------*/ 236 | 237 | /** 238 | * Creates a `lodash` object which wraps `value` to enable implicit method 239 | * chain sequences. Methods that operate on and return arrays, collections, 240 | * and functions can be chained together. Methods that retrieve a single value 241 | * or may return a primitive value will automatically end the chain sequence 242 | * and return the unwrapped value. Otherwise, the value must be unwrapped 243 | * with `_#value`. 244 | * 245 | * Explicit chain sequences, which must be unwrapped with `_#value`, may be 246 | * enabled using `_.chain`. 247 | * 248 | * The execution of chained methods is lazy, that is, it's deferred until 249 | * `_#value` is implicitly or explicitly called. 250 | * 251 | * Lazy evaluation allows several methods to support shortcut fusion. 252 | * Shortcut fusion is an optimization to merge iteratee calls; this avoids 253 | * the creation of intermediate arrays and can greatly reduce the number of 254 | * iteratee executions. Sections of a chain sequence qualify for shortcut 255 | * fusion if the section is applied to an array and iteratees accept only 256 | * one argument. The heuristic for whether a section qualifies for shortcut 257 | * fusion is subject to change. 258 | * 259 | * Chaining is supported in custom builds as long as the `_#value` method is 260 | * directly or indirectly included in the build. 261 | * 262 | * In addition to lodash methods, wrappers have `Array` and `String` methods. 263 | * 264 | * The wrapper `Array` methods are: 265 | * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` 266 | * 267 | * The wrapper `String` methods are: 268 | * `replace` and `split` 269 | * 270 | * The wrapper methods that support shortcut fusion are: 271 | * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, 272 | * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, 273 | * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` 274 | * 275 | * The chainable wrapper methods are: 276 | * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, 277 | * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, 278 | * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, 279 | * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, 280 | * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, 281 | * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, 282 | * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, 283 | * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, 284 | * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, 285 | * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, 286 | * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, 287 | * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, 288 | * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, 289 | * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, 290 | * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, 291 | * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, 292 | * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, 293 | * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, 294 | * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, 295 | * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, 296 | * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, 297 | * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, 298 | * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, 299 | * `zipObject`, `zipObjectDeep`, and `zipWith` 300 | * 301 | * The wrapper methods that are **not** chainable by default are: 302 | * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, 303 | * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, 304 | * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, 305 | * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, 306 | * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, 307 | * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, 308 | * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, 309 | * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, 310 | * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, 311 | * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, 312 | * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, 313 | * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, 314 | * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, 315 | * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, 316 | * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, 317 | * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, 318 | * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, 319 | * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, 320 | * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, 321 | * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, 322 | * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, 323 | * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, 324 | * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, 325 | * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, 326 | * `upperFirst`, `value`, and `words` 327 | * 328 | * @name _ 329 | * @constructor 330 | * @category Seq 331 | * @param {*} value The value to wrap in a `lodash` instance. 332 | * @returns {Object} Returns the new `lodash` wrapper instance. 333 | * @example 334 | * 335 | * function square(n) { 336 | * return n * n; 337 | * } 338 | * 339 | * var wrapped = _([1, 2, 3]); 340 | * 341 | * // Returns an unwrapped value. 342 | * wrapped.reduce(_.add); 343 | * // => 6 344 | * 345 | * // Returns a wrapped value. 346 | * var squares = wrapped.map(square); 347 | * 348 | * _.isArray(squares); 349 | * // => false 350 | * 351 | * _.isArray(squares.value()); 352 | * // => true 353 | */ 354 | function lodash(value) { 355 | return value instanceof LodashWrapper 356 | ? value 357 | : new LodashWrapper(value); 358 | } 359 | 360 | /** 361 | * The base implementation of `_.create` without support for assigning 362 | * properties to the created object. 363 | * 364 | * @private 365 | * @param {Object} proto The object to inherit from. 366 | * @returns {Object} Returns the new object. 367 | */ 368 | var baseCreate = (function() { 369 | function object() {} 370 | return function(proto) { 371 | if (!isObject(proto)) { 372 | return {}; 373 | } 374 | if (objectCreate) { 375 | return objectCreate(proto); 376 | } 377 | object.prototype = proto; 378 | var result = new object; 379 | object.prototype = undefined; 380 | return result; 381 | }; 382 | }()); 383 | 384 | /** 385 | * The base constructor for creating `lodash` wrapper objects. 386 | * 387 | * @private 388 | * @param {*} value The value to wrap. 389 | * @param {boolean} [chainAll] Enable explicit method chain sequences. 390 | */ 391 | function LodashWrapper(value, chainAll) { 392 | this.__wrapped__ = value; 393 | this.__actions__ = []; 394 | this.__chain__ = !!chainAll; 395 | } 396 | 397 | LodashWrapper.prototype = baseCreate(lodash.prototype); 398 | LodashWrapper.prototype.constructor = LodashWrapper; 399 | 400 | /*------------------------------------------------------------------------*/ 401 | 402 | /** 403 | * Assigns `value` to `key` of `object` if the existing value is not equivalent 404 | * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 405 | * for equality comparisons. 406 | * 407 | * @private 408 | * @param {Object} object The object to modify. 409 | * @param {string} key The key of the property to assign. 410 | * @param {*} value The value to assign. 411 | */ 412 | function assignValue(object, key, value) { 413 | var objValue = object[key]; 414 | if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || 415 | (value === undefined && !(key in object))) { 416 | baseAssignValue(object, key, value); 417 | } 418 | } 419 | 420 | /** 421 | * The base implementation of `assignValue` and `assignMergeValue` without 422 | * value checks. 423 | * 424 | * @private 425 | * @param {Object} object The object to modify. 426 | * @param {string} key The key of the property to assign. 427 | * @param {*} value The value to assign. 428 | */ 429 | function baseAssignValue(object, key, value) { 430 | object[key] = value; 431 | } 432 | 433 | /** 434 | * The base implementation of `_.delay` and `_.defer` which accepts `args` 435 | * to provide to `func`. 436 | * 437 | * @private 438 | * @param {Function} func The function to delay. 439 | * @param {number} wait The number of milliseconds to delay invocation. 440 | * @param {Array} args The arguments to provide to `func`. 441 | * @returns {number|Object} Returns the timer id or timeout object. 442 | */ 443 | function baseDelay(func, wait, args) { 444 | if (typeof func != 'function') { 445 | throw new TypeError(FUNC_ERROR_TEXT); 446 | } 447 | return setTimeout(function() { func.apply(undefined, args); }, wait); 448 | } 449 | 450 | /** 451 | * The base implementation of `_.forEach` without support for iteratee shorthands. 452 | * 453 | * @private 454 | * @param {Array|Object} collection The collection to iterate over. 455 | * @param {Function} iteratee The function invoked per iteration. 456 | * @returns {Array|Object} Returns `collection`. 457 | */ 458 | var baseEach = createBaseEach(baseForOwn); 459 | 460 | /** 461 | * The base implementation of `_.every` without support for iteratee shorthands. 462 | * 463 | * @private 464 | * @param {Array|Object} collection The collection to iterate over. 465 | * @param {Function} predicate The function invoked per iteration. 466 | * @returns {boolean} Returns `true` if all elements pass the predicate check, 467 | * else `false` 468 | */ 469 | function baseEvery(collection, predicate) { 470 | var result = true; 471 | baseEach(collection, function(value, index, collection) { 472 | result = !!predicate(value, index, collection); 473 | return result; 474 | }); 475 | return result; 476 | } 477 | 478 | /** 479 | * The base implementation of methods like `_.max` and `_.min` which accepts a 480 | * `comparator` to determine the extremum value. 481 | * 482 | * @private 483 | * @param {Array} array The array to iterate over. 484 | * @param {Function} iteratee The iteratee invoked per iteration. 485 | * @param {Function} comparator The comparator used to compare values. 486 | * @returns {*} Returns the extremum value. 487 | */ 488 | function baseExtremum(array, iteratee, comparator) { 489 | var index = -1, 490 | length = array.length; 491 | 492 | while (++index < length) { 493 | var value = array[index], 494 | current = iteratee(value); 495 | 496 | if (current != null && (computed === undefined 497 | ? (current === current && !false) 498 | : comparator(current, computed) 499 | )) { 500 | var computed = current, 501 | result = value; 502 | } 503 | } 504 | return result; 505 | } 506 | 507 | /** 508 | * The base implementation of `_.filter` without support for iteratee shorthands. 509 | * 510 | * @private 511 | * @param {Array|Object} collection The collection to iterate over. 512 | * @param {Function} predicate The function invoked per iteration. 513 | * @returns {Array} Returns the new filtered array. 514 | */ 515 | function baseFilter(collection, predicate) { 516 | var result = []; 517 | baseEach(collection, function(value, index, collection) { 518 | if (predicate(value, index, collection)) { 519 | result.push(value); 520 | } 521 | }); 522 | return result; 523 | } 524 | 525 | /** 526 | * The base implementation of `_.flatten` with support for restricting flattening. 527 | * 528 | * @private 529 | * @param {Array} array The array to flatten. 530 | * @param {number} depth The maximum recursion depth. 531 | * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. 532 | * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. 533 | * @param {Array} [result=[]] The initial result value. 534 | * @returns {Array} Returns the new flattened array. 535 | */ 536 | function baseFlatten(array, depth, predicate, isStrict, result) { 537 | var index = -1, 538 | length = array.length; 539 | 540 | predicate || (predicate = isFlattenable); 541 | result || (result = []); 542 | 543 | while (++index < length) { 544 | var value = array[index]; 545 | if (depth > 0 && predicate(value)) { 546 | if (depth > 1) { 547 | // Recursively flatten arrays (susceptible to call stack limits). 548 | baseFlatten(value, depth - 1, predicate, isStrict, result); 549 | } else { 550 | arrayPush(result, value); 551 | } 552 | } else if (!isStrict) { 553 | result[result.length] = value; 554 | } 555 | } 556 | return result; 557 | } 558 | 559 | /** 560 | * The base implementation of `baseForOwn` which iterates over `object` 561 | * properties returned by `keysFunc` and invokes `iteratee` for each property. 562 | * Iteratee functions may exit iteration early by explicitly returning `false`. 563 | * 564 | * @private 565 | * @param {Object} object The object to iterate over. 566 | * @param {Function} iteratee The function invoked per iteration. 567 | * @param {Function} keysFunc The function to get the keys of `object`. 568 | * @returns {Object} Returns `object`. 569 | */ 570 | var baseFor = createBaseFor(); 571 | 572 | /** 573 | * The base implementation of `_.forOwn` without support for iteratee shorthands. 574 | * 575 | * @private 576 | * @param {Object} object The object to iterate over. 577 | * @param {Function} iteratee The function invoked per iteration. 578 | * @returns {Object} Returns `object`. 579 | */ 580 | function baseForOwn(object, iteratee) { 581 | return object && baseFor(object, iteratee, keys); 582 | } 583 | 584 | /** 585 | * The base implementation of `_.functions` which creates an array of 586 | * `object` function property names filtered from `props`. 587 | * 588 | * @private 589 | * @param {Object} object The object to inspect. 590 | * @param {Array} props The property names to filter. 591 | * @returns {Array} Returns the function names. 592 | */ 593 | function baseFunctions(object, props) { 594 | return baseFilter(props, function(key) { 595 | return isFunction(object[key]); 596 | }); 597 | } 598 | 599 | /** 600 | * The base implementation of `getTag` without fallbacks for buggy environments. 601 | * 602 | * @private 603 | * @param {*} value The value to query. 604 | * @returns {string} Returns the `toStringTag`. 605 | */ 606 | function baseGetTag(value) { 607 | return objectToString(value); 608 | } 609 | 610 | /** 611 | * The base implementation of `_.gt` which doesn't coerce arguments. 612 | * 613 | * @private 614 | * @param {*} value The value to compare. 615 | * @param {*} other The other value to compare. 616 | * @returns {boolean} Returns `true` if `value` is greater than `other`, 617 | * else `false`. 618 | */ 619 | function baseGt(value, other) { 620 | return value > other; 621 | } 622 | 623 | /** 624 | * The base implementation of `_.isArguments`. 625 | * 626 | * @private 627 | * @param {*} value The value to check. 628 | * @returns {boolean} Returns `true` if `value` is an `arguments` object, 629 | */ 630 | var baseIsArguments = noop; 631 | 632 | /** 633 | * The base implementation of `_.isDate` without Node.js optimizations. 634 | * 635 | * @private 636 | * @param {*} value The value to check. 637 | * @returns {boolean} Returns `true` if `value` is a date object, else `false`. 638 | */ 639 | function baseIsDate(value) { 640 | return isObjectLike(value) && baseGetTag(value) == dateTag; 641 | } 642 | 643 | /** 644 | * The base implementation of `_.isEqual` which supports partial comparisons 645 | * and tracks traversed objects. 646 | * 647 | * @private 648 | * @param {*} value The value to compare. 649 | * @param {*} other The other value to compare. 650 | * @param {boolean} bitmask The bitmask flags. 651 | * 1 - Unordered comparison 652 | * 2 - Partial comparison 653 | * @param {Function} [customizer] The function to customize comparisons. 654 | * @param {Object} [stack] Tracks traversed `value` and `other` objects. 655 | * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 656 | */ 657 | function baseIsEqual(value, other, bitmask, customizer, stack) { 658 | if (value === other) { 659 | return true; 660 | } 661 | if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { 662 | return value !== value && other !== other; 663 | } 664 | return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); 665 | } 666 | 667 | /** 668 | * A specialized version of `baseIsEqual` for arrays and objects which performs 669 | * deep comparisons and tracks traversed objects enabling objects with circular 670 | * references to be compared. 671 | * 672 | * @private 673 | * @param {Object} object The object to compare. 674 | * @param {Object} other The other object to compare. 675 | * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 676 | * @param {Function} customizer The function to customize comparisons. 677 | * @param {Function} equalFunc The function to determine equivalents of values. 678 | * @param {Object} [stack] Tracks traversed `object` and `other` objects. 679 | * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. 680 | */ 681 | function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { 682 | var objIsArr = isArray(object), 683 | othIsArr = isArray(other), 684 | objTag = objIsArr ? arrayTag : baseGetTag(object), 685 | othTag = othIsArr ? arrayTag : baseGetTag(other); 686 | 687 | objTag = objTag == argsTag ? objectTag : objTag; 688 | othTag = othTag == argsTag ? objectTag : othTag; 689 | 690 | var objIsObj = objTag == objectTag, 691 | othIsObj = othTag == objectTag, 692 | isSameTag = objTag == othTag; 693 | 694 | stack || (stack = []); 695 | var objStack = find(stack, function(entry) { 696 | return entry[0] == object; 697 | }); 698 | var othStack = find(stack, function(entry) { 699 | return entry[0] == other; 700 | }); 701 | if (objStack && othStack) { 702 | return objStack[1] == other; 703 | } 704 | stack.push([object, other]); 705 | stack.push([other, object]); 706 | if (isSameTag && !objIsObj) { 707 | var result = (objIsArr) 708 | ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) 709 | : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); 710 | stack.pop(); 711 | return result; 712 | } 713 | if (!(bitmask & COMPARE_PARTIAL_FLAG)) { 714 | var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), 715 | othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); 716 | 717 | if (objIsWrapped || othIsWrapped) { 718 | var objUnwrapped = objIsWrapped ? object.value() : object, 719 | othUnwrapped = othIsWrapped ? other.value() : other; 720 | 721 | var result = equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); 722 | stack.pop(); 723 | return result; 724 | } 725 | } 726 | if (!isSameTag) { 727 | return false; 728 | } 729 | var result = equalObjects(object, other, bitmask, customizer, equalFunc, stack); 730 | stack.pop(); 731 | return result; 732 | } 733 | 734 | /** 735 | * The base implementation of `_.isRegExp` without Node.js optimizations. 736 | * 737 | * @private 738 | * @param {*} value The value to check. 739 | * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. 740 | */ 741 | function baseIsRegExp(value) { 742 | return isObjectLike(value) && baseGetTag(value) == regexpTag; 743 | } 744 | 745 | /** 746 | * The base implementation of `_.iteratee`. 747 | * 748 | * @private 749 | * @param {*} [value=_.identity] The value to convert to an iteratee. 750 | * @returns {Function} Returns the iteratee. 751 | */ 752 | function baseIteratee(func) { 753 | if (typeof func == 'function') { 754 | return func; 755 | } 756 | if (func == null) { 757 | return identity; 758 | } 759 | return (typeof func == 'object' ? baseMatches : baseProperty)(func); 760 | } 761 | 762 | /** 763 | * The base implementation of `_.lt` which doesn't coerce arguments. 764 | * 765 | * @private 766 | * @param {*} value The value to compare. 767 | * @param {*} other The other value to compare. 768 | * @returns {boolean} Returns `true` if `value` is less than `other`, 769 | * else `false`. 770 | */ 771 | function baseLt(value, other) { 772 | return value < other; 773 | } 774 | 775 | /** 776 | * The base implementation of `_.map` without support for iteratee shorthands. 777 | * 778 | * @private 779 | * @param {Array|Object} collection The collection to iterate over. 780 | * @param {Function} iteratee The function invoked per iteration. 781 | * @returns {Array} Returns the new mapped array. 782 | */ 783 | function baseMap(collection, iteratee) { 784 | var index = -1, 785 | result = isArrayLike(collection) ? Array(collection.length) : []; 786 | 787 | baseEach(collection, function(value, key, collection) { 788 | result[++index] = iteratee(value, key, collection); 789 | }); 790 | return result; 791 | } 792 | 793 | /** 794 | * The base implementation of `_.matches` which doesn't clone `source`. 795 | * 796 | * @private 797 | * @param {Object} source The object of property values to match. 798 | * @returns {Function} Returns the new spec function. 799 | */ 800 | function baseMatches(source) { 801 | var props = nativeKeys(source); 802 | return function(object) { 803 | var length = props.length; 804 | if (object == null) { 805 | return !length; 806 | } 807 | object = Object(object); 808 | while (length--) { 809 | var key = props[length]; 810 | if (!(key in object && 811 | baseIsEqual(source[key], object[key], COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG) 812 | )) { 813 | return false; 814 | } 815 | } 816 | return true; 817 | }; 818 | } 819 | 820 | /** 821 | * The base implementation of `_.pick` without support for individual 822 | * property identifiers. 823 | * 824 | * @private 825 | * @param {Object} object The source object. 826 | * @param {string[]} paths The property paths to pick. 827 | * @returns {Object} Returns the new object. 828 | */ 829 | function basePick(object, props) { 830 | object = Object(object); 831 | return reduce(props, function(result, key) { 832 | if (key in object) { 833 | result[key] = object[key]; 834 | } 835 | return result; 836 | }, {}); 837 | } 838 | 839 | /** 840 | * The base implementation of `_.rest` which doesn't validate or coerce arguments. 841 | * 842 | * @private 843 | * @param {Function} func The function to apply a rest parameter to. 844 | * @param {number} [start=func.length-1] The start position of the rest parameter. 845 | * @returns {Function} Returns the new function. 846 | */ 847 | function baseRest(func, start) { 848 | return setToString(overRest(func, start, identity), func + ''); 849 | } 850 | 851 | /** 852 | * The base implementation of `_.slice` without an iteratee call guard. 853 | * 854 | * @private 855 | * @param {Array} array The array to slice. 856 | * @param {number} [start=0] The start position. 857 | * @param {number} [end=array.length] The end position. 858 | * @returns {Array} Returns the slice of `array`. 859 | */ 860 | function baseSlice(array, start, end) { 861 | var index = -1, 862 | length = array.length; 863 | 864 | if (start < 0) { 865 | start = -start > length ? 0 : (length + start); 866 | } 867 | end = end > length ? length : end; 868 | if (end < 0) { 869 | end += length; 870 | } 871 | length = start > end ? 0 : ((end - start) >>> 0); 872 | start >>>= 0; 873 | 874 | var result = Array(length); 875 | while (++index < length) { 876 | result[index] = array[index + start]; 877 | } 878 | return result; 879 | } 880 | 881 | /** 882 | * Copies the values of `source` to `array`. 883 | * 884 | * @private 885 | * @param {Array} source The array to copy values from. 886 | * @param {Array} [array=[]] The array to copy values to. 887 | * @returns {Array} Returns `array`. 888 | */ 889 | function copyArray(source) { 890 | return baseSlice(source, 0, source.length); 891 | } 892 | 893 | /** 894 | * The base implementation of `_.some` without support for iteratee shorthands. 895 | * 896 | * @private 897 | * @param {Array|Object} collection The collection to iterate over. 898 | * @param {Function} predicate The function invoked per iteration. 899 | * @returns {boolean} Returns `true` if any element passes the predicate check, 900 | * else `false`. 901 | */ 902 | function baseSome(collection, predicate) { 903 | var result; 904 | 905 | baseEach(collection, function(value, index, collection) { 906 | result = predicate(value, index, collection); 907 | return !result; 908 | }); 909 | return !!result; 910 | } 911 | 912 | /** 913 | * The base implementation of `wrapperValue` which returns the result of 914 | * performing a sequence of actions on the unwrapped `value`, where each 915 | * successive action is supplied the return value of the previous. 916 | * 917 | * @private 918 | * @param {*} value The unwrapped value. 919 | * @param {Array} actions Actions to perform to resolve the unwrapped value. 920 | * @returns {*} Returns the resolved value. 921 | */ 922 | function baseWrapperValue(value, actions) { 923 | var result = value; 924 | return reduce(actions, function(result, action) { 925 | return action.func.apply(action.thisArg, arrayPush([result], action.args)); 926 | }, result); 927 | } 928 | 929 | /** 930 | * Compares values to sort them in ascending order. 931 | * 932 | * @private 933 | * @param {*} value The value to compare. 934 | * @param {*} other The other value to compare. 935 | * @returns {number} Returns the sort order indicator for `value`. 936 | */ 937 | function compareAscending(value, other) { 938 | if (value !== other) { 939 | var valIsDefined = value !== undefined, 940 | valIsNull = value === null, 941 | valIsReflexive = value === value, 942 | valIsSymbol = false; 943 | 944 | var othIsDefined = other !== undefined, 945 | othIsNull = other === null, 946 | othIsReflexive = other === other, 947 | othIsSymbol = false; 948 | 949 | if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || 950 | (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || 951 | (valIsNull && othIsDefined && othIsReflexive) || 952 | (!valIsDefined && othIsReflexive) || 953 | !valIsReflexive) { 954 | return 1; 955 | } 956 | if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || 957 | (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || 958 | (othIsNull && valIsDefined && valIsReflexive) || 959 | (!othIsDefined && valIsReflexive) || 960 | !othIsReflexive) { 961 | return -1; 962 | } 963 | } 964 | return 0; 965 | } 966 | 967 | /** 968 | * Copies properties of `source` to `object`. 969 | * 970 | * @private 971 | * @param {Object} source The object to copy properties from. 972 | * @param {Array} props The property identifiers to copy. 973 | * @param {Object} [object={}] The object to copy properties to. 974 | * @param {Function} [customizer] The function to customize copied values. 975 | * @returns {Object} Returns `object`. 976 | */ 977 | function copyObject(source, props, object, customizer) { 978 | var isNew = !object; 979 | object || (object = {}); 980 | 981 | var index = -1, 982 | length = props.length; 983 | 984 | while (++index < length) { 985 | var key = props[index]; 986 | 987 | var newValue = customizer 988 | ? customizer(object[key], source[key], key, object, source) 989 | : undefined; 990 | 991 | if (newValue === undefined) { 992 | newValue = source[key]; 993 | } 994 | if (isNew) { 995 | baseAssignValue(object, key, newValue); 996 | } else { 997 | assignValue(object, key, newValue); 998 | } 999 | } 1000 | return object; 1001 | } 1002 | 1003 | /** 1004 | * Creates a function like `_.assign`. 1005 | * 1006 | * @private 1007 | * @param {Function} assigner The function to assign values. 1008 | * @returns {Function} Returns the new assigner function. 1009 | */ 1010 | function createAssigner(assigner) { 1011 | return baseRest(function(object, sources) { 1012 | var index = -1, 1013 | length = sources.length, 1014 | customizer = length > 1 ? sources[length - 1] : undefined; 1015 | 1016 | customizer = (assigner.length > 3 && typeof customizer == 'function') 1017 | ? (length--, customizer) 1018 | : undefined; 1019 | 1020 | object = Object(object); 1021 | while (++index < length) { 1022 | var source = sources[index]; 1023 | if (source) { 1024 | assigner(object, source, index, customizer); 1025 | } 1026 | } 1027 | return object; 1028 | }); 1029 | } 1030 | 1031 | /** 1032 | * Creates a `baseEach` or `baseEachRight` function. 1033 | * 1034 | * @private 1035 | * @param {Function} eachFunc The function to iterate over a collection. 1036 | * @param {boolean} [fromRight] Specify iterating from right to left. 1037 | * @returns {Function} Returns the new base function. 1038 | */ 1039 | function createBaseEach(eachFunc, fromRight) { 1040 | return function(collection, iteratee) { 1041 | if (collection == null) { 1042 | return collection; 1043 | } 1044 | if (!isArrayLike(collection)) { 1045 | return eachFunc(collection, iteratee); 1046 | } 1047 | var length = collection.length, 1048 | index = fromRight ? length : -1, 1049 | iterable = Object(collection); 1050 | 1051 | while ((fromRight ? index-- : ++index < length)) { 1052 | if (iteratee(iterable[index], index, iterable) === false) { 1053 | break; 1054 | } 1055 | } 1056 | return collection; 1057 | }; 1058 | } 1059 | 1060 | /** 1061 | * Creates a base function for methods like `_.forIn` and `_.forOwn`. 1062 | * 1063 | * @private 1064 | * @param {boolean} [fromRight] Specify iterating from right to left. 1065 | * @returns {Function} Returns the new base function. 1066 | */ 1067 | function createBaseFor(fromRight) { 1068 | return function(object, iteratee, keysFunc) { 1069 | var index = -1, 1070 | iterable = Object(object), 1071 | props = keysFunc(object), 1072 | length = props.length; 1073 | 1074 | while (length--) { 1075 | var key = props[fromRight ? length : ++index]; 1076 | if (iteratee(iterable[key], key, iterable) === false) { 1077 | break; 1078 | } 1079 | } 1080 | return object; 1081 | }; 1082 | } 1083 | 1084 | /** 1085 | * Creates a function that produces an instance of `Ctor` regardless of 1086 | * whether it was invoked as part of a `new` expression or by `call` or `apply`. 1087 | * 1088 | * @private 1089 | * @param {Function} Ctor The constructor to wrap. 1090 | * @returns {Function} Returns the new wrapped function. 1091 | */ 1092 | function createCtor(Ctor) { 1093 | return function() { 1094 | // Use a `switch` statement to work with class constructors. See 1095 | // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist 1096 | // for more details. 1097 | var args = arguments; 1098 | var thisBinding = baseCreate(Ctor.prototype), 1099 | result = Ctor.apply(thisBinding, args); 1100 | 1101 | // Mimic the constructor's `return` behavior. 1102 | // See https://es5.github.io/#x13.2.2 for more details. 1103 | return isObject(result) ? result : thisBinding; 1104 | }; 1105 | } 1106 | 1107 | /** 1108 | * Creates a `_.find` or `_.findLast` function. 1109 | * 1110 | * @private 1111 | * @param {Function} findIndexFunc The function to find the collection index. 1112 | * @returns {Function} Returns the new find function. 1113 | */ 1114 | function createFind(findIndexFunc) { 1115 | return function(collection, predicate, fromIndex) { 1116 | var iterable = Object(collection); 1117 | if (!isArrayLike(collection)) { 1118 | var iteratee = baseIteratee(predicate, 3); 1119 | collection = keys(collection); 1120 | predicate = function(key) { return iteratee(iterable[key], key, iterable); }; 1121 | } 1122 | var index = findIndexFunc(collection, predicate, fromIndex); 1123 | return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; 1124 | }; 1125 | } 1126 | 1127 | /** 1128 | * Creates a function that wraps `func` to invoke it with the `this` binding 1129 | * of `thisArg` and `partials` prepended to the arguments it receives. 1130 | * 1131 | * @private 1132 | * @param {Function} func The function to wrap. 1133 | * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 1134 | * @param {*} thisArg The `this` binding of `func`. 1135 | * @param {Array} partials The arguments to prepend to those provided to 1136 | * the new function. 1137 | * @returns {Function} Returns the new wrapped function. 1138 | */ 1139 | function createPartial(func, bitmask, thisArg, partials) { 1140 | if (typeof func != 'function') { 1141 | throw new TypeError(FUNC_ERROR_TEXT); 1142 | } 1143 | var isBind = bitmask & WRAP_BIND_FLAG, 1144 | Ctor = createCtor(func); 1145 | 1146 | function wrapper() { 1147 | var argsIndex = -1, 1148 | argsLength = arguments.length, 1149 | leftIndex = -1, 1150 | leftLength = partials.length, 1151 | args = Array(leftLength + argsLength), 1152 | fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; 1153 | 1154 | while (++leftIndex < leftLength) { 1155 | args[leftIndex] = partials[leftIndex]; 1156 | } 1157 | while (argsLength--) { 1158 | args[leftIndex++] = arguments[++argsIndex]; 1159 | } 1160 | return fn.apply(isBind ? thisArg : this, args); 1161 | } 1162 | return wrapper; 1163 | } 1164 | 1165 | /** 1166 | * A specialized version of `baseIsEqualDeep` for arrays with support for 1167 | * partial deep comparisons. 1168 | * 1169 | * @private 1170 | * @param {Array} array The array to compare. 1171 | * @param {Array} other The other array to compare. 1172 | * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 1173 | * @param {Function} customizer The function to customize comparisons. 1174 | * @param {Function} equalFunc The function to determine equivalents of values. 1175 | * @param {Object} stack Tracks traversed `array` and `other` objects. 1176 | * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. 1177 | */ 1178 | function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { 1179 | var isPartial = bitmask & COMPARE_PARTIAL_FLAG, 1180 | arrLength = array.length, 1181 | othLength = other.length; 1182 | 1183 | if (arrLength != othLength && !(isPartial && othLength > arrLength)) { 1184 | return false; 1185 | } 1186 | var index = -1, 1187 | result = true, 1188 | seen = (bitmask & COMPARE_UNORDERED_FLAG) ? [] : undefined; 1189 | 1190 | // Ignore non-index properties. 1191 | while (++index < arrLength) { 1192 | var arrValue = array[index], 1193 | othValue = other[index]; 1194 | 1195 | var compared; 1196 | if (compared !== undefined) { 1197 | if (compared) { 1198 | continue; 1199 | } 1200 | result = false; 1201 | break; 1202 | } 1203 | // Recursively compare arrays (susceptible to call stack limits). 1204 | if (seen) { 1205 | if (!baseSome(other, function(othValue, othIndex) { 1206 | if (!indexOf(seen, othIndex) && 1207 | (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { 1208 | return seen.push(othIndex); 1209 | } 1210 | })) { 1211 | result = false; 1212 | break; 1213 | } 1214 | } else if (!( 1215 | arrValue === othValue || 1216 | equalFunc(arrValue, othValue, bitmask, customizer, stack) 1217 | )) { 1218 | result = false; 1219 | break; 1220 | } 1221 | } 1222 | return result; 1223 | } 1224 | 1225 | /** 1226 | * A specialized version of `baseIsEqualDeep` for comparing objects of 1227 | * the same `toStringTag`. 1228 | * 1229 | * **Note:** This function only supports comparing values with tags of 1230 | * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. 1231 | * 1232 | * @private 1233 | * @param {Object} object The object to compare. 1234 | * @param {Object} other The other object to compare. 1235 | * @param {string} tag The `toStringTag` of the objects to compare. 1236 | * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 1237 | * @param {Function} customizer The function to customize comparisons. 1238 | * @param {Function} equalFunc The function to determine equivalents of values. 1239 | * @param {Object} stack Tracks traversed `object` and `other` objects. 1240 | * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. 1241 | */ 1242 | function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { 1243 | switch (tag) { 1244 | 1245 | case boolTag: 1246 | case dateTag: 1247 | case numberTag: 1248 | // Coerce booleans to `1` or `0` and dates to milliseconds. 1249 | // Invalid dates are coerced to `NaN`. 1250 | return eq(+object, +other); 1251 | 1252 | case errorTag: 1253 | return object.name == other.name && object.message == other.message; 1254 | 1255 | case regexpTag: 1256 | case stringTag: 1257 | // Coerce regexes to strings and treat strings, primitives and objects, 1258 | // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring 1259 | // for more details. 1260 | return object == (other + ''); 1261 | 1262 | } 1263 | return false; 1264 | } 1265 | 1266 | /** 1267 | * A specialized version of `baseIsEqualDeep` for objects with support for 1268 | * partial deep comparisons. 1269 | * 1270 | * @private 1271 | * @param {Object} object The object to compare. 1272 | * @param {Object} other The other object to compare. 1273 | * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 1274 | * @param {Function} customizer The function to customize comparisons. 1275 | * @param {Function} equalFunc The function to determine equivalents of values. 1276 | * @param {Object} stack Tracks traversed `object` and `other` objects. 1277 | * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. 1278 | */ 1279 | function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { 1280 | var isPartial = bitmask & COMPARE_PARTIAL_FLAG, 1281 | objProps = keys(object), 1282 | objLength = objProps.length, 1283 | othProps = keys(other), 1284 | othLength = othProps.length; 1285 | 1286 | if (objLength != othLength && !isPartial) { 1287 | return false; 1288 | } 1289 | var index = objLength; 1290 | while (index--) { 1291 | var key = objProps[index]; 1292 | if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { 1293 | return false; 1294 | } 1295 | } 1296 | var result = true; 1297 | 1298 | var skipCtor = isPartial; 1299 | while (++index < objLength) { 1300 | key = objProps[index]; 1301 | var objValue = object[key], 1302 | othValue = other[key]; 1303 | 1304 | var compared; 1305 | // Recursively compare objects (susceptible to call stack limits). 1306 | if (!(compared === undefined 1307 | ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) 1308 | : compared 1309 | )) { 1310 | result = false; 1311 | break; 1312 | } 1313 | skipCtor || (skipCtor = key == 'constructor'); 1314 | } 1315 | if (result && !skipCtor) { 1316 | var objCtor = object.constructor, 1317 | othCtor = other.constructor; 1318 | 1319 | // Non `Object` object instances with different constructors are not equal. 1320 | if (objCtor != othCtor && 1321 | ('constructor' in object && 'constructor' in other) && 1322 | !(typeof objCtor == 'function' && objCtor instanceof objCtor && 1323 | typeof othCtor == 'function' && othCtor instanceof othCtor)) { 1324 | result = false; 1325 | } 1326 | } 1327 | return result; 1328 | } 1329 | 1330 | /** 1331 | * A specialized version of `baseRest` which flattens the rest array. 1332 | * 1333 | * @private 1334 | * @param {Function} func The function to apply a rest parameter to. 1335 | * @returns {Function} Returns the new function. 1336 | */ 1337 | function flatRest(func) { 1338 | return setToString(overRest(func, undefined, flatten), func + ''); 1339 | } 1340 | 1341 | /** 1342 | * Checks if `value` is a flattenable `arguments` object or array. 1343 | * 1344 | * @private 1345 | * @param {*} value The value to check. 1346 | * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. 1347 | */ 1348 | function isFlattenable(value) { 1349 | return isArray(value) || isArguments(value); 1350 | } 1351 | 1352 | /** 1353 | * Checks if `value` is a valid array-like index. 1354 | * 1355 | * @private 1356 | * @param {*} value The value to check. 1357 | * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. 1358 | * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. 1359 | */ 1360 | function isIndex(value, length) { 1361 | var type = typeof value; 1362 | length = length == null ? MAX_SAFE_INTEGER : length; 1363 | 1364 | return !!length && 1365 | (type == 'number' || 1366 | (type != 'symbol' && reIsUint.test(value))) && 1367 | (value > -1 && value % 1 == 0 && value < length); 1368 | } 1369 | 1370 | /** 1371 | * Checks if the given arguments are from an iteratee call. 1372 | * 1373 | * @private 1374 | * @param {*} value The potential iteratee value argument. 1375 | * @param {*} index The potential iteratee index or key argument. 1376 | * @param {*} object The potential iteratee object argument. 1377 | * @returns {boolean} Returns `true` if the arguments are from an iteratee call, 1378 | * else `false`. 1379 | */ 1380 | function isIterateeCall(value, index, object) { 1381 | if (!isObject(object)) { 1382 | return false; 1383 | } 1384 | var type = typeof index; 1385 | if (type == 'number' 1386 | ? (isArrayLike(object) && isIndex(index, object.length)) 1387 | : (type == 'string' && index in object) 1388 | ) { 1389 | return eq(object[index], value); 1390 | } 1391 | return false; 1392 | } 1393 | 1394 | /** 1395 | * This function is like 1396 | * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) 1397 | * except that it includes inherited enumerable properties. 1398 | * 1399 | * @private 1400 | * @param {Object} object The object to query. 1401 | * @returns {Array} Returns the array of property names. 1402 | */ 1403 | function nativeKeysIn(object) { 1404 | var result = []; 1405 | if (object != null) { 1406 | for (var key in Object(object)) { 1407 | result.push(key); 1408 | } 1409 | } 1410 | return result; 1411 | } 1412 | 1413 | /** 1414 | * Converts `value` to a string using `Object.prototype.toString`. 1415 | * 1416 | * @private 1417 | * @param {*} value The value to convert. 1418 | * @returns {string} Returns the converted string. 1419 | */ 1420 | function objectToString(value) { 1421 | return nativeObjectToString.call(value); 1422 | } 1423 | 1424 | /** 1425 | * A specialized version of `baseRest` which transforms the rest array. 1426 | * 1427 | * @private 1428 | * @param {Function} func The function to apply a rest parameter to. 1429 | * @param {number} [start=func.length-1] The start position of the rest parameter. 1430 | * @param {Function} transform The rest array transform. 1431 | * @returns {Function} Returns the new function. 1432 | */ 1433 | function overRest(func, start, transform) { 1434 | start = nativeMax(start === undefined ? (func.length - 1) : start, 0); 1435 | return function() { 1436 | var args = arguments, 1437 | index = -1, 1438 | length = nativeMax(args.length - start, 0), 1439 | array = Array(length); 1440 | 1441 | while (++index < length) { 1442 | array[index] = args[start + index]; 1443 | } 1444 | index = -1; 1445 | var otherArgs = Array(start + 1); 1446 | while (++index < start) { 1447 | otherArgs[index] = args[index]; 1448 | } 1449 | otherArgs[start] = transform(array); 1450 | return func.apply(this, otherArgs); 1451 | }; 1452 | } 1453 | 1454 | /** 1455 | * Sets the `toString` method of `func` to return `string`. 1456 | * 1457 | * @private 1458 | * @param {Function} func The function to modify. 1459 | * @param {Function} string The `toString` result. 1460 | * @returns {Function} Returns `func`. 1461 | */ 1462 | var setToString = identity; 1463 | 1464 | /*------------------------------------------------------------------------*/ 1465 | 1466 | /** 1467 | * Creates an array with all falsey values removed. The values `false`, `null`, 1468 | * `0`, `""`, `undefined`, and `NaN` are falsey. 1469 | * 1470 | * @static 1471 | * @memberOf _ 1472 | * @since 0.1.0 1473 | * @category Array 1474 | * @param {Array} array The array to compact. 1475 | * @returns {Array} Returns the new array of filtered values. 1476 | * @example 1477 | * 1478 | * _.compact([0, 1, false, 2, '', 3]); 1479 | * // => [1, 2, 3] 1480 | */ 1481 | function compact(array) { 1482 | return baseFilter(array, Boolean); 1483 | } 1484 | 1485 | /** 1486 | * Creates a new array concatenating `array` with any additional arrays 1487 | * and/or values. 1488 | * 1489 | * @static 1490 | * @memberOf _ 1491 | * @since 4.0.0 1492 | * @category Array 1493 | * @param {Array} array The array to concatenate. 1494 | * @param {...*} [values] The values to concatenate. 1495 | * @returns {Array} Returns the new concatenated array. 1496 | * @example 1497 | * 1498 | * var array = [1]; 1499 | * var other = _.concat(array, 2, [3], [[4]]); 1500 | * 1501 | * console.log(other); 1502 | * // => [1, 2, 3, [4]] 1503 | * 1504 | * console.log(array); 1505 | * // => [1] 1506 | */ 1507 | function concat() { 1508 | var length = arguments.length; 1509 | if (!length) { 1510 | return []; 1511 | } 1512 | var args = Array(length - 1), 1513 | array = arguments[0], 1514 | index = length; 1515 | 1516 | while (index--) { 1517 | args[index - 1] = arguments[index]; 1518 | } 1519 | return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); 1520 | } 1521 | 1522 | /** 1523 | * This method is like `_.find` except that it returns the index of the first 1524 | * element `predicate` returns truthy for instead of the element itself. 1525 | * 1526 | * @static 1527 | * @memberOf _ 1528 | * @since 1.1.0 1529 | * @category Array 1530 | * @param {Array} array The array to inspect. 1531 | * @param {Function} [predicate=_.identity] The function invoked per iteration. 1532 | * @param {number} [fromIndex=0] The index to search from. 1533 | * @returns {number} Returns the index of the found element, else `-1`. 1534 | * @example 1535 | * 1536 | * var users = [ 1537 | * { 'user': 'barney', 'active': false }, 1538 | * { 'user': 'fred', 'active': false }, 1539 | * { 'user': 'pebbles', 'active': true } 1540 | * ]; 1541 | * 1542 | * _.findIndex(users, function(o) { return o.user == 'barney'; }); 1543 | * // => 0 1544 | * 1545 | * // The `_.matches` iteratee shorthand. 1546 | * _.findIndex(users, { 'user': 'fred', 'active': false }); 1547 | * // => 1 1548 | * 1549 | * // The `_.matchesProperty` iteratee shorthand. 1550 | * _.findIndex(users, ['active', false]); 1551 | * // => 0 1552 | * 1553 | * // The `_.property` iteratee shorthand. 1554 | * _.findIndex(users, 'active'); 1555 | * // => 2 1556 | */ 1557 | function findIndex(array, predicate, fromIndex) { 1558 | var length = array == null ? 0 : array.length; 1559 | if (!length) { 1560 | return -1; 1561 | } 1562 | var index = fromIndex == null ? 0 : toInteger(fromIndex); 1563 | if (index < 0) { 1564 | index = nativeMax(length + index, 0); 1565 | } 1566 | return baseFindIndex(array, baseIteratee(predicate, 3), index); 1567 | } 1568 | 1569 | /** 1570 | * Flattens `array` a single level deep. 1571 | * 1572 | * @static 1573 | * @memberOf _ 1574 | * @since 0.1.0 1575 | * @category Array 1576 | * @param {Array} array The array to flatten. 1577 | * @returns {Array} Returns the new flattened array. 1578 | * @example 1579 | * 1580 | * _.flatten([1, [2, [3, [4]], 5]]); 1581 | * // => [1, 2, [3, [4]], 5] 1582 | */ 1583 | function flatten(array) { 1584 | var length = array == null ? 0 : array.length; 1585 | return length ? baseFlatten(array, 1) : []; 1586 | } 1587 | 1588 | /** 1589 | * Recursively flattens `array`. 1590 | * 1591 | * @static 1592 | * @memberOf _ 1593 | * @since 3.0.0 1594 | * @category Array 1595 | * @param {Array} array The array to flatten. 1596 | * @returns {Array} Returns the new flattened array. 1597 | * @example 1598 | * 1599 | * _.flattenDeep([1, [2, [3, [4]], 5]]); 1600 | * // => [1, 2, 3, 4, 5] 1601 | */ 1602 | function flattenDeep(array) { 1603 | var length = array == null ? 0 : array.length; 1604 | return length ? baseFlatten(array, INFINITY) : []; 1605 | } 1606 | 1607 | /** 1608 | * Gets the first element of `array`. 1609 | * 1610 | * @static 1611 | * @memberOf _ 1612 | * @since 0.1.0 1613 | * @alias first 1614 | * @category Array 1615 | * @param {Array} array The array to query. 1616 | * @returns {*} Returns the first element of `array`. 1617 | * @example 1618 | * 1619 | * _.head([1, 2, 3]); 1620 | * // => 1 1621 | * 1622 | * _.head([]); 1623 | * // => undefined 1624 | */ 1625 | function head(array) { 1626 | return (array && array.length) ? array[0] : undefined; 1627 | } 1628 | 1629 | /** 1630 | * Gets the index at which the first occurrence of `value` is found in `array` 1631 | * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 1632 | * for equality comparisons. If `fromIndex` is negative, it's used as the 1633 | * offset from the end of `array`. 1634 | * 1635 | * @static 1636 | * @memberOf _ 1637 | * @since 0.1.0 1638 | * @category Array 1639 | * @param {Array} array The array to inspect. 1640 | * @param {*} value The value to search for. 1641 | * @param {number} [fromIndex=0] The index to search from. 1642 | * @returns {number} Returns the index of the matched value, else `-1`. 1643 | * @example 1644 | * 1645 | * _.indexOf([1, 2, 1, 2], 2); 1646 | * // => 1 1647 | * 1648 | * // Search from the `fromIndex`. 1649 | * _.indexOf([1, 2, 1, 2], 2, 2); 1650 | * // => 3 1651 | */ 1652 | function indexOf(array, value, fromIndex) { 1653 | var length = array == null ? 0 : array.length; 1654 | if (typeof fromIndex == 'number') { 1655 | fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; 1656 | } else { 1657 | fromIndex = 0; 1658 | } 1659 | var index = (fromIndex || 0) - 1, 1660 | isReflexive = value === value; 1661 | 1662 | while (++index < length) { 1663 | var other = array[index]; 1664 | if ((isReflexive ? other === value : other !== other)) { 1665 | return index; 1666 | } 1667 | } 1668 | return -1; 1669 | } 1670 | 1671 | /** 1672 | * Gets the last element of `array`. 1673 | * 1674 | * @static 1675 | * @memberOf _ 1676 | * @since 0.1.0 1677 | * @category Array 1678 | * @param {Array} array The array to query. 1679 | * @returns {*} Returns the last element of `array`. 1680 | * @example 1681 | * 1682 | * _.last([1, 2, 3]); 1683 | * // => 3 1684 | */ 1685 | function last(array) { 1686 | var length = array == null ? 0 : array.length; 1687 | return length ? array[length - 1] : undefined; 1688 | } 1689 | 1690 | /** 1691 | * Creates a slice of `array` from `start` up to, but not including, `end`. 1692 | * 1693 | * **Note:** This method is used instead of 1694 | * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are 1695 | * returned. 1696 | * 1697 | * @static 1698 | * @memberOf _ 1699 | * @since 3.0.0 1700 | * @category Array 1701 | * @param {Array} array The array to slice. 1702 | * @param {number} [start=0] The start position. 1703 | * @param {number} [end=array.length] The end position. 1704 | * @returns {Array} Returns the slice of `array`. 1705 | */ 1706 | function slice(array, start, end) { 1707 | var length = array == null ? 0 : array.length; 1708 | start = start == null ? 0 : +start; 1709 | end = end === undefined ? length : +end; 1710 | return length ? baseSlice(array, start, end) : []; 1711 | } 1712 | 1713 | /*------------------------------------------------------------------------*/ 1714 | 1715 | /** 1716 | * Creates a `lodash` wrapper instance that wraps `value` with explicit method 1717 | * chain sequences enabled. The result of such sequences must be unwrapped 1718 | * with `_#value`. 1719 | * 1720 | * @static 1721 | * @memberOf _ 1722 | * @since 1.3.0 1723 | * @category Seq 1724 | * @param {*} value The value to wrap. 1725 | * @returns {Object} Returns the new `lodash` wrapper instance. 1726 | * @example 1727 | * 1728 | * var users = [ 1729 | * { 'user': 'barney', 'age': 36 }, 1730 | * { 'user': 'fred', 'age': 40 }, 1731 | * { 'user': 'pebbles', 'age': 1 } 1732 | * ]; 1733 | * 1734 | * var youngest = _ 1735 | * .chain(users) 1736 | * .sortBy('age') 1737 | * .map(function(o) { 1738 | * return o.user + ' is ' + o.age; 1739 | * }) 1740 | * .head() 1741 | * .value(); 1742 | * // => 'pebbles is 1' 1743 | */ 1744 | function chain(value) { 1745 | var result = lodash(value); 1746 | result.__chain__ = true; 1747 | return result; 1748 | } 1749 | 1750 | /** 1751 | * This method invokes `interceptor` and returns `value`. The interceptor 1752 | * is invoked with one argument; (value). The purpose of this method is to 1753 | * "tap into" a method chain sequence in order to modify intermediate results. 1754 | * 1755 | * @static 1756 | * @memberOf _ 1757 | * @since 0.1.0 1758 | * @category Seq 1759 | * @param {*} value The value to provide to `interceptor`. 1760 | * @param {Function} interceptor The function to invoke. 1761 | * @returns {*} Returns `value`. 1762 | * @example 1763 | * 1764 | * _([1, 2, 3]) 1765 | * .tap(function(array) { 1766 | * // Mutate input array. 1767 | * array.pop(); 1768 | * }) 1769 | * .reverse() 1770 | * .value(); 1771 | * // => [2, 1] 1772 | */ 1773 | function tap(value, interceptor) { 1774 | interceptor(value); 1775 | return value; 1776 | } 1777 | 1778 | /** 1779 | * This method is like `_.tap` except that it returns the result of `interceptor`. 1780 | * The purpose of this method is to "pass thru" values replacing intermediate 1781 | * results in a method chain sequence. 1782 | * 1783 | * @static 1784 | * @memberOf _ 1785 | * @since 3.0.0 1786 | * @category Seq 1787 | * @param {*} value The value to provide to `interceptor`. 1788 | * @param {Function} interceptor The function to invoke. 1789 | * @returns {*} Returns the result of `interceptor`. 1790 | * @example 1791 | * 1792 | * _(' abc ') 1793 | * .chain() 1794 | * .trim() 1795 | * .thru(function(value) { 1796 | * return [value]; 1797 | * }) 1798 | * .value(); 1799 | * // => ['abc'] 1800 | */ 1801 | function thru(value, interceptor) { 1802 | return interceptor(value); 1803 | } 1804 | 1805 | /** 1806 | * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. 1807 | * 1808 | * @name chain 1809 | * @memberOf _ 1810 | * @since 0.1.0 1811 | * @category Seq 1812 | * @returns {Object} Returns the new `lodash` wrapper instance. 1813 | * @example 1814 | * 1815 | * var users = [ 1816 | * { 'user': 'barney', 'age': 36 }, 1817 | * { 'user': 'fred', 'age': 40 } 1818 | * ]; 1819 | * 1820 | * // A sequence without explicit chaining. 1821 | * _(users).head(); 1822 | * // => { 'user': 'barney', 'age': 36 } 1823 | * 1824 | * // A sequence with explicit chaining. 1825 | * _(users) 1826 | * .chain() 1827 | * .head() 1828 | * .pick('user') 1829 | * .value(); 1830 | * // => { 'user': 'barney' } 1831 | */ 1832 | function wrapperChain() { 1833 | return chain(this); 1834 | } 1835 | 1836 | /** 1837 | * Executes the chain sequence to resolve the unwrapped value. 1838 | * 1839 | * @name value 1840 | * @memberOf _ 1841 | * @since 0.1.0 1842 | * @alias toJSON, valueOf 1843 | * @category Seq 1844 | * @returns {*} Returns the resolved unwrapped value. 1845 | * @example 1846 | * 1847 | * _([1, 2, 3]).value(); 1848 | * // => [1, 2, 3] 1849 | */ 1850 | function wrapperValue() { 1851 | return baseWrapperValue(this.__wrapped__, this.__actions__); 1852 | } 1853 | 1854 | /*------------------------------------------------------------------------*/ 1855 | 1856 | /** 1857 | * Checks if `predicate` returns truthy for **all** elements of `collection`. 1858 | * Iteration is stopped once `predicate` returns falsey. The predicate is 1859 | * invoked with three arguments: (value, index|key, collection). 1860 | * 1861 | * **Note:** This method returns `true` for 1862 | * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because 1863 | * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of 1864 | * elements of empty collections. 1865 | * 1866 | * @static 1867 | * @memberOf _ 1868 | * @since 0.1.0 1869 | * @category Collection 1870 | * @param {Array|Object} collection The collection to iterate over. 1871 | * @param {Function} [predicate=_.identity] The function invoked per iteration. 1872 | * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 1873 | * @returns {boolean} Returns `true` if all elements pass the predicate check, 1874 | * else `false`. 1875 | * @example 1876 | * 1877 | * _.every([true, 1, null, 'yes'], Boolean); 1878 | * // => false 1879 | * 1880 | * var users = [ 1881 | * { 'user': 'barney', 'age': 36, 'active': false }, 1882 | * { 'user': 'fred', 'age': 40, 'active': false } 1883 | * ]; 1884 | * 1885 | * // The `_.matches` iteratee shorthand. 1886 | * _.every(users, { 'user': 'barney', 'active': false }); 1887 | * // => false 1888 | * 1889 | * // The `_.matchesProperty` iteratee shorthand. 1890 | * _.every(users, ['active', false]); 1891 | * // => true 1892 | * 1893 | * // The `_.property` iteratee shorthand. 1894 | * _.every(users, 'active'); 1895 | * // => false 1896 | */ 1897 | function every(collection, predicate, guard) { 1898 | predicate = guard ? undefined : predicate; 1899 | return baseEvery(collection, baseIteratee(predicate)); 1900 | } 1901 | 1902 | /** 1903 | * Iterates over elements of `collection`, returning an array of all elements 1904 | * `predicate` returns truthy for. The predicate is invoked with three 1905 | * arguments: (value, index|key, collection). 1906 | * 1907 | * **Note:** Unlike `_.remove`, this method returns a new array. 1908 | * 1909 | * @static 1910 | * @memberOf _ 1911 | * @since 0.1.0 1912 | * @category Collection 1913 | * @param {Array|Object} collection The collection to iterate over. 1914 | * @param {Function} [predicate=_.identity] The function invoked per iteration. 1915 | * @returns {Array} Returns the new filtered array. 1916 | * @see _.reject 1917 | * @example 1918 | * 1919 | * var users = [ 1920 | * { 'user': 'barney', 'age': 36, 'active': true }, 1921 | * { 'user': 'fred', 'age': 40, 'active': false } 1922 | * ]; 1923 | * 1924 | * _.filter(users, function(o) { return !o.active; }); 1925 | * // => objects for ['fred'] 1926 | * 1927 | * // The `_.matches` iteratee shorthand. 1928 | * _.filter(users, { 'age': 36, 'active': true }); 1929 | * // => objects for ['barney'] 1930 | * 1931 | * // The `_.matchesProperty` iteratee shorthand. 1932 | * _.filter(users, ['active', false]); 1933 | * // => objects for ['fred'] 1934 | * 1935 | * // The `_.property` iteratee shorthand. 1936 | * _.filter(users, 'active'); 1937 | * // => objects for ['barney'] 1938 | */ 1939 | function filter(collection, predicate) { 1940 | return baseFilter(collection, baseIteratee(predicate)); 1941 | } 1942 | 1943 | /** 1944 | * Iterates over elements of `collection`, returning the first element 1945 | * `predicate` returns truthy for. The predicate is invoked with three 1946 | * arguments: (value, index|key, collection). 1947 | * 1948 | * @static 1949 | * @memberOf _ 1950 | * @since 0.1.0 1951 | * @category Collection 1952 | * @param {Array|Object} collection The collection to inspect. 1953 | * @param {Function} [predicate=_.identity] The function invoked per iteration. 1954 | * @param {number} [fromIndex=0] The index to search from. 1955 | * @returns {*} Returns the matched element, else `undefined`. 1956 | * @example 1957 | * 1958 | * var users = [ 1959 | * { 'user': 'barney', 'age': 36, 'active': true }, 1960 | * { 'user': 'fred', 'age': 40, 'active': false }, 1961 | * { 'user': 'pebbles', 'age': 1, 'active': true } 1962 | * ]; 1963 | * 1964 | * _.find(users, function(o) { return o.age < 40; }); 1965 | * // => object for 'barney' 1966 | * 1967 | * // The `_.matches` iteratee shorthand. 1968 | * _.find(users, { 'age': 1, 'active': true }); 1969 | * // => object for 'pebbles' 1970 | * 1971 | * // The `_.matchesProperty` iteratee shorthand. 1972 | * _.find(users, ['active', false]); 1973 | * // => object for 'fred' 1974 | * 1975 | * // The `_.property` iteratee shorthand. 1976 | * _.find(users, 'active'); 1977 | * // => object for 'barney' 1978 | */ 1979 | var find = createFind(findIndex); 1980 | 1981 | /** 1982 | * Iterates over elements of `collection` and invokes `iteratee` for each element. 1983 | * The iteratee is invoked with three arguments: (value, index|key, collection). 1984 | * Iteratee functions may exit iteration early by explicitly returning `false`. 1985 | * 1986 | * **Note:** As with other "Collections" methods, objects with a "length" 1987 | * property are iterated like arrays. To avoid this behavior use `_.forIn` 1988 | * or `_.forOwn` for object iteration. 1989 | * 1990 | * @static 1991 | * @memberOf _ 1992 | * @since 0.1.0 1993 | * @alias each 1994 | * @category Collection 1995 | * @param {Array|Object} collection The collection to iterate over. 1996 | * @param {Function} [iteratee=_.identity] The function invoked per iteration. 1997 | * @returns {Array|Object} Returns `collection`. 1998 | * @see _.forEachRight 1999 | * @example 2000 | * 2001 | * _.forEach([1, 2], function(value) { 2002 | * console.log(value); 2003 | * }); 2004 | * // => Logs `1` then `2`. 2005 | * 2006 | * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { 2007 | * console.log(key); 2008 | * }); 2009 | * // => Logs 'a' then 'b' (iteration order is not guaranteed). 2010 | */ 2011 | function forEach(collection, iteratee) { 2012 | return baseEach(collection, baseIteratee(iteratee)); 2013 | } 2014 | 2015 | /** 2016 | * Creates an array of values by running each element in `collection` thru 2017 | * `iteratee`. The iteratee is invoked with three arguments: 2018 | * (value, index|key, collection). 2019 | * 2020 | * Many lodash methods are guarded to work as iteratees for methods like 2021 | * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. 2022 | * 2023 | * The guarded methods are: 2024 | * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, 2025 | * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, 2026 | * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, 2027 | * `template`, `trim`, `trimEnd`, `trimStart`, and `words` 2028 | * 2029 | * @static 2030 | * @memberOf _ 2031 | * @since 0.1.0 2032 | * @category Collection 2033 | * @param {Array|Object} collection The collection to iterate over. 2034 | * @param {Function} [iteratee=_.identity] The function invoked per iteration. 2035 | * @returns {Array} Returns the new mapped array. 2036 | * @example 2037 | * 2038 | * function square(n) { 2039 | * return n * n; 2040 | * } 2041 | * 2042 | * _.map([4, 8], square); 2043 | * // => [16, 64] 2044 | * 2045 | * _.map({ 'a': 4, 'b': 8 }, square); 2046 | * // => [16, 64] (iteration order is not guaranteed) 2047 | * 2048 | * var users = [ 2049 | * { 'user': 'barney' }, 2050 | * { 'user': 'fred' } 2051 | * ]; 2052 | * 2053 | * // The `_.property` iteratee shorthand. 2054 | * _.map(users, 'user'); 2055 | * // => ['barney', 'fred'] 2056 | */ 2057 | function map(collection, iteratee) { 2058 | return baseMap(collection, baseIteratee(iteratee)); 2059 | } 2060 | 2061 | /** 2062 | * Reduces `collection` to a value which is the accumulated result of running 2063 | * each element in `collection` thru `iteratee`, where each successive 2064 | * invocation is supplied the return value of the previous. If `accumulator` 2065 | * is not given, the first element of `collection` is used as the initial 2066 | * value. The iteratee is invoked with four arguments: 2067 | * (accumulator, value, index|key, collection). 2068 | * 2069 | * Many lodash methods are guarded to work as iteratees for methods like 2070 | * `_.reduce`, `_.reduceRight`, and `_.transform`. 2071 | * 2072 | * The guarded methods are: 2073 | * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, 2074 | * and `sortBy` 2075 | * 2076 | * @static 2077 | * @memberOf _ 2078 | * @since 0.1.0 2079 | * @category Collection 2080 | * @param {Array|Object} collection The collection to iterate over. 2081 | * @param {Function} [iteratee=_.identity] The function invoked per iteration. 2082 | * @param {*} [accumulator] The initial value. 2083 | * @returns {*} Returns the accumulated value. 2084 | * @see _.reduceRight 2085 | * @example 2086 | * 2087 | * _.reduce([1, 2], function(sum, n) { 2088 | * return sum + n; 2089 | * }, 0); 2090 | * // => 3 2091 | * 2092 | * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { 2093 | * (result[value] || (result[value] = [])).push(key); 2094 | * return result; 2095 | * }, {}); 2096 | * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) 2097 | */ 2098 | function reduce(collection, iteratee, accumulator) { 2099 | return baseReduce(collection, baseIteratee(iteratee), accumulator, arguments.length < 3, baseEach); 2100 | } 2101 | 2102 | /** 2103 | * Gets the size of `collection` by returning its length for array-like 2104 | * values or the number of own enumerable string keyed properties for objects. 2105 | * 2106 | * @static 2107 | * @memberOf _ 2108 | * @since 0.1.0 2109 | * @category Collection 2110 | * @param {Array|Object|string} collection The collection to inspect. 2111 | * @returns {number} Returns the collection size. 2112 | * @example 2113 | * 2114 | * _.size([1, 2, 3]); 2115 | * // => 3 2116 | * 2117 | * _.size({ 'a': 1, 'b': 2 }); 2118 | * // => 2 2119 | * 2120 | * _.size('pebbles'); 2121 | * // => 7 2122 | */ 2123 | function size(collection) { 2124 | if (collection == null) { 2125 | return 0; 2126 | } 2127 | collection = isArrayLike(collection) ? collection : nativeKeys(collection); 2128 | return collection.length; 2129 | } 2130 | 2131 | /** 2132 | * Checks if `predicate` returns truthy for **any** element of `collection`. 2133 | * Iteration is stopped once `predicate` returns truthy. The predicate is 2134 | * invoked with three arguments: (value, index|key, collection). 2135 | * 2136 | * @static 2137 | * @memberOf _ 2138 | * @since 0.1.0 2139 | * @category Collection 2140 | * @param {Array|Object} collection The collection to iterate over. 2141 | * @param {Function} [predicate=_.identity] The function invoked per iteration. 2142 | * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 2143 | * @returns {boolean} Returns `true` if any element passes the predicate check, 2144 | * else `false`. 2145 | * @example 2146 | * 2147 | * _.some([null, 0, 'yes', false], Boolean); 2148 | * // => true 2149 | * 2150 | * var users = [ 2151 | * { 'user': 'barney', 'active': true }, 2152 | * { 'user': 'fred', 'active': false } 2153 | * ]; 2154 | * 2155 | * // The `_.matches` iteratee shorthand. 2156 | * _.some(users, { 'user': 'barney', 'active': false }); 2157 | * // => false 2158 | * 2159 | * // The `_.matchesProperty` iteratee shorthand. 2160 | * _.some(users, ['active', false]); 2161 | * // => true 2162 | * 2163 | * // The `_.property` iteratee shorthand. 2164 | * _.some(users, 'active'); 2165 | * // => true 2166 | */ 2167 | function some(collection, predicate, guard) { 2168 | predicate = guard ? undefined : predicate; 2169 | return baseSome(collection, baseIteratee(predicate)); 2170 | } 2171 | 2172 | /** 2173 | * Creates an array of elements, sorted in ascending order by the results of 2174 | * running each element in a collection thru each iteratee. This method 2175 | * performs a stable sort, that is, it preserves the original sort order of 2176 | * equal elements. The iteratees are invoked with one argument: (value). 2177 | * 2178 | * @static 2179 | * @memberOf _ 2180 | * @since 0.1.0 2181 | * @category Collection 2182 | * @param {Array|Object} collection The collection to iterate over. 2183 | * @param {...(Function|Function[])} [iteratees=[_.identity]] 2184 | * The iteratees to sort by. 2185 | * @returns {Array} Returns the new sorted array. 2186 | * @example 2187 | * 2188 | * var users = [ 2189 | * { 'user': 'fred', 'age': 48 }, 2190 | * { 'user': 'barney', 'age': 36 }, 2191 | * { 'user': 'fred', 'age': 40 }, 2192 | * { 'user': 'barney', 'age': 34 } 2193 | * ]; 2194 | * 2195 | * _.sortBy(users, [function(o) { return o.user; }]); 2196 | * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] 2197 | * 2198 | * _.sortBy(users, ['user', 'age']); 2199 | * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] 2200 | */ 2201 | function sortBy(collection, iteratee) { 2202 | var index = 0; 2203 | iteratee = baseIteratee(iteratee); 2204 | 2205 | return baseMap(baseMap(collection, function(value, key, collection) { 2206 | return { 'value': value, 'index': index++, 'criteria': iteratee(value, key, collection) }; 2207 | }).sort(function(object, other) { 2208 | return compareAscending(object.criteria, other.criteria) || (object.index - other.index); 2209 | }), baseProperty('value')); 2210 | } 2211 | 2212 | /*------------------------------------------------------------------------*/ 2213 | 2214 | /** 2215 | * Creates a function that invokes `func`, with the `this` binding and arguments 2216 | * of the created function, while it's called less than `n` times. Subsequent 2217 | * calls to the created function return the result of the last `func` invocation. 2218 | * 2219 | * @static 2220 | * @memberOf _ 2221 | * @since 3.0.0 2222 | * @category Function 2223 | * @param {number} n The number of calls at which `func` is no longer invoked. 2224 | * @param {Function} func The function to restrict. 2225 | * @returns {Function} Returns the new restricted function. 2226 | * @example 2227 | * 2228 | * jQuery(element).on('click', _.before(5, addContactToList)); 2229 | * // => Allows adding up to 4 contacts to the list. 2230 | */ 2231 | function before(n, func) { 2232 | var result; 2233 | if (typeof func != 'function') { 2234 | throw new TypeError(FUNC_ERROR_TEXT); 2235 | } 2236 | n = toInteger(n); 2237 | return function() { 2238 | if (--n > 0) { 2239 | result = func.apply(this, arguments); 2240 | } 2241 | if (n <= 1) { 2242 | func = undefined; 2243 | } 2244 | return result; 2245 | }; 2246 | } 2247 | 2248 | /** 2249 | * Creates a function that invokes `func` with the `this` binding of `thisArg` 2250 | * and `partials` prepended to the arguments it receives. 2251 | * 2252 | * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, 2253 | * may be used as a placeholder for partially applied arguments. 2254 | * 2255 | * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" 2256 | * property of bound functions. 2257 | * 2258 | * @static 2259 | * @memberOf _ 2260 | * @since 0.1.0 2261 | * @category Function 2262 | * @param {Function} func The function to bind. 2263 | * @param {*} thisArg The `this` binding of `func`. 2264 | * @param {...*} [partials] The arguments to be partially applied. 2265 | * @returns {Function} Returns the new bound function. 2266 | * @example 2267 | * 2268 | * function greet(greeting, punctuation) { 2269 | * return greeting + ' ' + this.user + punctuation; 2270 | * } 2271 | * 2272 | * var object = { 'user': 'fred' }; 2273 | * 2274 | * var bound = _.bind(greet, object, 'hi'); 2275 | * bound('!'); 2276 | * // => 'hi fred!' 2277 | * 2278 | * // Bound with placeholders. 2279 | * var bound = _.bind(greet, object, _, '!'); 2280 | * bound('hi'); 2281 | * // => 'hi fred!' 2282 | */ 2283 | var bind = baseRest(function(func, thisArg, partials) { 2284 | return createPartial(func, WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG, thisArg, partials); 2285 | }); 2286 | 2287 | /** 2288 | * Defers invoking the `func` until the current call stack has cleared. Any 2289 | * additional arguments are provided to `func` when it's invoked. 2290 | * 2291 | * @static 2292 | * @memberOf _ 2293 | * @since 0.1.0 2294 | * @category Function 2295 | * @param {Function} func The function to defer. 2296 | * @param {...*} [args] The arguments to invoke `func` with. 2297 | * @returns {number} Returns the timer id. 2298 | * @example 2299 | * 2300 | * _.defer(function(text) { 2301 | * console.log(text); 2302 | * }, 'deferred'); 2303 | * // => Logs 'deferred' after one millisecond. 2304 | */ 2305 | var defer = baseRest(function(func, args) { 2306 | return baseDelay(func, 1, args); 2307 | }); 2308 | 2309 | /** 2310 | * Invokes `func` after `wait` milliseconds. Any additional arguments are 2311 | * provided to `func` when it's invoked. 2312 | * 2313 | * @static 2314 | * @memberOf _ 2315 | * @since 0.1.0 2316 | * @category Function 2317 | * @param {Function} func The function to delay. 2318 | * @param {number} wait The number of milliseconds to delay invocation. 2319 | * @param {...*} [args] The arguments to invoke `func` with. 2320 | * @returns {number} Returns the timer id. 2321 | * @example 2322 | * 2323 | * _.delay(function(text) { 2324 | * console.log(text); 2325 | * }, 1000, 'later'); 2326 | * // => Logs 'later' after one second. 2327 | */ 2328 | var delay = baseRest(function(func, wait, args) { 2329 | return baseDelay(func, toNumber(wait) || 0, args); 2330 | }); 2331 | 2332 | /** 2333 | * Creates a function that negates the result of the predicate `func`. The 2334 | * `func` predicate is invoked with the `this` binding and arguments of the 2335 | * created function. 2336 | * 2337 | * @static 2338 | * @memberOf _ 2339 | * @since 3.0.0 2340 | * @category Function 2341 | * @param {Function} predicate The predicate to negate. 2342 | * @returns {Function} Returns the new negated function. 2343 | * @example 2344 | * 2345 | * function isEven(n) { 2346 | * return n % 2 == 0; 2347 | * } 2348 | * 2349 | * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); 2350 | * // => [1, 3, 5] 2351 | */ 2352 | function negate(predicate) { 2353 | if (typeof predicate != 'function') { 2354 | throw new TypeError(FUNC_ERROR_TEXT); 2355 | } 2356 | return function() { 2357 | var args = arguments; 2358 | return !predicate.apply(this, args); 2359 | }; 2360 | } 2361 | 2362 | /** 2363 | * Creates a function that is restricted to invoking `func` once. Repeat calls 2364 | * to the function return the value of the first invocation. The `func` is 2365 | * invoked with the `this` binding and arguments of the created function. 2366 | * 2367 | * @static 2368 | * @memberOf _ 2369 | * @since 0.1.0 2370 | * @category Function 2371 | * @param {Function} func The function to restrict. 2372 | * @returns {Function} Returns the new restricted function. 2373 | * @example 2374 | * 2375 | * var initialize = _.once(createApplication); 2376 | * initialize(); 2377 | * initialize(); 2378 | * // => `createApplication` is invoked once 2379 | */ 2380 | function once(func) { 2381 | return before(2, func); 2382 | } 2383 | 2384 | /*------------------------------------------------------------------------*/ 2385 | 2386 | /** 2387 | * Creates a shallow clone of `value`. 2388 | * 2389 | * **Note:** This method is loosely based on the 2390 | * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) 2391 | * and supports cloning arrays, array buffers, booleans, date objects, maps, 2392 | * numbers, `Object` objects, regexes, sets, strings, symbols, and typed 2393 | * arrays. The own enumerable properties of `arguments` objects are cloned 2394 | * as plain objects. An empty object is returned for uncloneable values such 2395 | * as error objects, functions, DOM nodes, and WeakMaps. 2396 | * 2397 | * @static 2398 | * @memberOf _ 2399 | * @since 0.1.0 2400 | * @category Lang 2401 | * @param {*} value The value to clone. 2402 | * @returns {*} Returns the cloned value. 2403 | * @see _.cloneDeep 2404 | * @example 2405 | * 2406 | * var objects = [{ 'a': 1 }, { 'b': 2 }]; 2407 | * 2408 | * var shallow = _.clone(objects); 2409 | * console.log(shallow[0] === objects[0]); 2410 | * // => true 2411 | */ 2412 | function clone(value) { 2413 | if (!isObject(value)) { 2414 | return value; 2415 | } 2416 | return isArray(value) ? copyArray(value) : copyObject(value, nativeKeys(value)); 2417 | } 2418 | 2419 | /** 2420 | * Performs a 2421 | * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 2422 | * comparison between two values to determine if they are equivalent. 2423 | * 2424 | * @static 2425 | * @memberOf _ 2426 | * @since 4.0.0 2427 | * @category Lang 2428 | * @param {*} value The value to compare. 2429 | * @param {*} other The other value to compare. 2430 | * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 2431 | * @example 2432 | * 2433 | * var object = { 'a': 1 }; 2434 | * var other = { 'a': 1 }; 2435 | * 2436 | * _.eq(object, object); 2437 | * // => true 2438 | * 2439 | * _.eq(object, other); 2440 | * // => false 2441 | * 2442 | * _.eq('a', 'a'); 2443 | * // => true 2444 | * 2445 | * _.eq('a', Object('a')); 2446 | * // => false 2447 | * 2448 | * _.eq(NaN, NaN); 2449 | * // => true 2450 | */ 2451 | function eq(value, other) { 2452 | return value === other || (value !== value && other !== other); 2453 | } 2454 | 2455 | /** 2456 | * Checks if `value` is likely an `arguments` object. 2457 | * 2458 | * @static 2459 | * @memberOf _ 2460 | * @since 0.1.0 2461 | * @category Lang 2462 | * @param {*} value The value to check. 2463 | * @returns {boolean} Returns `true` if `value` is an `arguments` object, 2464 | * else `false`. 2465 | * @example 2466 | * 2467 | * _.isArguments(function() { return arguments; }()); 2468 | * // => true 2469 | * 2470 | * _.isArguments([1, 2, 3]); 2471 | * // => false 2472 | */ 2473 | var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { 2474 | return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && 2475 | !propertyIsEnumerable.call(value, 'callee'); 2476 | }; 2477 | 2478 | /** 2479 | * Checks if `value` is classified as an `Array` object. 2480 | * 2481 | * @static 2482 | * @memberOf _ 2483 | * @since 0.1.0 2484 | * @category Lang 2485 | * @param {*} value The value to check. 2486 | * @returns {boolean} Returns `true` if `value` is an array, else `false`. 2487 | * @example 2488 | * 2489 | * _.isArray([1, 2, 3]); 2490 | * // => true 2491 | * 2492 | * _.isArray(document.body.children); 2493 | * // => false 2494 | * 2495 | * _.isArray('abc'); 2496 | * // => false 2497 | * 2498 | * _.isArray(_.noop); 2499 | * // => false 2500 | */ 2501 | var isArray = Array.isArray; 2502 | 2503 | /** 2504 | * Checks if `value` is array-like. A value is considered array-like if it's 2505 | * not a function and has a `value.length` that's an integer greater than or 2506 | * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. 2507 | * 2508 | * @static 2509 | * @memberOf _ 2510 | * @since 4.0.0 2511 | * @category Lang 2512 | * @param {*} value The value to check. 2513 | * @returns {boolean} Returns `true` if `value` is array-like, else `false`. 2514 | * @example 2515 | * 2516 | * _.isArrayLike([1, 2, 3]); 2517 | * // => true 2518 | * 2519 | * _.isArrayLike(document.body.children); 2520 | * // => true 2521 | * 2522 | * _.isArrayLike('abc'); 2523 | * // => true 2524 | * 2525 | * _.isArrayLike(_.noop); 2526 | * // => false 2527 | */ 2528 | function isArrayLike(value) { 2529 | return value != null && isLength(value.length) && !isFunction(value); 2530 | } 2531 | 2532 | /** 2533 | * Checks if `value` is classified as a boolean primitive or object. 2534 | * 2535 | * @static 2536 | * @memberOf _ 2537 | * @since 0.1.0 2538 | * @category Lang 2539 | * @param {*} value The value to check. 2540 | * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. 2541 | * @example 2542 | * 2543 | * _.isBoolean(false); 2544 | * // => true 2545 | * 2546 | * _.isBoolean(null); 2547 | * // => false 2548 | */ 2549 | function isBoolean(value) { 2550 | return value === true || value === false || 2551 | (isObjectLike(value) && baseGetTag(value) == boolTag); 2552 | } 2553 | 2554 | /** 2555 | * Checks if `value` is classified as a `Date` object. 2556 | * 2557 | * @static 2558 | * @memberOf _ 2559 | * @since 0.1.0 2560 | * @category Lang 2561 | * @param {*} value The value to check. 2562 | * @returns {boolean} Returns `true` if `value` is a date object, else `false`. 2563 | * @example 2564 | * 2565 | * _.isDate(new Date); 2566 | * // => true 2567 | * 2568 | * _.isDate('Mon April 23 2012'); 2569 | * // => false 2570 | */ 2571 | var isDate = baseIsDate; 2572 | 2573 | /** 2574 | * Checks if `value` is an empty object, collection, map, or set. 2575 | * 2576 | * Objects are considered empty if they have no own enumerable string keyed 2577 | * properties. 2578 | * 2579 | * Array-like values such as `arguments` objects, arrays, buffers, strings, or 2580 | * jQuery-like collections are considered empty if they have a `length` of `0`. 2581 | * Similarly, maps and sets are considered empty if they have a `size` of `0`. 2582 | * 2583 | * @static 2584 | * @memberOf _ 2585 | * @since 0.1.0 2586 | * @category Lang 2587 | * @param {*} value The value to check. 2588 | * @returns {boolean} Returns `true` if `value` is empty, else `false`. 2589 | * @example 2590 | * 2591 | * _.isEmpty(null); 2592 | * // => true 2593 | * 2594 | * _.isEmpty(true); 2595 | * // => true 2596 | * 2597 | * _.isEmpty(1); 2598 | * // => true 2599 | * 2600 | * _.isEmpty([1, 2, 3]); 2601 | * // => false 2602 | * 2603 | * _.isEmpty({ 'a': 1 }); 2604 | * // => false 2605 | */ 2606 | function isEmpty(value) { 2607 | if (isArrayLike(value) && 2608 | (isArray(value) || isString(value) || 2609 | isFunction(value.splice) || isArguments(value))) { 2610 | return !value.length; 2611 | } 2612 | return !nativeKeys(value).length; 2613 | } 2614 | 2615 | /** 2616 | * Performs a deep comparison between two values to determine if they are 2617 | * equivalent. 2618 | * 2619 | * **Note:** This method supports comparing arrays, array buffers, booleans, 2620 | * date objects, error objects, maps, numbers, `Object` objects, regexes, 2621 | * sets, strings, symbols, and typed arrays. `Object` objects are compared 2622 | * by their own, not inherited, enumerable properties. Functions and DOM 2623 | * nodes are compared by strict equality, i.e. `===`. 2624 | * 2625 | * @static 2626 | * @memberOf _ 2627 | * @since 0.1.0 2628 | * @category Lang 2629 | * @param {*} value The value to compare. 2630 | * @param {*} other The other value to compare. 2631 | * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 2632 | * @example 2633 | * 2634 | * var object = { 'a': 1 }; 2635 | * var other = { 'a': 1 }; 2636 | * 2637 | * _.isEqual(object, other); 2638 | * // => true 2639 | * 2640 | * object === other; 2641 | * // => false 2642 | */ 2643 | function isEqual(value, other) { 2644 | return baseIsEqual(value, other); 2645 | } 2646 | 2647 | /** 2648 | * Checks if `value` is a finite primitive number. 2649 | * 2650 | * **Note:** This method is based on 2651 | * [`Number.isFinite`](https://mdn.io/Number/isFinite). 2652 | * 2653 | * @static 2654 | * @memberOf _ 2655 | * @since 0.1.0 2656 | * @category Lang 2657 | * @param {*} value The value to check. 2658 | * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. 2659 | * @example 2660 | * 2661 | * _.isFinite(3); 2662 | * // => true 2663 | * 2664 | * _.isFinite(Number.MIN_VALUE); 2665 | * // => true 2666 | * 2667 | * _.isFinite(Infinity); 2668 | * // => false 2669 | * 2670 | * _.isFinite('3'); 2671 | * // => false 2672 | */ 2673 | function isFinite(value) { 2674 | return typeof value == 'number' && nativeIsFinite(value); 2675 | } 2676 | 2677 | /** 2678 | * Checks if `value` is classified as a `Function` object. 2679 | * 2680 | * @static 2681 | * @memberOf _ 2682 | * @since 0.1.0 2683 | * @category Lang 2684 | * @param {*} value The value to check. 2685 | * @returns {boolean} Returns `true` if `value` is a function, else `false`. 2686 | * @example 2687 | * 2688 | * _.isFunction(_); 2689 | * // => true 2690 | * 2691 | * _.isFunction(/abc/); 2692 | * // => false 2693 | */ 2694 | function isFunction(value) { 2695 | if (!isObject(value)) { 2696 | return false; 2697 | } 2698 | // The use of `Object#toString` avoids issues with the `typeof` operator 2699 | // in Safari 9 which returns 'object' for typed arrays and other constructors. 2700 | var tag = baseGetTag(value); 2701 | return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; 2702 | } 2703 | 2704 | /** 2705 | * Checks if `value` is a valid array-like length. 2706 | * 2707 | * **Note:** This method is loosely based on 2708 | * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). 2709 | * 2710 | * @static 2711 | * @memberOf _ 2712 | * @since 4.0.0 2713 | * @category Lang 2714 | * @param {*} value The value to check. 2715 | * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. 2716 | * @example 2717 | * 2718 | * _.isLength(3); 2719 | * // => true 2720 | * 2721 | * _.isLength(Number.MIN_VALUE); 2722 | * // => false 2723 | * 2724 | * _.isLength(Infinity); 2725 | * // => false 2726 | * 2727 | * _.isLength('3'); 2728 | * // => false 2729 | */ 2730 | function isLength(value) { 2731 | return typeof value == 'number' && 2732 | value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; 2733 | } 2734 | 2735 | /** 2736 | * Checks if `value` is the 2737 | * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) 2738 | * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) 2739 | * 2740 | * @static 2741 | * @memberOf _ 2742 | * @since 0.1.0 2743 | * @category Lang 2744 | * @param {*} value The value to check. 2745 | * @returns {boolean} Returns `true` if `value` is an object, else `false`. 2746 | * @example 2747 | * 2748 | * _.isObject({}); 2749 | * // => true 2750 | * 2751 | * _.isObject([1, 2, 3]); 2752 | * // => true 2753 | * 2754 | * _.isObject(_.noop); 2755 | * // => true 2756 | * 2757 | * _.isObject(null); 2758 | * // => false 2759 | */ 2760 | function isObject(value) { 2761 | var type = typeof value; 2762 | return value != null && (type == 'object' || type == 'function'); 2763 | } 2764 | 2765 | /** 2766 | * Checks if `value` is object-like. A value is object-like if it's not `null` 2767 | * and has a `typeof` result of "object". 2768 | * 2769 | * @static 2770 | * @memberOf _ 2771 | * @since 4.0.0 2772 | * @category Lang 2773 | * @param {*} value The value to check. 2774 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 2775 | * @example 2776 | * 2777 | * _.isObjectLike({}); 2778 | * // => true 2779 | * 2780 | * _.isObjectLike([1, 2, 3]); 2781 | * // => true 2782 | * 2783 | * _.isObjectLike(_.noop); 2784 | * // => false 2785 | * 2786 | * _.isObjectLike(null); 2787 | * // => false 2788 | */ 2789 | function isObjectLike(value) { 2790 | return value != null && typeof value == 'object'; 2791 | } 2792 | 2793 | /** 2794 | * Checks if `value` is `NaN`. 2795 | * 2796 | * **Note:** This method is based on 2797 | * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as 2798 | * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for 2799 | * `undefined` and other non-number values. 2800 | * 2801 | * @static 2802 | * @memberOf _ 2803 | * @since 0.1.0 2804 | * @category Lang 2805 | * @param {*} value The value to check. 2806 | * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. 2807 | * @example 2808 | * 2809 | * _.isNaN(NaN); 2810 | * // => true 2811 | * 2812 | * _.isNaN(new Number(NaN)); 2813 | * // => true 2814 | * 2815 | * isNaN(undefined); 2816 | * // => true 2817 | * 2818 | * _.isNaN(undefined); 2819 | * // => false 2820 | */ 2821 | function isNaN(value) { 2822 | // An `NaN` primitive is the only value that is not equal to itself. 2823 | // Perform the `toStringTag` check first to avoid errors with some 2824 | // ActiveX objects in IE. 2825 | return isNumber(value) && value != +value; 2826 | } 2827 | 2828 | /** 2829 | * Checks if `value` is `null`. 2830 | * 2831 | * @static 2832 | * @memberOf _ 2833 | * @since 0.1.0 2834 | * @category Lang 2835 | * @param {*} value The value to check. 2836 | * @returns {boolean} Returns `true` if `value` is `null`, else `false`. 2837 | * @example 2838 | * 2839 | * _.isNull(null); 2840 | * // => true 2841 | * 2842 | * _.isNull(void 0); 2843 | * // => false 2844 | */ 2845 | function isNull(value) { 2846 | return value === null; 2847 | } 2848 | 2849 | /** 2850 | * Checks if `value` is classified as a `Number` primitive or object. 2851 | * 2852 | * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are 2853 | * classified as numbers, use the `_.isFinite` method. 2854 | * 2855 | * @static 2856 | * @memberOf _ 2857 | * @since 0.1.0 2858 | * @category Lang 2859 | * @param {*} value The value to check. 2860 | * @returns {boolean} Returns `true` if `value` is a number, else `false`. 2861 | * @example 2862 | * 2863 | * _.isNumber(3); 2864 | * // => true 2865 | * 2866 | * _.isNumber(Number.MIN_VALUE); 2867 | * // => true 2868 | * 2869 | * _.isNumber(Infinity); 2870 | * // => true 2871 | * 2872 | * _.isNumber('3'); 2873 | * // => false 2874 | */ 2875 | function isNumber(value) { 2876 | return typeof value == 'number' || 2877 | (isObjectLike(value) && baseGetTag(value) == numberTag); 2878 | } 2879 | 2880 | /** 2881 | * Checks if `value` is classified as a `RegExp` object. 2882 | * 2883 | * @static 2884 | * @memberOf _ 2885 | * @since 0.1.0 2886 | * @category Lang 2887 | * @param {*} value The value to check. 2888 | * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. 2889 | * @example 2890 | * 2891 | * _.isRegExp(/abc/); 2892 | * // => true 2893 | * 2894 | * _.isRegExp('/abc/'); 2895 | * // => false 2896 | */ 2897 | var isRegExp = baseIsRegExp; 2898 | 2899 | /** 2900 | * Checks if `value` is classified as a `String` primitive or object. 2901 | * 2902 | * @static 2903 | * @since 0.1.0 2904 | * @memberOf _ 2905 | * @category Lang 2906 | * @param {*} value The value to check. 2907 | * @returns {boolean} Returns `true` if `value` is a string, else `false`. 2908 | * @example 2909 | * 2910 | * _.isString('abc'); 2911 | * // => true 2912 | * 2913 | * _.isString(1); 2914 | * // => false 2915 | */ 2916 | function isString(value) { 2917 | return typeof value == 'string' || 2918 | (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); 2919 | } 2920 | 2921 | /** 2922 | * Checks if `value` is `undefined`. 2923 | * 2924 | * @static 2925 | * @since 0.1.0 2926 | * @memberOf _ 2927 | * @category Lang 2928 | * @param {*} value The value to check. 2929 | * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. 2930 | * @example 2931 | * 2932 | * _.isUndefined(void 0); 2933 | * // => true 2934 | * 2935 | * _.isUndefined(null); 2936 | * // => false 2937 | */ 2938 | function isUndefined(value) { 2939 | return value === undefined; 2940 | } 2941 | 2942 | /** 2943 | * Converts `value` to an array. 2944 | * 2945 | * @static 2946 | * @since 0.1.0 2947 | * @memberOf _ 2948 | * @category Lang 2949 | * @param {*} value The value to convert. 2950 | * @returns {Array} Returns the converted array. 2951 | * @example 2952 | * 2953 | * _.toArray({ 'a': 1, 'b': 2 }); 2954 | * // => [1, 2] 2955 | * 2956 | * _.toArray('abc'); 2957 | * // => ['a', 'b', 'c'] 2958 | * 2959 | * _.toArray(1); 2960 | * // => [] 2961 | * 2962 | * _.toArray(null); 2963 | * // => [] 2964 | */ 2965 | function toArray(value) { 2966 | if (!isArrayLike(value)) { 2967 | return values(value); 2968 | } 2969 | return value.length ? copyArray(value) : []; 2970 | } 2971 | 2972 | /** 2973 | * Converts `value` to an integer. 2974 | * 2975 | * **Note:** This method is loosely based on 2976 | * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). 2977 | * 2978 | * @static 2979 | * @memberOf _ 2980 | * @since 4.0.0 2981 | * @category Lang 2982 | * @param {*} value The value to convert. 2983 | * @returns {number} Returns the converted integer. 2984 | * @example 2985 | * 2986 | * _.toInteger(3.2); 2987 | * // => 3 2988 | * 2989 | * _.toInteger(Number.MIN_VALUE); 2990 | * // => 0 2991 | * 2992 | * _.toInteger(Infinity); 2993 | * // => 1.7976931348623157e+308 2994 | * 2995 | * _.toInteger('3.2'); 2996 | * // => 3 2997 | */ 2998 | var toInteger = Number; 2999 | 3000 | /** 3001 | * Converts `value` to a number. 3002 | * 3003 | * @static 3004 | * @memberOf _ 3005 | * @since 4.0.0 3006 | * @category Lang 3007 | * @param {*} value The value to process. 3008 | * @returns {number} Returns the number. 3009 | * @example 3010 | * 3011 | * _.toNumber(3.2); 3012 | * // => 3.2 3013 | * 3014 | * _.toNumber(Number.MIN_VALUE); 3015 | * // => 5e-324 3016 | * 3017 | * _.toNumber(Infinity); 3018 | * // => Infinity 3019 | * 3020 | * _.toNumber('3.2'); 3021 | * // => 3.2 3022 | */ 3023 | var toNumber = Number; 3024 | 3025 | /** 3026 | * Converts `value` to a string. An empty string is returned for `null` 3027 | * and `undefined` values. The sign of `-0` is preserved. 3028 | * 3029 | * @static 3030 | * @memberOf _ 3031 | * @since 4.0.0 3032 | * @category Lang 3033 | * @param {*} value The value to convert. 3034 | * @returns {string} Returns the converted string. 3035 | * @example 3036 | * 3037 | * _.toString(null); 3038 | * // => '' 3039 | * 3040 | * _.toString(-0); 3041 | * // => '-0' 3042 | * 3043 | * _.toString([1, 2, 3]); 3044 | * // => '1,2,3' 3045 | */ 3046 | function toString(value) { 3047 | if (typeof value == 'string') { 3048 | return value; 3049 | } 3050 | return value == null ? '' : (value + ''); 3051 | } 3052 | 3053 | /*------------------------------------------------------------------------*/ 3054 | 3055 | /** 3056 | * Assigns own enumerable string keyed properties of source objects to the 3057 | * destination object. Source objects are applied from left to right. 3058 | * Subsequent sources overwrite property assignments of previous sources. 3059 | * 3060 | * **Note:** This method mutates `object` and is loosely based on 3061 | * [`Object.assign`](https://mdn.io/Object/assign). 3062 | * 3063 | * @static 3064 | * @memberOf _ 3065 | * @since 0.10.0 3066 | * @category Object 3067 | * @param {Object} object The destination object. 3068 | * @param {...Object} [sources] The source objects. 3069 | * @returns {Object} Returns `object`. 3070 | * @see _.assignIn 3071 | * @example 3072 | * 3073 | * function Foo() { 3074 | * this.a = 1; 3075 | * } 3076 | * 3077 | * function Bar() { 3078 | * this.c = 3; 3079 | * } 3080 | * 3081 | * Foo.prototype.b = 2; 3082 | * Bar.prototype.d = 4; 3083 | * 3084 | * _.assign({ 'a': 0 }, new Foo, new Bar); 3085 | * // => { 'a': 1, 'c': 3 } 3086 | */ 3087 | var assign = createAssigner(function(object, source) { 3088 | copyObject(source, nativeKeys(source), object); 3089 | }); 3090 | 3091 | /** 3092 | * This method is like `_.assign` except that it iterates over own and 3093 | * inherited source properties. 3094 | * 3095 | * **Note:** This method mutates `object`. 3096 | * 3097 | * @static 3098 | * @memberOf _ 3099 | * @since 4.0.0 3100 | * @alias extend 3101 | * @category Object 3102 | * @param {Object} object The destination object. 3103 | * @param {...Object} [sources] The source objects. 3104 | * @returns {Object} Returns `object`. 3105 | * @see _.assign 3106 | * @example 3107 | * 3108 | * function Foo() { 3109 | * this.a = 1; 3110 | * } 3111 | * 3112 | * function Bar() { 3113 | * this.c = 3; 3114 | * } 3115 | * 3116 | * Foo.prototype.b = 2; 3117 | * Bar.prototype.d = 4; 3118 | * 3119 | * _.assignIn({ 'a': 0 }, new Foo, new Bar); 3120 | * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } 3121 | */ 3122 | var assignIn = createAssigner(function(object, source) { 3123 | copyObject(source, nativeKeysIn(source), object); 3124 | }); 3125 | 3126 | /** 3127 | * Creates an object that inherits from the `prototype` object. If a 3128 | * `properties` object is given, its own enumerable string keyed properties 3129 | * are assigned to the created object. 3130 | * 3131 | * @static 3132 | * @memberOf _ 3133 | * @since 2.3.0 3134 | * @category Object 3135 | * @param {Object} prototype The object to inherit from. 3136 | * @param {Object} [properties] The properties to assign to the object. 3137 | * @returns {Object} Returns the new object. 3138 | * @example 3139 | * 3140 | * function Shape() { 3141 | * this.x = 0; 3142 | * this.y = 0; 3143 | * } 3144 | * 3145 | * function Circle() { 3146 | * Shape.call(this); 3147 | * } 3148 | * 3149 | * Circle.prototype = _.create(Shape.prototype, { 3150 | * 'constructor': Circle 3151 | * }); 3152 | * 3153 | * var circle = new Circle; 3154 | * circle instanceof Circle; 3155 | * // => true 3156 | * 3157 | * circle instanceof Shape; 3158 | * // => true 3159 | */ 3160 | function create(prototype, properties) { 3161 | var result = baseCreate(prototype); 3162 | return properties == null ? result : assign(result, properties); 3163 | } 3164 | 3165 | /** 3166 | * Assigns own and inherited enumerable string keyed properties of source 3167 | * objects to the destination object for all destination properties that 3168 | * resolve to `undefined`. Source objects are applied from left to right. 3169 | * Once a property is set, additional values of the same property are ignored. 3170 | * 3171 | * **Note:** This method mutates `object`. 3172 | * 3173 | * @static 3174 | * @since 0.1.0 3175 | * @memberOf _ 3176 | * @category Object 3177 | * @param {Object} object The destination object. 3178 | * @param {...Object} [sources] The source objects. 3179 | * @returns {Object} Returns `object`. 3180 | * @see _.defaultsDeep 3181 | * @example 3182 | * 3183 | * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); 3184 | * // => { 'a': 1, 'b': 2 } 3185 | */ 3186 | var defaults = baseRest(function(object, sources) { 3187 | object = Object(object); 3188 | 3189 | var index = -1; 3190 | var length = sources.length; 3191 | var guard = length > 2 ? sources[2] : undefined; 3192 | 3193 | if (guard && isIterateeCall(sources[0], sources[1], guard)) { 3194 | length = 1; 3195 | } 3196 | 3197 | while (++index < length) { 3198 | var source = sources[index]; 3199 | var props = keysIn(source); 3200 | var propsIndex = -1; 3201 | var propsLength = props.length; 3202 | 3203 | while (++propsIndex < propsLength) { 3204 | var key = props[propsIndex]; 3205 | var value = object[key]; 3206 | 3207 | if (value === undefined || 3208 | (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { 3209 | object[key] = source[key]; 3210 | } 3211 | } 3212 | } 3213 | 3214 | return object; 3215 | }); 3216 | 3217 | /** 3218 | * Checks if `path` is a direct property of `object`. 3219 | * 3220 | * @static 3221 | * @since 0.1.0 3222 | * @memberOf _ 3223 | * @category Object 3224 | * @param {Object} object The object to query. 3225 | * @param {Array|string} path The path to check. 3226 | * @returns {boolean} Returns `true` if `path` exists, else `false`. 3227 | * @example 3228 | * 3229 | * var object = { 'a': { 'b': 2 } }; 3230 | * var other = _.create({ 'a': _.create({ 'b': 2 }) }); 3231 | * 3232 | * _.has(object, 'a'); 3233 | * // => true 3234 | * 3235 | * _.has(object, 'a.b'); 3236 | * // => true 3237 | * 3238 | * _.has(object, ['a', 'b']); 3239 | * // => true 3240 | * 3241 | * _.has(other, 'a'); 3242 | * // => false 3243 | */ 3244 | function has(object, path) { 3245 | return object != null && hasOwnProperty.call(object, path); 3246 | } 3247 | 3248 | /** 3249 | * Creates an array of the own enumerable property names of `object`. 3250 | * 3251 | * **Note:** Non-object values are coerced to objects. See the 3252 | * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) 3253 | * for more details. 3254 | * 3255 | * @static 3256 | * @since 0.1.0 3257 | * @memberOf _ 3258 | * @category Object 3259 | * @param {Object} object The object to query. 3260 | * @returns {Array} Returns the array of property names. 3261 | * @example 3262 | * 3263 | * function Foo() { 3264 | * this.a = 1; 3265 | * this.b = 2; 3266 | * } 3267 | * 3268 | * Foo.prototype.c = 3; 3269 | * 3270 | * _.keys(new Foo); 3271 | * // => ['a', 'b'] (iteration order is not guaranteed) 3272 | * 3273 | * _.keys('hi'); 3274 | * // => ['0', '1'] 3275 | */ 3276 | var keys = nativeKeys; 3277 | 3278 | /** 3279 | * Creates an array of the own and inherited enumerable property names of `object`. 3280 | * 3281 | * **Note:** Non-object values are coerced to objects. 3282 | * 3283 | * @static 3284 | * @memberOf _ 3285 | * @since 3.0.0 3286 | * @category Object 3287 | * @param {Object} object The object to query. 3288 | * @returns {Array} Returns the array of property names. 3289 | * @example 3290 | * 3291 | * function Foo() { 3292 | * this.a = 1; 3293 | * this.b = 2; 3294 | * } 3295 | * 3296 | * Foo.prototype.c = 3; 3297 | * 3298 | * _.keysIn(new Foo); 3299 | * // => ['a', 'b', 'c'] (iteration order is not guaranteed) 3300 | */ 3301 | var keysIn = nativeKeysIn; 3302 | 3303 | /** 3304 | * Creates an object composed of the picked `object` properties. 3305 | * 3306 | * @static 3307 | * @since 0.1.0 3308 | * @memberOf _ 3309 | * @category Object 3310 | * @param {Object} object The source object. 3311 | * @param {...(string|string[])} [paths] The property paths to pick. 3312 | * @returns {Object} Returns the new object. 3313 | * @example 3314 | * 3315 | * var object = { 'a': 1, 'b': '2', 'c': 3 }; 3316 | * 3317 | * _.pick(object, ['a', 'c']); 3318 | * // => { 'a': 1, 'c': 3 } 3319 | */ 3320 | var pick = flatRest(function(object, paths) { 3321 | return object == null ? {} : basePick(object, paths); 3322 | }); 3323 | 3324 | /** 3325 | * This method is like `_.get` except that if the resolved value is a 3326 | * function it's invoked with the `this` binding of its parent object and 3327 | * its result is returned. 3328 | * 3329 | * @static 3330 | * @since 0.1.0 3331 | * @memberOf _ 3332 | * @category Object 3333 | * @param {Object} object The object to query. 3334 | * @param {Array|string} path The path of the property to resolve. 3335 | * @param {*} [defaultValue] The value returned for `undefined` resolved values. 3336 | * @returns {*} Returns the resolved value. 3337 | * @example 3338 | * 3339 | * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; 3340 | * 3341 | * _.result(object, 'a[0].b.c1'); 3342 | * // => 3 3343 | * 3344 | * _.result(object, 'a[0].b.c2'); 3345 | * // => 4 3346 | * 3347 | * _.result(object, 'a[0].b.c3', 'default'); 3348 | * // => 'default' 3349 | * 3350 | * _.result(object, 'a[0].b.c3', _.constant('default')); 3351 | * // => 'default' 3352 | */ 3353 | function result(object, path, defaultValue) { 3354 | var value = object == null ? undefined : object[path]; 3355 | if (value === undefined) { 3356 | value = defaultValue; 3357 | } 3358 | return isFunction(value) ? value.call(object) : value; 3359 | } 3360 | 3361 | /** 3362 | * Creates an array of the own enumerable string keyed property values of `object`. 3363 | * 3364 | * **Note:** Non-object values are coerced to objects. 3365 | * 3366 | * @static 3367 | * @since 0.1.0 3368 | * @memberOf _ 3369 | * @category Object 3370 | * @param {Object} object The object to query. 3371 | * @returns {Array} Returns the array of property values. 3372 | * @example 3373 | * 3374 | * function Foo() { 3375 | * this.a = 1; 3376 | * this.b = 2; 3377 | * } 3378 | * 3379 | * Foo.prototype.c = 3; 3380 | * 3381 | * _.values(new Foo); 3382 | * // => [1, 2] (iteration order is not guaranteed) 3383 | * 3384 | * _.values('hi'); 3385 | * // => ['h', 'i'] 3386 | */ 3387 | function values(object) { 3388 | return object == null ? [] : baseValues(object, keys(object)); 3389 | } 3390 | 3391 | /*------------------------------------------------------------------------*/ 3392 | 3393 | /** 3394 | * Converts the characters "&", "<", ">", '"', and "'" in `string` to their 3395 | * corresponding HTML entities. 3396 | * 3397 | * **Note:** No other characters are escaped. To escape additional 3398 | * characters use a third-party library like [_he_](https://mths.be/he). 3399 | * 3400 | * Though the ">" character is escaped for symmetry, characters like 3401 | * ">" and "/" don't need escaping in HTML and have no special meaning 3402 | * unless they're part of a tag or unquoted attribute value. See 3403 | * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) 3404 | * (under "semi-related fun fact") for more details. 3405 | * 3406 | * When working with HTML you should always 3407 | * [quote attribute values](http://wonko.com/post/html-escaping) to reduce 3408 | * XSS vectors. 3409 | * 3410 | * @static 3411 | * @since 0.1.0 3412 | * @memberOf _ 3413 | * @category String 3414 | * @param {string} [string=''] The string to escape. 3415 | * @returns {string} Returns the escaped string. 3416 | * @example 3417 | * 3418 | * _.escape('fred, barney, & pebbles'); 3419 | * // => 'fred, barney, & pebbles' 3420 | */ 3421 | function escape(string) { 3422 | string = toString(string); 3423 | return (string && reHasUnescapedHtml.test(string)) 3424 | ? string.replace(reUnescapedHtml, escapeHtmlChar) 3425 | : string; 3426 | } 3427 | 3428 | /*------------------------------------------------------------------------*/ 3429 | 3430 | /** 3431 | * This method returns the first argument it receives. 3432 | * 3433 | * @static 3434 | * @since 0.1.0 3435 | * @memberOf _ 3436 | * @category Util 3437 | * @param {*} value Any value. 3438 | * @returns {*} Returns `value`. 3439 | * @example 3440 | * 3441 | * var object = { 'a': 1 }; 3442 | * 3443 | * console.log(_.identity(object) === object); 3444 | * // => true 3445 | */ 3446 | function identity(value) { 3447 | return value; 3448 | } 3449 | 3450 | /** 3451 | * Creates a function that invokes `func` with the arguments of the created 3452 | * function. If `func` is a property name, the created function returns the 3453 | * property value for a given element. If `func` is an array or object, the 3454 | * created function returns `true` for elements that contain the equivalent 3455 | * source properties, otherwise it returns `false`. 3456 | * 3457 | * @static 3458 | * @since 4.0.0 3459 | * @memberOf _ 3460 | * @category Util 3461 | * @param {*} [func=_.identity] The value to convert to a callback. 3462 | * @returns {Function} Returns the callback. 3463 | * @example 3464 | * 3465 | * var users = [ 3466 | * { 'user': 'barney', 'age': 36, 'active': true }, 3467 | * { 'user': 'fred', 'age': 40, 'active': false } 3468 | * ]; 3469 | * 3470 | * // The `_.matches` iteratee shorthand. 3471 | * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); 3472 | * // => [{ 'user': 'barney', 'age': 36, 'active': true }] 3473 | * 3474 | * // The `_.matchesProperty` iteratee shorthand. 3475 | * _.filter(users, _.iteratee(['user', 'fred'])); 3476 | * // => [{ 'user': 'fred', 'age': 40 }] 3477 | * 3478 | * // The `_.property` iteratee shorthand. 3479 | * _.map(users, _.iteratee('user')); 3480 | * // => ['barney', 'fred'] 3481 | * 3482 | * // Create custom iteratee shorthands. 3483 | * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { 3484 | * return !_.isRegExp(func) ? iteratee(func) : function(string) { 3485 | * return func.test(string); 3486 | * }; 3487 | * }); 3488 | * 3489 | * _.filter(['abc', 'def'], /ef/); 3490 | * // => ['def'] 3491 | */ 3492 | var iteratee = baseIteratee; 3493 | 3494 | /** 3495 | * Creates a function that performs a partial deep comparison between a given 3496 | * object and `source`, returning `true` if the given object has equivalent 3497 | * property values, else `false`. 3498 | * 3499 | * **Note:** The created function is equivalent to `_.isMatch` with `source` 3500 | * partially applied. 3501 | * 3502 | * Partial comparisons will match empty array and empty object `source` 3503 | * values against any array or object value, respectively. See `_.isEqual` 3504 | * for a list of supported value comparisons. 3505 | * 3506 | * @static 3507 | * @memberOf _ 3508 | * @since 3.0.0 3509 | * @category Util 3510 | * @param {Object} source The object of property values to match. 3511 | * @returns {Function} Returns the new spec function. 3512 | * @example 3513 | * 3514 | * var objects = [ 3515 | * { 'a': 1, 'b': 2, 'c': 3 }, 3516 | * { 'a': 4, 'b': 5, 'c': 6 } 3517 | * ]; 3518 | * 3519 | * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); 3520 | * // => [{ 'a': 4, 'b': 5, 'c': 6 }] 3521 | */ 3522 | function matches(source) { 3523 | return baseMatches(assign({}, source)); 3524 | } 3525 | 3526 | /** 3527 | * Adds all own enumerable string keyed function properties of a source 3528 | * object to the destination object. If `object` is a function, then methods 3529 | * are added to its prototype as well. 3530 | * 3531 | * **Note:** Use `_.runInContext` to create a pristine `lodash` function to 3532 | * avoid conflicts caused by modifying the original. 3533 | * 3534 | * @static 3535 | * @since 0.1.0 3536 | * @memberOf _ 3537 | * @category Util 3538 | * @param {Function|Object} [object=lodash] The destination object. 3539 | * @param {Object} source The object of functions to add. 3540 | * @param {Object} [options={}] The options object. 3541 | * @param {boolean} [options.chain=true] Specify whether mixins are chainable. 3542 | * @returns {Function|Object} Returns `object`. 3543 | * @example 3544 | * 3545 | * function vowels(string) { 3546 | * return _.filter(string, function(v) { 3547 | * return /[aeiou]/i.test(v); 3548 | * }); 3549 | * } 3550 | * 3551 | * _.mixin({ 'vowels': vowels }); 3552 | * _.vowels('fred'); 3553 | * // => ['e'] 3554 | * 3555 | * _('fred').vowels().value(); 3556 | * // => ['e'] 3557 | * 3558 | * _.mixin({ 'vowels': vowels }, { 'chain': false }); 3559 | * _('fred').vowels(); 3560 | * // => ['e'] 3561 | */ 3562 | function mixin(object, source, options) { 3563 | var props = keys(source), 3564 | methodNames = baseFunctions(source, props); 3565 | 3566 | if (options == null && 3567 | !(isObject(source) && (methodNames.length || !props.length))) { 3568 | options = source; 3569 | source = object; 3570 | object = this; 3571 | methodNames = baseFunctions(source, keys(source)); 3572 | } 3573 | var chain = !(isObject(options) && 'chain' in options) || !!options.chain, 3574 | isFunc = isFunction(object); 3575 | 3576 | baseEach(methodNames, function(methodName) { 3577 | var func = source[methodName]; 3578 | object[methodName] = func; 3579 | if (isFunc) { 3580 | object.prototype[methodName] = function() { 3581 | var chainAll = this.__chain__; 3582 | if (chain || chainAll) { 3583 | var result = object(this.__wrapped__), 3584 | actions = result.__actions__ = copyArray(this.__actions__); 3585 | 3586 | actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); 3587 | result.__chain__ = chainAll; 3588 | return result; 3589 | } 3590 | return func.apply(object, arrayPush([this.value()], arguments)); 3591 | }; 3592 | } 3593 | }); 3594 | 3595 | return object; 3596 | } 3597 | 3598 | /** 3599 | * Reverts the `_` variable to its previous value and returns a reference to 3600 | * the `lodash` function. 3601 | * 3602 | * @static 3603 | * @since 0.1.0 3604 | * @memberOf _ 3605 | * @category Util 3606 | * @returns {Function} Returns the `lodash` function. 3607 | * @example 3608 | * 3609 | * var lodash = _.noConflict(); 3610 | */ 3611 | function noConflict() { 3612 | if (root._ === this) { 3613 | root._ = oldDash; 3614 | } 3615 | return this; 3616 | } 3617 | 3618 | /** 3619 | * This method returns `undefined`. 3620 | * 3621 | * @static 3622 | * @memberOf _ 3623 | * @since 2.3.0 3624 | * @category Util 3625 | * @example 3626 | * 3627 | * _.times(2, _.noop); 3628 | * // => [undefined, undefined] 3629 | */ 3630 | function noop() { 3631 | // No operation performed. 3632 | } 3633 | 3634 | /** 3635 | * Generates a unique ID. If `prefix` is given, the ID is appended to it. 3636 | * 3637 | * @static 3638 | * @since 0.1.0 3639 | * @memberOf _ 3640 | * @category Util 3641 | * @param {string} [prefix=''] The value to prefix the ID with. 3642 | * @returns {string} Returns the unique ID. 3643 | * @example 3644 | * 3645 | * _.uniqueId('contact_'); 3646 | * // => 'contact_104' 3647 | * 3648 | * _.uniqueId(); 3649 | * // => '105' 3650 | */ 3651 | function uniqueId(prefix) { 3652 | var id = ++idCounter; 3653 | return toString(prefix) + id; 3654 | } 3655 | 3656 | /*------------------------------------------------------------------------*/ 3657 | 3658 | /** 3659 | * Computes the maximum value of `array`. If `array` is empty or falsey, 3660 | * `undefined` is returned. 3661 | * 3662 | * @static 3663 | * @since 0.1.0 3664 | * @memberOf _ 3665 | * @category Math 3666 | * @param {Array} array The array to iterate over. 3667 | * @returns {*} Returns the maximum value. 3668 | * @example 3669 | * 3670 | * _.max([4, 2, 8, 6]); 3671 | * // => 8 3672 | * 3673 | * _.max([]); 3674 | * // => undefined 3675 | */ 3676 | function max(array) { 3677 | return (array && array.length) 3678 | ? baseExtremum(array, identity, baseGt) 3679 | : undefined; 3680 | } 3681 | 3682 | /** 3683 | * Computes the minimum value of `array`. If `array` is empty or falsey, 3684 | * `undefined` is returned. 3685 | * 3686 | * @static 3687 | * @since 0.1.0 3688 | * @memberOf _ 3689 | * @category Math 3690 | * @param {Array} array The array to iterate over. 3691 | * @returns {*} Returns the minimum value. 3692 | * @example 3693 | * 3694 | * _.min([4, 2, 8, 6]); 3695 | * // => 2 3696 | * 3697 | * _.min([]); 3698 | * // => undefined 3699 | */ 3700 | function min(array) { 3701 | return (array && array.length) 3702 | ? baseExtremum(array, identity, baseLt) 3703 | : undefined; 3704 | } 3705 | 3706 | /*------------------------------------------------------------------------*/ 3707 | 3708 | // Add methods that return wrapped values in chain sequences. 3709 | lodash.assignIn = assignIn; 3710 | lodash.before = before; 3711 | lodash.bind = bind; 3712 | lodash.chain = chain; 3713 | lodash.compact = compact; 3714 | lodash.concat = concat; 3715 | lodash.create = create; 3716 | lodash.defaults = defaults; 3717 | lodash.defer = defer; 3718 | lodash.delay = delay; 3719 | lodash.filter = filter; 3720 | lodash.flatten = flatten; 3721 | lodash.flattenDeep = flattenDeep; 3722 | lodash.iteratee = iteratee; 3723 | lodash.keys = keys; 3724 | lodash.map = map; 3725 | lodash.matches = matches; 3726 | lodash.mixin = mixin; 3727 | lodash.negate = negate; 3728 | lodash.once = once; 3729 | lodash.pick = pick; 3730 | lodash.slice = slice; 3731 | lodash.sortBy = sortBy; 3732 | lodash.tap = tap; 3733 | lodash.thru = thru; 3734 | lodash.toArray = toArray; 3735 | lodash.values = values; 3736 | 3737 | // Add aliases. 3738 | lodash.extend = assignIn; 3739 | 3740 | // Add methods to `lodash.prototype`. 3741 | mixin(lodash, lodash); 3742 | 3743 | /*------------------------------------------------------------------------*/ 3744 | 3745 | // Add methods that return unwrapped values in chain sequences. 3746 | lodash.clone = clone; 3747 | lodash.escape = escape; 3748 | lodash.every = every; 3749 | lodash.find = find; 3750 | lodash.forEach = forEach; 3751 | lodash.has = has; 3752 | lodash.head = head; 3753 | lodash.identity = identity; 3754 | lodash.indexOf = indexOf; 3755 | lodash.isArguments = isArguments; 3756 | lodash.isArray = isArray; 3757 | lodash.isBoolean = isBoolean; 3758 | lodash.isDate = isDate; 3759 | lodash.isEmpty = isEmpty; 3760 | lodash.isEqual = isEqual; 3761 | lodash.isFinite = isFinite; 3762 | lodash.isFunction = isFunction; 3763 | lodash.isNaN = isNaN; 3764 | lodash.isNull = isNull; 3765 | lodash.isNumber = isNumber; 3766 | lodash.isObject = isObject; 3767 | lodash.isRegExp = isRegExp; 3768 | lodash.isString = isString; 3769 | lodash.isUndefined = isUndefined; 3770 | lodash.last = last; 3771 | lodash.max = max; 3772 | lodash.min = min; 3773 | lodash.noConflict = noConflict; 3774 | lodash.noop = noop; 3775 | lodash.reduce = reduce; 3776 | lodash.result = result; 3777 | lodash.size = size; 3778 | lodash.some = some; 3779 | lodash.uniqueId = uniqueId; 3780 | 3781 | // Add aliases. 3782 | lodash.each = forEach; 3783 | lodash.first = head; 3784 | 3785 | mixin(lodash, (function() { 3786 | var source = {}; 3787 | baseForOwn(lodash, function(func, methodName) { 3788 | if (!hasOwnProperty.call(lodash.prototype, methodName)) { 3789 | source[methodName] = func; 3790 | } 3791 | }); 3792 | return source; 3793 | }()), { 'chain': false }); 3794 | 3795 | /*------------------------------------------------------------------------*/ 3796 | 3797 | /** 3798 | * The semantic version number. 3799 | * 3800 | * @static 3801 | * @memberOf _ 3802 | * @type {string} 3803 | */ 3804 | lodash.VERSION = VERSION; 3805 | 3806 | // Add `Array` methods to `lodash.prototype`. 3807 | baseEach(['pop', 'join', 'replace', 'reverse', 'split', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { 3808 | var func = (/^(?:replace|split)$/.test(methodName) ? String.prototype : arrayProto)[methodName], 3809 | chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', 3810 | retUnwrapped = /^(?:pop|join|replace|shift)$/.test(methodName); 3811 | 3812 | lodash.prototype[methodName] = function() { 3813 | var args = arguments; 3814 | if (retUnwrapped && !this.__chain__) { 3815 | var value = this.value(); 3816 | return func.apply(isArray(value) ? value : [], args); 3817 | } 3818 | return this[chainName](function(value) { 3819 | return func.apply(isArray(value) ? value : [], args); 3820 | }); 3821 | }; 3822 | }); 3823 | 3824 | // Add chain sequence methods to the `lodash` wrapper. 3825 | lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; 3826 | 3827 | /*--------------------------------------------------------------------------*/ 3828 | 3829 | // Some AMD build optimizers, like r.js, check for condition patterns like: 3830 | if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { 3831 | // Expose Lodash on the global object to prevent errors when Lodash is 3832 | // loaded by a script tag in the presence of an AMD loader. 3833 | // See http://requirejs.org/docs/errors.html#mismatch for more details. 3834 | // Use `_.noConflict` to remove Lodash from the global object. 3835 | root._ = lodash; 3836 | 3837 | // Define as an anonymous module so, through path mapping, it can be 3838 | // referenced as the "underscore" module. 3839 | define(function() { 3840 | return lodash; 3841 | }); 3842 | } 3843 | // Check for `exports` after `define` in case a build optimizer adds it. 3844 | else if (freeModule) { 3845 | // Export for Node.js. 3846 | (freeModule.exports = lodash)._ = lodash; 3847 | // Export for CommonJS support. 3848 | freeExports._ = lodash; 3849 | } 3850 | else { 3851 | // Export to the global object. 3852 | root._ = lodash; 3853 | } 3854 | }.call(this)); 3855 | -------------------------------------------------------------------------------- /libs/pokeapi.js: -------------------------------------------------------------------------------- 1 | class PokeApi { 2 | static async getTypeEffectiveness(type) { 3 | try { 4 | const response = await fetch(`https://pokeapi.co/api/v2/type/${type}`); 5 | const data = await response.json(); 6 | return data.damage_relations; 7 | } catch (error) { 8 | console.error(`Error fetching type effectiveness for ${type}:`, error); 9 | return null; 10 | } 11 | } 12 | 13 | static async getAbility(pokemonId, abilityIndex) { 14 | try { 15 | const pokemonInfo = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonId}`); 16 | const data = await pokemonInfo.json(); 17 | 18 | const abilityLength = data.abilities.length 19 | 20 | if (abilityIndex >= abilityLength) { 21 | abilityIndex = abilityLength - 1 // Pokerogue uses a "None" ability as padding when pokémon have less than 3. 22 | } 23 | 24 | const abilityName = data.abilities[abilityIndex].ability.name 25 | const abilityInfo = await fetch(`https://pokeapi.co/api/v2/ability/${abilityName}`); 26 | const abilityData = await abilityInfo.json(); 27 | const description = abilityData.flavor_text_entries.find((entry) => entry.language.name === "en") || "No description found" 28 | return { 29 | 'name': abilityName.toUpperCase().replace('-', ' '), 30 | 'description': description.flavor_text, 31 | 'isHidden': data.abilities[abilityIndex].is_hidden 32 | } 33 | } catch (error) { 34 | console.error('Error fetching Pokémons ability:', error); 35 | return null; 36 | } 37 | } 38 | 39 | static async getNature(nature) { 40 | try { 41 | const natureInfo = await fetch(`https://pokeapi.co/api/v2/nature/${nature}`) 42 | const data = await natureInfo.json(); 43 | } catch (error) { 44 | console.error("Error fetching Nature details:", error) 45 | return null; 46 | } 47 | } 48 | 49 | // Function to get Pokémon type 50 | static async getPokemonType(id) { 51 | try { 52 | const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`); 53 | const data = await response.json(); 54 | const types = data.types.map(type => type.type.name); 55 | return types; 56 | } catch (error) { 57 | console.error('Error fetching Pokémon type:', error); 58 | return null; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /libs/pokerogueutils.js: -------------------------------------------------------------------------------- 1 | function _getNatureStatMultiplier(nature, stat) { 2 | switch (stat) { 3 | case Stat.ATK: 4 | switch (nature) { 5 | case Nature.LONELY: 6 | case Nature.BRAVE: 7 | case Nature.ADAMANT: 8 | case Nature.NAUGHTY: 9 | return 1.1; 10 | case Nature.BOLD: 11 | case Nature.TIMID: 12 | case Nature.MODEST: 13 | case Nature.CALM: 14 | return 0.9; 15 | } 16 | break; 17 | case Stat.DEF: 18 | switch (nature) { 19 | case Nature.BOLD: 20 | case Nature.RELAXED: 21 | case Nature.IMPISH: 22 | case Nature.LAX: 23 | return 1.1; 24 | case Nature.LONELY: 25 | case Nature.HASTY: 26 | case Nature.MILD: 27 | case Nature.GENTLE: 28 | return 0.9; 29 | } 30 | break; 31 | case Stat.SPATK: 32 | switch (nature) { 33 | case Nature.MODEST: 34 | case Nature.MILD: 35 | case Nature.QUIET: 36 | case Nature.RASH: 37 | return 1.1; 38 | case Nature.ADAMANT: 39 | case Nature.IMPISH: 40 | case Nature.JOLLY: 41 | case Nature.CAREFUL: 42 | return 0.9; 43 | } 44 | break; 45 | case Stat.SPDEF: 46 | switch (nature) { 47 | case Nature.CALM: 48 | case Nature.GENTLE: 49 | case Nature.SASSY: 50 | case Nature.CAREFUL: 51 | return 1.1; 52 | case Nature.NAUGHTY: 53 | case Nature.LAX: 54 | case Nature.NAIVE: 55 | case Nature.RASH: 56 | return 0.9; 57 | } 58 | break; 59 | case Stat.SPD: 60 | switch (nature) { 61 | case Nature.TIMID: 62 | case Nature.HASTY: 63 | case Nature.JOLLY: 64 | case Nature.NAIVE: 65 | return 1.1; 66 | case Nature.BRAVE: 67 | case Nature.RELAXED: 68 | case Nature.QUIET: 69 | case Nature.SASSY: 70 | return 0.9; 71 | } 72 | break; 73 | } 74 | return 1; 75 | } 76 | 77 | class PokeRogueUtils { 78 | static getNatureDescription(natureIndex) { 79 | let ret = "(-)"; 80 | let increasedStat = null; 81 | let decreasedStat = null; 82 | for (let stat of Object.values(Stat).filter(v => !isNaN(parseInt(v.toString()))).map(v => parseInt(v.toString()))) { 83 | const multiplier = _getNatureStatMultiplier(natureIndex, stat); 84 | if (multiplier > 1) 85 | increasedStat = stat; 86 | else if (multiplier < 1) 87 | decreasedStat = stat; 88 | } 89 | if (increasedStat && decreasedStat) 90 | ret = `(+${Stat[increasedStat]}/-${Stat[decreasedStat]})`; 91 | else if (increasedStat) 92 | ret = `(+${Stat[increasedStat]})`; 93 | else if (decreasedStat) 94 | ret = `(-${Stat[decreasedStat]})`; 95 | return ret; 96 | } 97 | } -------------------------------------------------------------------------------- /libs/utils.js: -------------------------------------------------------------------------------- 1 | async function _calculateTypesEffectiveness(types) { 2 | const typeEffectiveness = await Promise.all(types.map(PokeApi.getTypeEffectiveness)); 3 | if (typeEffectiveness.some(data => data === null)) { 4 | return null; 5 | } 6 | 7 | const weaknesses = new Set(); 8 | const resistances = new Set(); 9 | const immunities = new Set(); 10 | 11 | if (types.length === 1) { 12 | const data = typeEffectiveness[0]; 13 | data.double_damage_from.forEach(t => weaknesses.add(t.name)); 14 | data.half_damage_from.forEach(t => resistances.add(t.name)); 15 | data.no_damage_from.forEach(t => immunities.add(t.name)); 16 | } else if (types.length === 2) { 17 | const [type1, type2] = types; 18 | const type1Effectiveness = typeEffectiveness[0]; 19 | const type2Effectiveness = typeEffectiveness[1]; 20 | 21 | // Calculate weaknesses 22 | type1Effectiveness.double_damage_from.forEach(t => { 23 | if (!type2Effectiveness.half_damage_from.some(r => r.name === t.name)) { 24 | weaknesses.add(t.name) 25 | } 26 | }); 27 | type2Effectiveness.double_damage_from.forEach(t => { 28 | if (!type1Effectiveness.half_damage_from.some(r => r.name === t.name)) { 29 | weaknesses.add(t.name) 30 | } 31 | }); 32 | 33 | // Calculate resistances 34 | type1Effectiveness.half_damage_from.forEach(t => { 35 | if (!type2Effectiveness.double_damage_from.some(r => r.name === t.name)) { 36 | resistances.add(t.name) 37 | } 38 | }); 39 | 40 | type2Effectiveness.half_damage_from.forEach(t => { 41 | if (!type1Effectiveness.double_damage_from.some(r => r.name === t.name)) { 42 | resistances.add(t.name) 43 | } 44 | }); 45 | 46 | // Calculate immunities 47 | type1Effectiveness.no_damage_from.forEach(t => immunities.add(t.name)) 48 | type2Effectiveness.no_damage_from.forEach(t => immunities.add(t.name)) 49 | 50 | immunities.forEach(immunity => { 51 | weaknesses.delete(immunity); 52 | resistances.delete(immunity); 53 | }) 54 | } 55 | 56 | return { weaknesses, resistances, immunities }; 57 | } 58 | 59 | class Utils { 60 | // Function that converts PokeRogue pokemon ID to pokeAPI pokemon ID 61 | static convertPokemonId(pokemonId) { 62 | const conversionList = { 63 | 2019: 10091, 64 | 2020: 10092, 65 | 2026: 10100, 66 | 2027: 10101, 67 | 2028: 10102, 68 | 2037: 10103, 69 | 2038: 10104, 70 | 2050: 10105, 71 | 2051: 10106, 72 | 2052: 10107, 73 | 2053: 10108, 74 | 2074: 10109, 75 | 2075: 10110, 76 | 2076: 10111, 77 | 2088: 10112, 78 | 2089: 10113, 79 | 2103: 10114, 80 | 2105: 10115, 81 | 2670: 10061, 82 | 4052: 10162, 83 | 4077: 10163, 84 | 4078: 10164, 85 | 4079: 10165, 86 | 4080: 10166, 87 | 4083: 10167, 88 | 4110: 10168, 89 | 4122: 10169, 90 | 4144: 10170, 91 | 4145: 10171, 92 | 4146: 10172, 93 | 4199: 10173, 94 | 4222: 10174, 95 | 4263: 10175, 96 | 4264: 10176, 97 | 4554: 10177, 98 | 4555: 10178, 99 | 4562: 10179, 100 | 4618: 10180, 101 | 6058: 10229, 102 | 6059: 10230, 103 | 6100: 10231, 104 | 6101: 10232, 105 | 6157: 10233, 106 | 6211: 10234, 107 | 6215: 10235, 108 | 6503: 10236, 109 | 6549: 10237, 110 | 6570: 10238, 111 | 6571: 10239, 112 | 6628: 10240, 113 | 6705: 10241, 114 | 6706: 10242, 115 | 6713: 10243, 116 | 6724: 10244, 117 | 8128: 10252, 118 | 8194: 10253, 119 | 8901: 10272 120 | } 121 | if (pokemonId in conversionList) { 122 | return conversionList[pokemonId] 123 | } else { 124 | return pokemonId 125 | } 126 | } 127 | 128 | // Function to calculate weaknesses, resistances, and immunities 129 | 130 | 131 | static async getPokemonTypeEffectiveness(id) { 132 | const types = await PokeApi.getPokemonType(id); 133 | if (types) { 134 | const { weaknesses, resistances, immunities } = await _calculateTypesEffectiveness(types); 135 | return { 136 | 'weaknesses': weaknesses, 137 | 'resistances': resistances, 138 | 'immunities': immunities 139 | } 140 | } 141 | return {} 142 | } 143 | 144 | static mapPartyToPokemonArray(party) { 145 | return party.map(({ species, abilityIndex, nature, ivs }) => ({ species, abilityIndex, nature, ivs })) 146 | } 147 | } -------------------------------------------------------------------------------- /manifest_chrome.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "Rogue Dex", 4 | "version": "2.8.3", 5 | "permissions": ["activeTab", "webRequest"], 6 | "host_permissions": [ 7 | "https://pokerogue.net/*", 8 | "https://api.pokerogue.net/*" 9 | ], 10 | "background": { 11 | "service_worker": "service_worker.js" 12 | }, 13 | "content_scripts": [ 14 | { 15 | "matches": ["https://api.pokerogue.net/*", "https://pokerogue.net/*"], 16 | "js": ["inject.js", 17 | "libs/lodash.js", 18 | "libs/localstorageutils.js", 19 | "libs/httputils.js", 20 | "libs/httpjsutils.js", 21 | "libs/enums/Stat.js", 22 | "libs/enums/Types.js"], 23 | "run_at": "document_start", 24 | "all_frames": true 25 | }, 26 | { 27 | "matches": ["https://pokerogue.net/*"], 28 | "js": ["content.js", "libs/crypto-js.min.js"], 29 | "css": ["styles.css"] 30 | } 31 | ], 32 | "web_accessible_resources": [ 33 | { 34 | "resources": ["inject.js", "injected.js"], 35 | "matches": [""], 36 | "extension_ids": [] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /manifest_firefox.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Rogue Dex", 4 | "version": "2.8.3", 5 | "permissions": [ 6 | "activeTab", 7 | "webRequest", 8 | "storage", 9 | "https://pokerogue.net/*", 10 | "https://api.pokerogue.net/*" 11 | ], 12 | "browser_specific_settings": { 13 | "gecko": { 14 | "id": "{46029ed0-cb54-4130-8105-fcbbed40adc1}" 15 | } 16 | }, 17 | "background": { 18 | "scripts": [ 19 | "background.js", 20 | "libs/pokeapi.js", 21 | "libs/pokerogueutils.js", 22 | "libs/utils.js", 23 | "libs/enums/Nature.js", 24 | "libs/enums/Stat.js", 25 | "libs/enums/WeatherType.js" 26 | ], 27 | "persistent": true 28 | }, 29 | "content_scripts": [ 30 | { 31 | "matches": ["https://api.pokerogue.net/*", "https://pokerogue.net/*"], 32 | "js" : [ 33 | "inject.js", 34 | "libs/lodash.js", 35 | "libs/localstorageutils.js", 36 | "libs/httputils.js", 37 | "libs/httpjsutils.js", 38 | "libs/enums/Stat.js", 39 | "libs/enums/Types.js" 40 | ], 41 | "run_at": "document_start", 42 | "all_frames": true 43 | }, 44 | { 45 | "matches": ["https://pokerogue.net/*"], 46 | "js" : [ 47 | "content.js", 48 | "libs/crypto-js.min.js" 49 | ], 50 | "css": ["styles.css"] 51 | } 52 | ], 53 | "web_accessible_resources": ["inject.js", "injected.js"] 54 | } 55 | -------------------------------------------------------------------------------- /roguedex_chrome.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roguedex-dev/roguedex/dfb5c85222ce7a7e3918ee03bb5e415efdfbf10b/roguedex_chrome.zip -------------------------------------------------------------------------------- /roguedex_firefox.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roguedex-dev/roguedex/dfb5c85222ce7a7e3918ee03bb5e415efdfbf10b/roguedex_firefox.zip -------------------------------------------------------------------------------- /service_worker.js: -------------------------------------------------------------------------------- 1 | try { 2 | importScripts("background.js", "libs/pokeapi.js", "libs/pokerogueutils.js", "libs/utils.js", "libs/enums/Nature.js", "libs/enums/Stat.js", "libs/enums/WeatherType.js") 3 | } catch (e) { 4 | console.error("Error while importing script:", e) 5 | } -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --font-size: min(3vh, 2vw); 3 | --font-size-sm: min(3vh, 3vw); 4 | --font-size-m: min(2vh, 2vw); 5 | --font-size-l: min(2vh, 3vw); 6 | --font-size-xl: min(3vh, 3vw); 7 | --arrow-font-size: calc(var(--font-size) * 2); 8 | --pkm-icon-size: min(10vh, 6vw); 9 | --pkm-icon-size-sm: min(15vh, 12vw); 10 | --pkm-icon-size-m: min(10vh, 12vw); 11 | --pkm-icon-size-l: min(12vh, 12vw); 12 | --pkm-icon-size-xl: min(12vh, 12vw); 13 | --type-icon-size: min(5vh, 3vw); 14 | --type-icon-size-sm: min(5vh, 5vw); 15 | --type-icon-size-m: min(4vh, 4vw); 16 | --type-icon-size-l: min(3vh, 4vw); 17 | --type-icon-size-xl: min(4vh, 5vw); 18 | } 19 | 20 | @media only screen and (min-width: 0px) { 21 | :root { 22 | --font-size: var(--font-size-sm); 23 | --pkm-icon-size: var(--pkm-icon-size-sm); 24 | --type-icon-size: var(--type-icon-size-sm); 25 | } 26 | } 27 | 28 | @media only screen and (min-width: 720px) { 29 | :root { 30 | --font-size: var(--font-size-m); 31 | --pkm-icon-size: var(--pkm-icon-size-m); 32 | --type-icon-size: var(--type-icon-size-m); 33 | } 34 | } 35 | 36 | @media only screen and (min-width: 2560px) { 37 | :root { 38 | --font-size: var(--font-size-l); 39 | --pkm-icon-size: var(--pkm-icon-size-l); 40 | --type-icon-size: var(--type-icon-size-l); 41 | } 42 | } 43 | 44 | @media only screen and (min-width: 5120px) { 45 | :root { 46 | --font-size: var(--font-size-xl); 47 | --pkm-icon-size: var(--pkm-icon-size-xl); 48 | --type-icon-size: var(--type-icon-size-xl); 49 | } 50 | } 51 | .allies-team { 52 | margin: 0 auto; 53 | padding: 0 auto; 54 | position: absolute; 55 | top: 0; 56 | right: 0; 57 | z-index: 1; 58 | display: flex; 59 | } 60 | 61 | .enemies-team { 62 | margin: 0 auto; 63 | padding: 0 auto; 64 | position: absolute; 65 | top: 0; 66 | z-index: 1; 67 | display: flex; 68 | } 69 | 70 | .pokemon-cards { 71 | display: flex; 72 | flex-wrap: nowrap; 73 | overflow: hidden; 74 | } 75 | 76 | .pokemon-card { 77 | background-color: #333333b8; 78 | border: 2px solid #555; 79 | border-radius: 8px; 80 | flex: 0 0 auto; 81 | display:flex; 82 | flex-direction: column; 83 | } 84 | 85 | .pokemon-icon img { 86 | width: var(--pkm-icon-size); 87 | height: var(--pkm-icon-size); 88 | } 89 | 90 | .pokemon-info { 91 | margin-top: 10px; 92 | } 93 | 94 | .pokemon-types { 95 | display: flex; 96 | justify-content: center; 97 | margin-bottom: 10px; 98 | } 99 | 100 | .type-icon { 101 | --width: var(--type-icon-size); 102 | --height: var(--type-icon-size); 103 | width: var(--width); 104 | height: var(--height); 105 | background-size: cover; 106 | background-repeat: no-repeat; 107 | background-position: left; 108 | background-position-x: min(-0.03em, -1.15px); 109 | border-radius: 50%; 110 | margin: 0 5px; 111 | } 112 | 113 | .pokemon-weaknesses, 114 | .pokemon-resistances, 115 | .pokemon-immunities { 116 | min-width: var(--type-icon-size); 117 | display: flex; 118 | justify-content: center; 119 | } 120 | 121 | .pokemon-weaknesses { 122 | background-color: #6a1f1f; 123 | border: 2px solid red; 124 | border-radius: 10px; 125 | } 126 | 127 | .pokemon-resistances { 128 | background-color: #216a1f; 129 | border: 2px solid green; 130 | border-radius: 10px; 131 | } 132 | 133 | .pokemon-immunities { 134 | background-color: #484848; 135 | border: 2px solid white; 136 | border-radius: 10px; 137 | } 138 | 139 | .pokemon-weaknesses .type-icon, 140 | .pokemon-resistances .type-icon, 141 | .pokemon-immunities .type-icon { 142 | opacity: 1; 143 | } 144 | 145 | .text-base { 146 | display: flex; 147 | font-family: 'emerald'; 148 | font-size: var(--font-size); 149 | text-shadow: 2px 0 #fff, -2px 0 #fff, 0 2px #fff, 0 -2px #fff, 1px 1px #fff, -1px -1px #fff, 1px -1px #fff, -1px 1px #fff; 150 | color: black; 151 | } 152 | 153 | .arrow-button-wrapper { 154 | display: grid; 155 | } 156 | .arrow-button { 157 | font-size: var(--arrow-font-size); 158 | } 159 | 160 | .tooltip .tooltiptext { 161 | visibility: hidden; 162 | text-align: center; 163 | border-radius: 6px; 164 | padding: 5px 0; 165 | font-size: var(--font-size); 166 | position: absolute; 167 | z-index: 1; 168 | background-color: #fff; 169 | max-width: 12vw; 170 | } 171 | 172 | .tooltip:hover .tooltiptext { 173 | visibility: visible; 174 | } 175 | 176 | /* Slider settings */ 177 | @media screen and (-webkit-min-device-pixel-ratio:0) { 178 | input[type='range'] { 179 | overflow: hidden; 180 | width: 100%; 181 | -webkit-appearance: none; 182 | } 183 | 184 | input[type='range']::-webkit-slider-runnable-track { 185 | height: 1vh; 186 | -webkit-appearance: none; 187 | color: #13bba4; 188 | margin-top: -1px; 189 | } 190 | 191 | input[type='range']::-webkit-slider-thumb { 192 | width: 1vh; 193 | -webkit-appearance: none; 194 | height: 1vh; 195 | cursor: ew-resize; 196 | box-shadow: -8vh 0 0 8vh #b3462c; 197 | } 198 | 199 | } 200 | /** FF*/ 201 | input[type="range"]::-moz-range-progress { 202 | background-color: #b3462c; 203 | } 204 | input[type="range"]::-moz-range-track { 205 | background-color: #fff; 206 | } 207 | input[type="range"] { 208 | background-color:transparent 209 | } 210 | 211 | .slider-wrapper { 212 | display: flex; 213 | } 214 | 215 | .running-status { 216 | position: absolute; 217 | width: 100%; 218 | justify-content: center; 219 | text-align: center; 220 | color: blue; 221 | background-color: #ffffff50; 222 | } 223 | 224 | .hidden-ability { 225 | color: #f700ff; 226 | } 227 | 228 | input { 229 | font-size: var(--font-size); 230 | } --------------------------------------------------------------------------------