Infinite Craft Helper

A script that adds various useful features to Infinite Craft.

  1. // ==UserScript==
  2. // @name Infinite Craft Helper
  3. // @namespace mikarific.com
  4. // @match https://neal.fun/infinite-craft/*
  5. // @version 2.1.4
  6. // @author Mikarific
  7. // @description A script that adds various useful features to Infinite Craft.
  8. // @icon https://i.imgur.com/WlkWOkU.png
  9. // @grant GM.getValue
  10. // @grant GM.setValue
  11. // @grant GM.xmlHttpRequest
  12. // @grant unsafeWindow
  13. // @run-at document-end
  14. // @noframes
  15. // @inject-into page
  16. // @sandbox raw
  17. // @connect *
  18. // @supportURL https://discord.gg/NSMut3Wx3Y
  19. // @homepageURL https://discord.gg/NSMut3Wx3Y
  20. // @license MIT
  21. //
  22. // Created with love using Gorilla
  23. // ==/UserScript==
  24.  
  25. (function () {
  26. 'use strict';
  27.  
  28. const whiteFavicon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6CAQAAAAi5ZK2AAAFUWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMjUwIgogICB0aWZmOkltYWdlV2lkdGg9IjI1MCIKICAgdGlmZjpSZXNvbHV0aW9uVW5pdD0iMiIKICAgdGlmZjpYUmVzb2x1dGlvbj0iNzIvMSIKICAgdGlmZjpZUmVzb2x1dGlvbj0iNzIvMSIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjI1MCIKICAgZXhpZjpQaXhlbFlEaW1lbnNpb249IjI1MCIKICAgZXhpZjpDb2xvclNwYWNlPSI2NTUzNSIKICAgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMSIKICAgcGhvdG9zaG9wOklD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';
  29. const closeIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgNjAwIj48cGF0aCBkPSJNMzAwLjAwMDAyLDM0OS44MzIzM0w2MC4xMDc4Miw1ODkuNzIzMzJjLTYuNTQ2ODksNi41NDc2OS0xNC43NzY0Myw5Ljg5NzE4LTI0LjY4ODYsMTAuMDQ4NTEtOS45MTEzOCwuMTUyMS0xOC4yOTIyNC0zLjE5NzQtMjUuMTQyNTYtMTAuMDQ4NTFDMy40MjU1Nyw1ODIuODcyOTgsLjAwMDAyLDU3NC41Njc4LDAsNTY0LjgwNzc0Yy4wMDAwMi05Ljc2MDA3LDMuNDI1NTctMTguMDY1MjYsMTAuMjc2NjYtMjQuOTE1NTZsMjM5Ljg5MTAxLTIzOS44OTIyTDEwLjI3NjY4LDYwLjEwNzc4QzMuNzI4OTksNTMuNTYwOTIsLjM3OTUsNDUuMzMxMzYsLjIyODE3LDM1LjQxOTIyLC4wNzYwNywyNS41MDc4OCwzLjQyNTU3LDE3LjEyNywxMC4yNzY2OCwxMC4yNzY2NiwxNy4xMjcwMiwzLjQyNTUzLDI1LjQzMjIsMCwzNS4xOTIyNiwwczE4LjA2NTI2LDMuNDI1NTMsMjQuOTE1NTYsMTAuMjc2NjZsMjM5Ljg5MjIsMjM5Ljg5MDk3TDUzOS44OTIyMiwxMC4yNzY1OWM2LjU0Njg2LTYuNTQ3NzIsMTQuNzc2NDMtOS44OTcyLDI0LjY4ODU2LTEwLjA0ODUxLDkuOTExMzQtLjE1MjE3LDE4LjI5MjIyLDMuMTk3MzgsMjUuMTQyNTYsMTAuMDQ4NTEsNi44NTExMyw2Ljg1MDI3LDEwLjI3NjY2LDE1LjE1NTUyLDEwLjI3NjY2LDI0LjkxNTU2cy0zLjQyNTUzLDE4LjA2NTIyLTEwLjI3NjY2LDI0LjkxNTU2bC0yMzkuODkwOTcsMjM5Ljg5MjI3LDIzOS44OTEwNSwyMzkuODkyMmM2LjU0NzcyLDYuNTQ2ODksOS44OTcyLDE0Ljc3NjQzLDEwLjA0ODUxLDI0LjY4ODYsLjE1MjE3LDkuOTExMzgtMy4xOTczOCwxOC4yOTIyNC0xMC4wNDg1MSwyNS4xNDI1Ni02Ljg1MDI3LDYuODUxMS0xNS4xNTU1MiwxMC4yNzY2NC0yNC45MTU1NiwxMC4yNzY2Ni05Ljc2MDA0LS4wMDAwMi0xOC4wNjUyMi0zLjQyNTU3LTI0LjkxNTU2LTEwLjI3NjY2bC0yMzkuODkyMjctMjM5Ljg5MTAxWiIvPjwvc3ZnPg==';
  30. const discoveriesIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgNTc5LjAyMTgyIj48cGF0aCBkPSJNMTE5Ljc1MDQzLDU3OS4wMjE4MmMtMTMuODM0NzUsMC0yNS4yOTQzOC04LjE5ODM3LTI4LjgyNjkxLTIwLjUwNzk4bC0xNy44Njc2Mi01Mi41NTM5NS01NS4zNzUxNi0xOC44MzIxMy0yLjAwNzM5LTEuMzM4MjZjLTEwLjEwOTMxLTYuNzE1NDMtMTUuNjczMzUtMTYuMTMxNS0xNS42NzMzNS0yNi41MjQxMywwLTEzLjgyODcyLDguMTkyMzQtMjUuMjk0MzgsMjAuNDg5ODktMjguODI2OTFsNTIuNTY2MDEtMTcuODc5NjgsMTguODMyMTMtNTUuMzg3MjEsMS4zNTAzMi0yLjAyNTQ4YzkuMDg0NTItMTMuNTk5NjUsMjAuNTA3OTgtMTUuNjM3MTgsMjYuNTEyMDgtMTUuNjM3MTgsMTMuODQ2OCwwLDI1LjMwMDQxLDguMTk4MzcsMjguODI2OTEsMjAuNDk1OTJsMTcuODY3NjIsNTIuNTUzOTUsNTIuNTY2MDEsMTcuODc5NjhjMTIuMjk3NTUsMy41MzI1MywyMC40OTU5MiwxNC45OTgxOSwyMC40OTU5MiwyOC44MjY5MSwwLDEzLjg0MDc3LTguMTk4MzcsMjUuMjk0MzgtMjAuNTA3OTgsMjguODI2OTFsLTUyLjU1Mzk1LDE3Ljg2NzYyLTE4LjgzMjEzLDU1LjM4NzIxLTEuMzM4MjYsMi4wMTM0MmMtOS4wODQ1MiwxMy42MjM3Ni0yMC41MTQwMSwxNS42NjEyOS0yNi41MjQxMywxNS42NjEyOVptLTY4Ljk4MDgzLTExOS43Njg1Mmw1MS40NzQ5LDE3LjUwNTkzLDE3LjUwNTkzLDUxLjQ4MDkzLDE3LjUwNTkzLTUxLjQ4MDkzLDUxLjQ3NDktMTcuNTA1OTMtNTEuNDc0OS0xNy40OTM4Ny0xNy41MDU5My01MS40ODA5My0xNy41MDU5Myw1MS40ODA5My01MS40NzQ5LDE3LjQ5Mzg3Wm0zNDUuNTI1MDYsNjIuOTcwN2MtMTMuOTAxMDYsMC0yNS40MDI4OS04LjI3MDcxLTI4Ljg2MzA4LTIwLjY2NDcxbC0zNy43MDA0NC0xMTYuNDc3MTEtMTE5LjM1ODYtMzguNjE2NzMtMi4xNDAwMi0xLjQzNDcxYy0xMy42MTE3LTkuMDc4NDktMTUuNjQzMjEtMjAuNTA3OTgtMTUuNjQzMjEtMjYuNTEyMDgsMC0xMy45MDEwNiw4LjI3MDcxLTI1LjQwMjg5LDIwLjY3MDc0LTI4Ljg2OTExbDExNi40NzEwOC0zNy42ODIzNSwzOC42Mjg3OC0xMTkuMzUyNTcsMS40MTA2LTIuMTIxOTNjNi43MTU0My0xMC4xMDkzMSwxNi4xMzE1LTE1LjY3OTM4LDI2LjUyNDEzLTE1LjY3OTM4LDE0LjE2NjMsMCwyNS44NDg5Nyw4LjYwMjI2LDI5LjA4MDA5LDIxLjQxMjIxbDM3LjQ4MzQyLDExNS43MzU2NCwxMTcuMDU1ODIsMzcuODgxMjhjMTEuNDUzNiwzLjgwMzgsMjAuMDg2LDE2LjEyNTQ3LDIwLjA4NiwyOC42NzYyLDAsMTQuMTY2My04LjU5NjIzLDI1Ljg0ODk3LTIxLjQwMDE1LDI5LjA2ODA0bC0xMTUuNzQxNjcsMzcuNDgzNDItMzguNjE2NzMsMTE5LjM4MjcxLTEuNDM0NzEsMi4xMzM5OWMtOS4wNzg0OSwxMy42MTE3LTIwLjUwNzk4LDE1LjYzNzE4LTI2LjUxMjA4LDE1LjYzNzE4Wm0tMTUxLjk1OTE3LTIwMy43MDUzNGwxMTQuODEzMzMsMzcuMTQ1ODQsMzcuMTQ1ODQsMTE0LjgxMzMzLDM3LjE0NTg0LTExNC44MTMzMywxMTQuODEzMzMtMzcuMTQ1ODQtMTE0LjgxMzMzLTM3LjE0NTg0LTM3LjE0NTg0LTExNC44MTMzMy0zNy4xNDU4NCwxMTQuODEzMzMtMTE0LjgxMzMzLDM3LjE0NTg0Wm0tNzguOTAzMjctOS44NzQyMWMtMTMuODUyODMsMC0yNS4zMTg0OS04LjIxMDQyLTI4LjgzMjk0LTIwLjUyNjA2bC0yNi41MTgxLTc4LjQ0NTEyLTc4Ljk2MzU1LTI2LjY5MjkyYy0xMi4xNTg5LTQuMDg3MTMtMjAuMDA3NjQtMTUuMzIzNzEtMjAuMDA3NjQtMjguNjU4MTIsMC0xMy44NDY4LDguMjA0NC0yNS4zMDY0MywyMC41MjAwMy0yOC44MzI5NGw3OC40NTExNS0yNi41MTgxLDI3LjQ3NjU5LTgxLjI3ODM4LDEuMzQ0MjktMi4wMTk0NUMxNDcuOTY4NDksMi4wMzc1NCwxNTkuNDE2MDcsMCwxNjUuNDMyMjIsMGMxMy44NDA3NywwLDI1LjMwNjQzLDguMjA0NCwyOC44MzI5NCwyMC41MjAwM2wyNi41MTgxLDc4LjQ1MTE1LDgxLjI4NDQxLDI3LjQ3NjU5LDIuMDI1NDgsMS4zNTAzMmMxMy42Mjk3OSw5LjA3ODQ5LDE1LjY2NzMyLDIwLjUxNDAxLDE1LjY2NzMyLDI2LjUyNDEzLDAsMTMuODQwNzctOC4yMTA0MiwyNS4zMDY0My0yMC41MjYwNiwyOC44MzI5NGwtNzguNDUxMTUsMjYuNTE4MS0yNy40NzY1OSw4MS4yODQ0MS0xLjM1NjM1LDIuMDMxNTFjLTkuMDc4NDksMTMuNjE3NzMtMjAuNTE0MDEsMTUuNjU1MjctMjYuNTE4MSwxNS42NTUyN1pNNjIuMDAwMTYsMTU0LjMyMjIzbDc3LjI5MzczLDI2LjEyNjI3LDI2LjEzODMzLDc3LjMwNTc5LDI2LjEyNjI3LTc3LjMwNTc5LDc3LjMwNTc5LTI2LjEyNjI3LTc3LjMwNTc5LTI2LjEyNjI3LTI2LjEyNjI3LTc3LjMwNTc5LTI2LjEzODMzLDc3LjMwNTc5LTc3LjI5MzczLDI2LjEyNjI3WiIvPjwvc3ZnPg==';
  31. const randomIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgNjAwIj48cGF0aCBkPSJNNjAuNTc2NTcsNjAwYy0xNy4yNTkzOCwwLTMxLjY3MDMyLTUuNzgxMjUtNDMuMjMyODItMTcuMzQzNzVTMCw1NTYuNjgyODEsMCw1MzkuNDIzNDN2LTEwOC4xNzM0M2MwLTUuMzM2MjQsMS43OTA5NC05Ljc5NTMxLDUuMzcyODItMTMuMzc3MiwzLjU4MTI2LTMuNTgxODksOC4wNDAzLTUuMzcyOCwxMy4zNzcxOC01LjM3MjgsNS4zMzYyNSwwLDkuNzk1MywxLjc5MDkxLDEzLjM3NzE4LDUuMzcyOCwzLjU4MTg3LDMuNTgxODYsNS4zNzI4Miw4LjA0MDkzLDUuMzcyODIsMTMuMzc3MnYxMDguMTczNDVjMCw1Ljc2ODc0LDIuNDAzNzYsMTEuMDU3MTgsNy4yMTEyNSwxNS44NjUzMiw0LjgwODEyLDQuODA3NDgsMTAuMDk2NTYsNy4yMTEyNCwxNS44NjUzMiw3LjIxMTI0aDEwOC4xNzM0M2M1LjMzNjI0LDAsOS43OTUzMSwxLjc5MDk0LDEzLjM3NzIsNS4zNzI4MiwzLjU4MTg5LDMuNTgxODksNS4zNzI4LDguMDQwOTMsNS4zNzI4LDEzLjM3NzE4LDAsNS4zMzY4OC0xLjc5MDkxLDkuNzk1OTMtNS4zNzI4LDEzLjM3NzE4LTMuNTgxODksMy41ODE4Ny04LjA0MDk2LDUuMzcyODItMTMuMzc3Miw1LjM3MjgySDYwLjU3NjU3Wm00NzguODQ2ODgsMGgtMTA4LjE3MzQ1Yy01LjMzNjI3LDAtOS43OTUyOC0xLjc5MDk0LTEzLjM3NzE3LTUuMzcyODItMy41ODE4OS0zLjU4MTI2LTUuMzcyODMtOC4wNDAzLTUuMzcyODMtMTMuMzc3MTgsMC01LjMzNjI1LDEuNzkwOTQtOS43OTUzLDUuMzcyODMtMTMuMzc3MTgsMy41ODE4OS0zLjU4MTg3LDguMDQwOTYtNS4zNzI4MiwxMy4zNzcxNy01LjM3MjgyaDEwOC4xNzM0NWM1Ljc2ODc0LDAsMTEuMDU3MjItMi40MDM3NiwxNS44NjUyOS03LjIxMTI1LDQuODA3NTUtNC44MDgxMiw3LjIxMTI3LTEwLjA5NjU2LDcuMjExMjctMTUuODY1MzJ2LTEwOC4xNzM0M2MwLTUuMzM2MjQsMS43OTA5NC05Ljc5NTMxLDUuMzcyODMtMTMuMzc3MiwzLjU4MTg5LTMuNTgxODksOC4wNDA5Ni01LjM3MjgsMTMuMzc3MTctNS4zNzI4LDUuMzM2ODksMCw5Ljc5NTkxLDEuNzkwOTEsMTMuMzc3MTcsNS4zNzI4LDMuNTgxODksMy41ODE4OSw1LjM3MjgzLDguMDQwOTYsNS4zNzI4MywxMy4zNzcydjEwOC4xNzM0NWMwLDE3LjI1OTM2LTUuNzgxMjcsMzEuNjcwMzEtMTcuMzQzNzUsNDMuMjMyOC0xMS41NjI0OCwxMS41NjI1LTI1Ljk3MzQ1LDE3LjM0Mzc1LTQzLjIzMjgsMTcuMzQzNzVaTTAsNjAuNTc2NTVDMCw0My4zMTcyLDUuNzgxMjUsMjguOTA2MjMsMTcuMzQzNzUsMTcuMzQzNzUsMjguOTA2MjUsNS43ODEyNyw0My4zMTcxOSwwLDYwLjU3NjU3LDBoMTA4LjE3MzQzYzUuMzM2MjQsMCw5Ljc5NTMxLDEuNzkwOTQsMTMuMzc3Miw1LjM3MjgzLDMuNTgxODksMy41ODEyNiw1LjM3MjgsOC4wNDAyOCw1LjM3MjgsMTMuMzc3MTcsMCw1LjMzNjMyLTEuNzkwOTEsOS43OTUyOC01LjM3MjgsMTMuMzc3MTctMy41ODE4NiwzLjU4MTgzLTguMDQwOTMsNS4zNzI4My0xMy4zNzcyLDUuMzcyODNINjAuNTc2NTdjLTUuNzY4NzUsMC0xMS4wNTcxOCwyLjQwMzcyLTE1Ljg2NTMyLDcuMjExMjctNC44MDc0OSw0LjgwODA2LTcuMjExMjUsMTAuMDk2NTUtNy4yMTEyNSwxNS44NjUyOXYxMDguMTczNDVjMCw1LjMzNjI3LTEuNzkwOTQsOS43OTUyOC01LjM3MjgyLDEzLjM3NzE3LTMuNTgxODksMy41ODE4My04LjA0MDkzLDUuMzcyNzctMTMuMzc3MTgsNS4zNzI4My01LjMzNjg4LDAtOS43OTU5My0xLjc5MDk0LTEzLjM3NzE4LTUuMzcyODMtMy41ODE4Ny0zLjU4MTg5LTUuMzcyODItOC4wNDA5LTUuMzcyODItMTMuMzc3MTdWNjAuNTc2NTVabTYwMCwwdjEwOC4xNzM0NWMwLDUuMzM2MjctMS43OTA5NCw5Ljc5NTI4LTUuMzcyODMsMTMuMzc3MTctMy41ODEyNiwzLjU4MTg5LTguMDQwMjgsNS4zNzI4My0xMy4zNzcxNyw1LjM3MjgzLTUuMzM2MzIsMC05Ljc5NTI4LTEuNzkwOTQtMTMuMzc3MTctNS4zNzI4My0zLjU4MTgzLTMuNTgxODktNS4zNzI4My04LjA0MDk2LTUuMzcyODMtMTMuMzc3MTdWNjAuNTc2NTVjMC01Ljc2ODc0LTIuNDAzNzItMTEuMDU3MjItNy4yMTEyNy0xNS44NjUyOS00LjgwODA2LTQuODA3NTUtMTAuMDk2NTUtNy4yMTEyNy0xNS44NjUyOS03LjIxMTI3aC0xMDguMTczNDVjLTUuMzM2MjcsMC05Ljc5NTI4LTEuNzkwOTQtMTMuMzc3MTctNS4zNzI4My0zLjU4MTgzLTMuNTgxODktNS4zNzI3Ny04LjA0MDk2LTUuMzcyODMtMTMuMzc3MTcsMC01LjMzNjg5LDEuNzkwOTQtOS43OTU5MSw1LjM3MjgzLTEzLjM3NzE3LDMuNTgxODktMy41ODE4OSw4LjA0MDktNS4zNzI4MywxMy4zNzcxNy01LjM3MjgzaDEwOC4xNzM0NWMxNy4yNTkzNSwwLDMxLjY3MDMyLDUuNzgxMjcsNDMuMjMyOCwxNy4zNDM3NXMxNy4zNDM3NSwyNS45NzM0NSwxNy4zNDM3NSw0My4yMzI4Wk0zMDEuNDQxODcsNDk1LjQzMzEzYzguMzE3NTEsMCwxNS4zMjUwMS0yLjg0ODc1LDIxLjAyMjUxLTguNTQ2MjUsNS42OTY5LTUuNjk2ODcsOC41NDUzMy0xMi43MDQwNiw4LjU0NTMzLTIxLjAyMTU3cy0yLjg0ODQzLTE1LjMyNDctOC41NDUzLTIxLjAyMTU3Yy01LjY5NzUzLTUuNjk2ODctMTIuNzA1LTguNTQ1My0yMS4wMjI1MS04LjU0NTMtOC4zMTY5MSwwLTE1LjMyNDA3LDIuODQ4NDMtMjEuMDIxNTcsOC41NDUzLTUuNjk2OSw1LjY5Njg3LTguNTQ1MzMsMTIuNzA0MDYtOC41NDUzMywyMS4wMjE1N3MyLjg0ODQzLDE1LjMyNDcsOC41NDUzLDIxLjAyMTU3YzUuNjk3NDcsNS42OTc1LDEyLjcwNDY5LDguNTQ2MjUsMjEuMDIxNTcsOC41NDYyNVptMC0zNTUuOTYyMTVjMTkuMTM0OTgsMCwzNS42Mzc1LDYuMDgxODUsNDkuNTA3NTEsMTguMjQ1NiwxMy44NzAwMSwxMi4xNjMxMiwyMC44MDUwMiwyNy40OTk2OSwyMC44MDUwMiw0Ni4wMDk3MSwwLDEzLjQxMzE2LTMuOTMwMywyNS42MjQ2OS0xMS43OTA5NiwzNi42MzQ3MS03Ljg2MDAzLDExLjAwOTM5LTE2Ljg2MjE4LDIwLjk2MTIzLTI3LjAwNjU3LDI5Ljg1NTYzLTE2LjI1MDAxLDE0Ljg1NTYtMjguMzUzNDUsMjguNjg5NjgtMzYuMzEwMyw0MS41MDIyLTcuOTU2ODgsMTIuODEyNDktMTIuNTYwMjksMjYuODM5MDYtMTMuODEwMyw0Mi4wNzk3LS42MjQ5OSw0LjkwMzc0LC44MTc0OCw5LjA3NDM5LDQuMzI3NSwxMi41MTE4OCwzLjUwOTM5LDMuNDM3NTIsNy43ODgxMSw1LjE1NjI1LDEyLjgzNjI0LDUuMTU2MjUsNC45MDM3NiwwLDkuMTQ2NTgtMS42ODI4LDEyLjcyODQzLTUuMDQ4NDUsMy41ODE4OS0zLjM2NTAyLDUuNzU3NTItNy41NzE1NSw2LjUyNjg4LTEyLjYxOTY5LDEuNzMwNjMtMTAuNjI1MDEsNS40ODA2My0yMC4xMjAzMiwxMS4yNS0yOC40ODU5NSw1Ljc2ODc0LTguMzY1NjMsMTQuODMxMi0xOC43MjYyNSwyNy4xODc1LTMxLjA4MTg3LDE4Ljk4OTk4LTE4Ljk5MDYxLDMyLjA3ODctMzQuOTY0MDgsMzkuMjY2MjItNDcuOTIwMzMsNy4xODc1Mi0xMi45NTY4OSwxMC43ODEyNS0yNy4zNjgxNCwxMC43ODEyNS00My4yMzM3OCwwLTI4Ljk0MTg4LTkuNzgzNzMtNTIuNTk1NjctMjkuMzUxMjMtNzAuOTYxMjctMTkuNTY2ODgtMTguMzY1NjUtNDQuNzM1MDEtMjcuNTQ4NDUtNzUuNTA0MzctMjcuNTQ4NDUtMjEuMjk4MTEsMC00MC43ODEyNSw0LjgxOTY4LTU4LjQ0OTM4LDE0LjQ1OTA0LTE3LjY2ODc2LDkuNjM5MzYtMzEuODE1NjEsMjMuNjQxODMtNDIuNDQwNjEsNDIuMDA3NDgtMi4zMDc1LDQuMTM1MDQtMi41ODM3Niw4LjU0NjI4LS44Mjg3NSwxMy4yMzM3OHM1LjAxMjIsNy44NzI1MSw5Ljc3MTU3LDkuNTU1MDJjNC4yNzg3NSwxLjY4MjUxLDguODM0MDcsMS44MDI4NSwxMy42NjU5MywuMzYwOTUsNC44MzE4Ny0xLjQ0MjQ3LDguNzg2MjMtNC4xNTkwNywxMS44NjMxMi04LjE0OTY4LDguMzE3NTEtMTAuNjczMTYsMTcuODQ4NzUtMTkuNDM1MDQsMjguNTkzNzUtMjYuMjg1NjUsMTAuNzQ0OTctNi44NTEyMywyMi44NzIxNi0xMC4yNzY4NSwzNi4zODE1Ny0xMC4yNzY4NVoiLz48L3N2Zz4=';
  32. const uploadIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NzMuNjgzODcgNjAwIj48cGF0aCBkPSJNMjEzLjE1ODQ1LDM2MS41NzY3NXYxMTYuMzU4NDVjMCw2LjcyMDAxLDIuMjY3MTIsMTIuMzQ3NCw2LjgwMTMzLDE2Ljg4MjE1LDQuNTM0MjMsNC41MzQyMywxMC4xNjE1OCw2LjgwMTM0LDE2Ljg4MjE1LDYuODAxMzRzMTIuMzQ3OTItMi4yNjcxLDE2Ljg4MjE1LTYuODAxMzRjNC41MzQyMS00LjUzNDc1LDYuODAxMzMtMTAuMTYyMTQsNi44MDEzMy0xNi44ODIxNXYtMTE2LjM1ODQ1bDQxLjc4MzAyLDQxLjc4Mjk5YzIuMzQ3OSwyLjM0NzksNC45ODk0OSw0LjEwODk3LDcuOTI0NzgsNS4yODMxNiwyLjkzNTI4LDEuMTc0MjIsNS44NzAyOCwxLjY4MDI2LDguODA1MDMsMS41MTgxNywyLjkzNTI4LS4xNjIxMiw1Ljg0MDMxLS44MzAwMiw4LjcxNTAyLTIuMDAzNjgsMi44NzQyMy0xLjE3NDE5LDUuNDg1MjgtMi45MzU1Myw3LjgzMzE4LTUuMjgzOTYsNC41NzUyOS00Ljg5ODQ1LDYuOTQzNzEtMTAuNDQ0NzUsNy4xMDUyOC0xNi42Mzg5OCwuMTYyMS02LjE5NDIzLTIuMjA2MzMtMTEuNzQwNTYtNy4xMDUyOC0xNi42Mzg5OGwtNzguNzY1MTktNzguNzY1MjFjLTIuOTU1MjgtMi45NTU3OS02LjA3MjY0LTUuMDQwODEtOS4zNTIxNC02LjI1NTAyLTMuMjc4OTctMS4yMTQ3NC02LjgyMTM1LTEuODIyMTUtMTAuNjI3MTMtMS44MjIxMi0zLjgwNTc4LS4wMDAwMi03LjM0ODE5LC42MDczOC0xMC42MjcxMywxLjgyMjEyLTMuMjc5NDUsMS4yMTQyMS02LjM5Njg1LDMuMjk5MjMtOS4zNTIxNCw2LjI1NTAybC03OC43NjUxOSw3OC43NjUxOWMtNC42OTYzMSw0LjY5NTc4LTcuMDE0MjMsMTAuMTkxNi02Ljk1MzcxLDE2LjQ4NzQxLC4wNjA1Miw2LjI5NTI4LDIuNTQwMjgsMTEuODkyMTMsNy40MzkyMywxNi43OTA1Nyw0Ljg5ODQ1LDQuNTc1MjYsMTAuNDQ0NzUsNi45NDM2OSwxNi42Mzg5OCw3LjEwNTI4LDYuMTk0MjMsLjE2MjEyLDExLjc0MDgzLTIuMjA2MzEsMTYuNjM5NzgtNy4xMDUyOGw0MS4yOTY2NS00MS4yOTY2OFpNNTcuMDg1NDEsNTk5Ljk5OTk5Yy0xNS45NTE2MSwwLTI5LjQ1Mzc1LTUuNTI2MzMtNDAuNTA2NDItMTYuNTc4OTlDNS41MjYzNCw1NzIuMzY4MzQsLjAwMDAxLDU1OC44NjYyLDAsNTQyLjkxNDU5VjU3LjA4NTRjLjAwMDAxLTE1Ljk1MTU2LDUuNTI2MzQtMjkuNDUzNzUsMTYuNTc4OTktNDAuNTA2NDFDMjcuNjMxNjYsNS41MjYzMyw0MS4xMzM4LDAsNTcuMDg1NDEsMGgyMjcuMTg2NjRjNy42MTEwOSwwLDE0LjkyODcyLDEuNDc3OTEsMjEuOTUyOTYsNC40MzM3Miw3LjAyNDIzLDIuOTU1MjgsMTMuMTI3NjgsNy4wMjM5NCwxOC4zMTAzMSwxMi4yMDYwOGwxMzIuNTA4NzYsMTMyLjUwODc2YzUuMTgyMTQsNS4xODI2Miw5LjI1MDgsMTEuMjg2MDcsMTIuMjA2MDgsMTguMzEwMzEsMi45NTU4MSw3LjAyNDIzLDQuNDMzNzIsMTQuMzQxODcsNC40MzM3MiwyMS45NTI5NnYzNTMuNTAyNzdjMCwxNS45NTE2Mi01LjUyNjMzLDI5LjQ1Mzc2LTE2LjU3ODk5LDQwLjUwNjQyLTExLjA1MjY2LDExLjA1MjY1LTI0LjU1NDg0LDE2LjU3ODk4LTQwLjUwNjQxLDE2LjU3ODk5SDU3LjA4NTQxWk0yODQuMjExMjQsMTYwLjkyOTkzVjQ3LjM2Nzc3SDU3LjA4NTQxYy0yLjQyOTQ4LDAtNC42NTY1OCwxLjAxMjA5LTYuNjgxMzMsMy4wMzYzMy0yLjAyNDIsMi4wMjQ3Mi0zLjAzNjMyLDQuMjUxODYtMy4wMzYzMiw2LjY4MTM0djQ4NS44MjkxN2MwLDIuNDI5NDgsMS4wMTIxMiw0LjY1NjU5LDMuMDM2MzIsNi42ODEzMywyLjAyNDc1LDIuMDI0MjEsNC4yNTE4NSwzLjAzNjMyLDYuNjgxMzMsMy4wMzYzMkg0MTYuNTk4NDNjMi40Mjk0OCwwLDQuNjU2NjMtMS4wMTIxMSw2LjY4MTM0LTMuMDM2MzIsMi4wMjQyNC0yLjAyNDc0LDMuMDM2MzMtNC4yNTE4NSwzLjAzNjMzLTYuNjgxMzNWMTg5LjQ3MjYzaC0xMTMuNTYyMTFjLTguMTM3MzcsMC0xNC45Mjg3Mi0yLjcyMjg4LTIwLjM3NDAxLTguMTY4NjktNS40NDU4MS01LjQ0NTI4LTguMTY4NjktMTIuMjM2NjMtOC4xNjg3NC0yMC4zNzQwMVpNNDcuMzY3NzUsNDcuMzY3Nzd2MFoiLz48L3N2Zz4=';
  33. const downloadIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1OTkuOTk5OTIgNjAwIj48cGF0aCBkPSJNMjk5Ljk5OTk4LDQzNi40NjE0NWMtNC44MjA2NiwuMDAwMDMtOS4zMDc2OC0uNzY5MzUtMTMuNDYxMDQtMi4zMDgwMi00LjE1NDAxLTEuNTM4LTguMTAyNjYtNC4xNzkwMy0xMS44NDYwNS03LjkyMzAzbC0xMjQuMzg0NDEtMTI0LjM4MzRjLTUuOTQ4NjktNS45NDg2OS04Ljg4NDM3LTEyLjkxMDA1LTguODA3MDQtMjAuODg0MDcsLjA3NjY2LTcuOTc0MDMsMy4wMTIzNC0xNS4wNjM2OCw4LjgwNzA0LTIxLjI2OTA4LDYuMjA1MzQtNi4yMDQ2NywxMy4zMzMzOS05LjQwOTcsMjEuMzg0MDctOS42MTUwMiw4LjA1MTMzLS4yMDUzMiwxNS4xNzk3MSwyLjc5NDY5LDIxLjM4NTA4LDkuMDAwMDNsNzYuOTIzMjYsNzYuOTIzMjZWMzAuMDAwMWMwLTguNTEyNzIsMi44NzE2OC0xNS42NDA2OCw4LjYxNTAyLTIxLjM4NDA0LDUuNzQzMzctNS43NDQwNCwxMi44NzEzNS04LjYxNjA2LDIxLjM4NDA3LTguNjE2MDZzMTUuNjQwNzEsMi44NzIwMiwyMS4zODQwNyw4LjYxNjA2YzUuNzQzMzQsNS43NDMzNyw4LjYxNTAyLDEyLjg3MTMyLDguNjE1MDIsMjEuMzg0MDRWMzM2LjAwMjExbDc2LjkyMzI2LTc2LjkyMzI2YzUuOTQ4NjktNS45NDg2OSwxMy4wMTI2OC04Ljg4NDY3LDIxLjE5MjA5LTguODA4MDEsOC4xNzkzNSwuMDc3MzMsMTUuMzcxNjksMy4yMTgzMywyMS41NzcxLDkuNDIzLDUuNzk0Nyw2LjIwNTQsOC43OTQ0LDEzLjIzMTAzLDguOTk5MDUsMjEuMDc3MDYsLjIwNTMyLDcuODQ2MDMtMi43OTQzOCwxNC44NzEzOS04Ljk5OTA1LDIxLjA3NjA2bC0xMjQuMzg0NDQsMTI0LjM4MzQ2Yy0zLjc0MzMzLDMuNzQ0LTcuNjkyMDQsNi4zODUtMTEuODQ2MDUsNy45MjMwMy00LjE1MzM2LDEuNTM4NjctOC42NDAzOCwyLjMwODAyLTEzLjQ2MTA0LDIuMzA3OTlabS0yMjcuNjkxNzQsMTYzLjUzODUzYy0yMC4yMDUzOS0uMDAwMDItMzcuMzA4MTEtNy4wMDAwNC01MS4zMDgxNy0yMS4wMDAwN0M3LjAwMDA0LDU2NC45OTk4NSwuMDAwMDIsNTQ3Ljg5NzE0LDAsNTI3LjY5MTc1di03OC40NjEyN2MuMDAwMDItOC41MTI2OSwyLjg3Mi0xNS42NDA3MSw4LjYxNjAzLTIxLjM4NDA3LDUuNzQzMzctNS43NDMzNCwxMi44NzEzOC04LjYxNTAyLDIxLjM4NDA3LTguNjE1MDJzMTUuNjQwNzIsMi44NzE2OCwyMS4zODQwNyw4LjYxNTAyYzUuNzQzMzUsNS43NDMzNyw4LjYxNTAyLDEyLjg3MTM4LDguNjE1MDIsMjEuMzg0MXY3OC40NjEyNmMwLDMuMDc3MzYsMS4yODIsNS44OTgzNSwzLjg0NjAxLDguNDYzMDMsMi41NjQ2OCwyLjU2NCw1LjM4NTY3LDMuODQ2MDEsOC40NjMwMywzLjg0NjAxaDQ1NS4zODM0OGMzLjA3NzM0LDAsNS44OTg0LTEuMjgyLDguNDYzMDQtMy44NDYwMSwyLjU2NDAzLTIuNTY0NjgsMy44NDYwMi01LjM4NTY3LDMuODQ2MDItOC40NjMwM3YtNzguNDYxMjZjMC04LjUxMjcyLDIuODcxNjUtMTUuNjQwNzEsOC42MTUwMi0yMS4zODQwNyw1Ljc0MzM3LTUuNzQzMzQsMTIuODcxMzgtOC42MTQ5OSwyMS4zODQwNC04LjYxNTAyLDguNTEyNzIsLjAwMDAzLDE1LjY0MDc0LDIuODcxNjgsMjEuMzg0MDQsOC42MTUwMiw1Ljc0NDA0LDUuNzQzMzcsOC42MTYwNiwxMi44NzEzNSw4LjYxNjA2LDIxLjM4NDA3djc4LjQ2MTI2YzAsMjAuMjA1NC03LjAwMDAyLDM3LjMwODEyLTIxLjAwMDA3LDUxLjMwODE3LTE0LjAwMDA1LDE0LjAwMDA1LTMxLjEwMjc2LDIxLjAwMDA3LTUxLjMwODE1LDIxLjAwMDA3bC00NTUuMzgzNDctLjAwMDAyWiIvPjwvc3ZnPg==';
  34. const settingsIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1NjYuODk3MzMgNjAwIj48cGF0aCBkPSJNMjQ0LjY2NjE0LDU5OS45OTk5NGMtNi42MjM4OSwwLTEyLjM1MDI4LTIuMjQzNjEtMTcuMTc5MTYtNi43MzA4My00LjgyODg3LTQuNDg3MjItNy43OTg4OS0xMC4wNDI3Ny04LjkwOTk5LTE2LjY2NjY2bC05LjM1OTE2LTczLjAxMjQ4Yy0xMC42NDExLTMuMjA0OTktMjIuMTQ3NDktOC4yNDc3Ny0zNC41MTkxNy0xNS4xMjgzMi0xMi4zNzE2Ny02Ljg4MDU3LTIyLjg5NTMtMTQuMjUyMjItMzEuNTcwODQtMjIuMTE0OTlsLTY2LjczMDgyLDI4LjcxNzVjLTYuNDk1NTUsMi45MDYxMy0xMi44ODQ0MywzLjIxNjExLTE5LjE2NjY2LC45My02LjI4MTY3LTIuMjg2NjctMTEuMjE3NS02LjQwMDAxLTE0LjgwNzUtMTIuMzQwMDFMMy44MzI4Niw0MTYuNTM4M2MtMy4xNjIyMi01LjkzOTk5LTQuMTIzNjEtMTIuMjIxOTMtMi44ODQxNy0xOC44NDU4MiwxLjIzODg5LTYuNjIzODksNC41NTA4My0xMi4wMDg2MSw5LjkzNTg0LTE2LjE1NDE3bDU4LjAxMjQ5LTQzLjY1NDE3Yy0uOTgyNzgtNi4wMjU1Ny0xLjc5NDczLTEyLjIzMjc5LTIuNDM1ODQtMTguNjIxNjctLjY0MTExLTYuMzg4ODgtLjk2MTY3LTEyLjU5NjEtLjk2MTY3LTE4LjYyMTY3LDAtNS41OTgzMiwuMzIwNTYtMTEuNDg1MDEsLjk2MTY3LTE3LjY1OTk5LC42NDExMS02LjE3NSwxLjQ1MzA2LTEzLjEzMDAxLDIuNDM1ODQtMjAuODY0OTlMMTAuODg0NTMsMjE4LjQ2MTY0Yy01LjM4NDk5LTQuMTQ1NTEtOC44MDM4OC05LjUzMDIzLTEwLjI1NjY2LTE2LjE1NDE3LTEuNDUyNzgtNi42MjM4OS0uMzg0NDUtMTIuOTA1ODMsMy4yMDQ5OS0xOC44NDU4Mkw0Mi40MjI4NiwxMTcuNjI4MzFjMy41OS01Ljk0MDU1LDguNDE5MTYtMTAuMDUzODYsMTQuNDg3NDktMTIuMzM5OTgsNi4wNjgzNC0yLjI4NjY4LDEyLjM1MDI4LTEuOTc2OTgsMTguODQ1ODQsLjkyOTE2bDY2LjczMDg0LDI4LjA3NzQ5YzkuOTU3MjItOC4yOTA1NiwyMC43MjYzOS0xNS43NjkxNCwzMi4zMDc1MS0yMi40MzU4MSwxMS41ODEwOS02LjY2NjY3LDIyLjg0MTk1LTExLjgxNjQsMzMuNzgyNS0xNS40NDkxN2wxMC03My4wMTI0OGMxLjExMTEyLTYuNjIzODQsNC4wODExMi0xMi4xNzk0MSw4LjkwOTk5LTE2LjY2NjY2LDQuODI4OS00LjQ4NzIsMTAuNTU1MjctNi43MzA4NSwxNy4xNzkxMy02LjczMDg1aDc2LjkyMzMxYzYuNjI0NDUsMCwxMi40NTc3OCwyLjI0MzY1LDE3LjUsNi43MzA4NSw1LjA0Mjc3LDQuNDg3MjUsOC4xMTk3NiwxMC4wNDI4Myw5LjIzMDg1LDE2LjY2NjY2bDkuMzU5MTgsNzMuNjUzMzVjMTIuNzc3NzYsNC40ODcyLDI0LjA3MDUzLDkuNjM2OTQsMzMuODc4MzIsMTUuNDQ5MTcsOS44MDc3NCw1LjgxMTY3LDE5LjkwMzg3LDEzLjA3NjY4LDMwLjI4ODM0LDIxLjc5NDk5bDY5LjI5NDk5LTI4LjA3NzQ5YzYuNDk1NTYtMi45MDYxNCwxMi43Nzc1MS0zLjMyMjgsMTguODQ1ODItMS4yNSw2LjA2ODMyLDIuMDcyOCwxMC44OTc1Miw2LjA3OTE1LDE0LjQ4NzUxLDEyLjAxOTE0bDM4LjU4OTk4LDY2LjQ3NTAxYzMuNTg5NDgsNS45Mzk5OSw0LjY1NzgsMTIuMjIxOTMsMy4yMDUwMSwxOC44NDU4Mi0xLjQ1Mjc5LDYuNjIzODktNC44NzE2MiwxMi4wMDg2MS0xMC4yNTY2NSwxNi4xNTQxN2wtNjAuNTc2NjcsNDUuNTc2NjhjMS44Mzc3Nyw2Ljg4MDU0LDIuODYzMzEsMTMuMTk0NzEsMy4wNzY2OCwxOC45NDI0OSwuMjEzODgsNS43NDc3OCwuMzIwODksMTEuNDIwODUsLjMyMDg0LDE3LjAxOTE3LC4wMDAwNSw1LjE3MTEzLS4yMTM1NywxMC42MzA1Ny0uNjQwODIsMTYuMzc4MzItLjQyNzgxLDUuNzQ3NzgtMS40MTA4OCwxMi43MDI3Ni0yLjk0OTE3LDIwLjg2NDk5bDU5LjI5NDk5LDQ0LjI5NDk5YzUuMzg0NDIsNC4xNDU1Niw4LjgwMzM1LDkuNTMwMjgsMTAuMjU2NjUsMTYuMTU0MTcsMS40NTI3OSw2LjYyMzg5LC4zODQ0MiwxMi45MDU4My0zLjIwNTAxLDE4Ljg0NTgybC0zOC41ODk5OCw2Ni45MjMzNGMtMy41ODk5OSw1Ljk0LTguNTU4MDQsOS45Nzg2LTE0LjkwNDE3LDEyLjExNTgzLTYuMzQ2MDgsMi4xMzY2NS0xMi43NjY5OCwxLjc1MTk1LTE5LjI2MjQ5LTEuMTU0MTZsLTY2Ljk4NzUtMjguNzE4MzJjLTEwLjM4NDQ3LDguNzE4MzQtMjAuODMzMDgsMTYuMTk2OTItMzEuMzQ1ODIsMjIuNDM1ODMtMTAuNTEyNzUsNi4yMzk0NS0yMS40NTMwNCwxMS4xNzU1Ni0zMi44MjA4NCwxNC44MDgzNGwtOS4zNTkxOCw3My42NTMzM2MtMS4xMTEwOSw2LjYyMzg5LTQuMTg4MDgsMTIuMTc5NDQtOS4yMzA4NSwxNi42NjY2Ni01LjA0MjIyLDQuNDg3MjItMTAuODc1NTUsNi43MzA4NC0xNy41LDYuNzMwODNsLTc2LjkyMzMxLS4wMDAwNlptNS40NDkxNy0zMy4zMzMzM2g2NS4xOTI1MWwxMi4zMDc0OC05MC4yNTY2N2MxNi43OTQ5OS00LjQ0NDQ1LDMxLjkxMjQ4LTEwLjU0NDcxLDQ1LjM1MjQ3LTE4LjMwMDgzLDEzLjQzOTk5LTcuNzU2NjgsMjcuMTI1OC0xOC4zODY5NCw0MS4wNTc0OC0zMS44OTA4NGw4My4xNDE2NywzNS40NDgzNSwzMy4xNDA4MS01Ni42NjY2Ni03Mi45NDkxNi01NC44MDc0OGMyLjc3NzgxLTkuNDg3MjMsNC42MTU1OC0xOC4yMTU4MSw1LjUxMzM2LTI2LjE4NTgzLC44OTcxNy03Ljk3LDEuMzQ1ODgtMTUuOTcyMjEsMS4zNDU4My0yNC4wMDY2OCwuMDAwMDUtOC40NjE2My0uNDQ4NjYtMTYuNDYzOS0xLjM0NTgzLTI0LjAwNjY4LS44OTc3OC03LjU0Mjc1LTIuNzM1NTQtMTUuODQzODktNS41MTMzNi0yNC45MDMzM2w3NC4yMzA4NS01Ni4wODk5OC0zMy4xNDA4MS01Ni42NjY2Ni04NS4wNjQxOCwzNS42NDA4MWMtMTAuMDg1NTUtMTEuMDY4MzItMjMuMzQ0MTYtMjEuNDQyMjEtMzkuNzc1ODQtMzEuMTIxNjctMTYuNDMxNjgtOS42Nzk0Ni0zMS45NzY0Mi0xNi4xMDAzMS00Ni42MzQxNi0xOS4yNjI0OWwtMTAuMTkyNDYtOTAuMjU2NjRoLTY2LjQ3NDE0bC0xMC4zODUsODkuNjE1MDFjLTE2Ljc5NDk5LDMuNTg5OTktMzIuMjMzMDQsOS4zNjk5Ni00Ni4zMTQxNiwxNy4zMzk5OC0xNC4wODExMSw3Ljk2OTk3LTI4LjA4NzQ5LDE4LjkyMDg1LTQyLjAxOTE3LDMyLjg1MjQ3bC04My4xNDA4My0zNC44MDc0OC0zMy4xNDA4Myw1Ni42NjY2Niw3Mi4zMDc0OSw1My45NzQxNWMtMi43Nzc3OSw3LjQ3ODg5LTQuNzIyMjEsMTUuNTk4Ni01LjgzMzMzLDI0LjM1OTE4LTEuMTExMTIsOC43NjA1OC0xLjY2NjY3LDE3Ljg2MzA2LTEuNjY2NjcsMjcuMzA3NTEsMCw4LjQ2MTY2LC41NTU1NSwxNi44NTkxNSwxLjY2NjY3LDI1LjE5MjQ5LDEuMTExMTIsOC4zMzMzMywyLjg0MTkyLDE2LjQ1MzA0LDUuMTkyNDksMjQuMzU5MTVsLTcxLjY2NjY2LDU0LjgwNzUsMzMuMTQwODQsNTYuNjY2NjYsODIuNDk5OTktMzVjMTMuMDc2NjUsMTMuMjA1MDEsMjYuNjU1OCwyMy43OTI0OSw0MC43Mzc1LDMxLjc2MjQ5LDE0LjA4MTExLDcuOTcwNTUsMjkuOTQ2MzksMTQuMTc4MDMsNDcuNTk1ODIsMTguNjIyNDlsMTAuODMzMzMsODkuNjE1MDFabTMyLjQzNTgzLTE4My4zMzMzMWMyMy4yNDc3NSwwLDQyLjk0ODYzLTguMDc2OTYsNTkuMTAyNS0yNC4yMzA4MywxNi4xNTM5Mi0xNi4xNTM4OSwyNC4yMzA4NS0zNS44NTQ3MiwyNC4yMzA4NS01OS4xMDI1cy04LjA3NjkzLTQyLjk0ODYtMjQuMjMwODUtNTkuMTAyNDdjLTE2LjE1Mzg3LTE2LjE1MzkyLTM1Ljg1NDc0LTI0LjIzMDg1LTU5LjEwMjUtMjQuMjMwODUtMjMuMzc2MTEsMC00My4xMDkxNSw4LjA3NjkzLTU5LjE5OTE2LDI0LjIzMDg1LTE2LjA4OTQ1LDE2LjE1MzkyLTI0LjEzNDE2LDM1Ljg1NDcyLTI0LjEzNDE2LDU5LjEwMjVzOC4wNDQ3MSw0Mi45NDg2LDI0LjEzNDE2LDU5LjEwMjVjMTYuMDkwMDEsMTYuMTUzODksMzUuODIzMDYsMjQuMjMwOCw1OS4xOTkxNiwyNC4yMzA4WiIvPjwvc3ZnPg==';
  35. const contributeIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgNjAwLjAwMDAxIj48cGF0aCBkPSJNMjU1LjE4MjI3LDM2Ny43NzQxM2wtNzMuMzYxMjUtNzMuMzYwNDZjLTQuMzcyMTQtNC4zNzI2Ny05Ljg2NzkyLTYuNjA5NS0xNi40ODc0MS02LjcxMDU0LTYuNjE5NS0uMTAxNTgtMTIuMjE2NjEsMi4xMzUyOC0xNi43OTEzNyw2LjcxMDU0LTQuNTc0NzYsNC41NzQ3My02Ljg2MjExLDEwLjEyMTA5LTYuODYyMTEsMTYuNjM4OThzMi4yODczNSwxMi4wNjQyMiw2Ljg2MjExLDE2LjYzODk4bDg2LjY1OTk3LDg2LjY1OTk3YzUuNzA4NDUsNS43MDg0NSwxMi4zNjg0NSw4LjU2MjY2LDE5Ljk4MDA2LDguNTYyNjYsNy42MTEwOSwwLDE0LjI3MDg0LTIuODU0MjEsMTkuOTc5MjctOC41NjI2NmwxNzUuNjg4MzUtMTc1LjY4ODMzYzQuMzcyNjctNC4zNzIxNCw2LjYwOTUtOS44Njc5Miw2LjcxMDU0LTE2LjQ4NzM5LC4xMDE1OC02LjYxOTUyLTIuMTM1MjYtMTIuMjE2NjQtNi43MTA1NC0xNi43OTEzNS00LjU3NDc2LTQuNTc0NzYtMTAuMTIxMDktNi44NjIxNC0xNi42Mzg5OC02Ljg2MjE0cy0xMi4wNjQyMiwyLjI4NzM4LTE2LjYzODk4LDYuODYyMTRsLTE2Mi4zODk2NiwxNjIuMzg5NThabTQ0Ljg3MDY0LDIzMi4yMjU4OGMtNDEuNDkyNzUsMC04MC40OTM5MS03Ljg3MzcxLTExNy4wMDM0Ny0yMy42MjExMS0zNi41MTAxLTE1Ljc0NzQxLTY4LjI2ODYxLTM3LjExODUyLTk1LjI3NTUyLTY0LjExMzMzLTI3LjAwNzQ0LTI2Ljk5NTMyLTQ4LjM4ODI5LTU4LjczOTg4LTY0LjE0MjU0LTk1LjIzMzY3QzcuODc3MTMsMzgwLjUzODYyLDAsMzQxLjU0NTYzLDAsMzAwLjA1MjljMC00MS40OTI3NSw3Ljg3MzcxLTgwLjQ5Mzg4LDIzLjYyMTExLTExNy4wMDM0NywxNS43NDc0MS0zNi41MTAxMiwzNy4xMTg1Mi02OC4yNjg2LDY0LjExMzMyLTk1LjI3NTUyLDI2Ljk5NTMzLTI3LjAwNzQ1LDU4LjczOTg4LTQ4LjM4ODI1LDk1LjIzMzY3LTY0LjE0MjU0QzIxOS40NjEzNiw3Ljg3NzE3LDI1OC40NTQzNSwwLDI5OS45NDcxLDBzODAuNDkzODgsNy44NzM3LDExNy4wMDM0NywyMy42MjExYzM2LjUxMDEyLDE1Ljc0NzQsNjguMjY4NjQsMzcuMTE4NTYsOTUuMjc1NTIsNjQuMTEzMzQsMjcuMDA3NDUsMjYuOTk1MzYsNDguMzg4Myw1OC43Mzk5MSw2NC4xNDI1NCw5NS4yMzM2OSwxNS43NTQyNCwzNi40OTMyNiwyMy42MzEzNiw3NS40ODYyNSwyMy42MzEzNiwxMTYuOTc5cy03Ljg3MzcsODAuNDkzOTEtMjMuNjIxMSwxMTcuMDAzNDdjLTE1Ljc0NzQsMzYuNTEwMS0zNy4xMTg1Miw2OC4yNjg2MS02NC4xMTMzNCw5NS4yNzU1Mi0yNi45OTUzMSwyNy4wMDc0NC01OC43Mzk5MSw0OC4zODgyOS05NS4yMzM2NSw2NC4xNDI1NC0zNi40OTMyNiwxNS43NTQyNS03NS40ODYyNSwyMy42MzEzOC0xMTYuOTc5LDIzLjYzMTM0Wm0tLjA1Mjg4LTQ3LjM2Nzc1YzcwLjUyNjQ5LDAsMTMwLjI2MzUtMjQuNDczNzUsMTc5LjIxMS03My40MjEyNSw0OC45NDc1LTQ4Ljk0NzUsNzMuNDIxMjUtMTA4LjY4NDQ5LDczLjQyMTI1LTE3OS4yMTFzLTI0LjQ3Mzc1LTEzMC4yNjM1LTczLjQyMTI1LTE3OS4yMTEtMTA4LjY4NDUxLTczLjQyMTI1LTE3OS4yMTEtNzMuNDIxMjUtMTMwLjI2MzUsMjQuNDczNzUtMTc5LjIxMSw3My40MjEyNWMtNDguOTQ3NSw0OC45NDc1LTczLjQyMTI1LDEwOC42ODQ1MS03My40MjEyNSwxNzkuMjExczI0LjQ3Mzc1LDEzMC4yNjM1LDczLjQyMTI1LDE3OS4yMTFjNDguOTQ3NSw0OC45NDc1LDEwOC42ODQ0OSw3My40MjEyNSwxNzkuMjExLDczLjQyMTI1WiIvPjwvc3ZnPg==';
  36. const dontContributeIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1OTkuOTk5OTggNjAwIj48cGF0aCBkPSJNMzAwLjA1MjksNjAwYy00MS40OTI3NSwwLTgwLjQ5MzktNy44NzM3MS0xMTcuMDAzNDctMjMuNjIxMTItMzYuNTEwMS0xNS43NDc0MS02OC4yNjg2MS0zNy4xMTg1MS05NS4yNzU1Mi02NC4xMTMzMy0yNy4wMDc0NC0yNi45OTUzMi00OC4zODgyOS01OC43Mzk4OC02NC4xNDI1NC05NS4yMzM2N0M3Ljg3NzEzLDM4MC41Mzg2LDAsMzQxLjU0NTYyLDAsMzAwLjA1Mjg5YzAtNDEuNDkyNzUsNy44NzM3MS04MC40OTM4OCwyMy42MjExMS0xMTcuMDAzNDcsMTUuNzQ3NDEtMzYuNTEwMTIsMzcuMTE4NTEtNjguMjY4NTksNjQuMTEzMzItOTUuMjc1NTIsMjYuOTk1MzMtMjcuMDA3NDUsNTguNzM5ODgtNDguMzg4MjUsOTUuMjMzNjctNjQuMTQyNTRDMjE5LjQ2MTM1LDcuODc3MTcsMjU4LjQ1NDM0LDAsMjk5Ljk0NzA5LDBzODAuNDkzODgsNy44NzM3LDExNy4wMDM0NywyMy42MjExYzM2LjUxMDEyLDE1Ljc0NzQsNjguMjY4NjQsMzcuMTE4NTYsOTUuMjc1NTIsNjQuMTEzMzQsMjcuMDA3NDUsMjYuOTk1MzYsNDguMzg4Myw1OC43Mzk5MSw2NC4xNDI1NCw5NS4yMzM2OSwxNS43NTQyNCwzNi40OTMyNiwyMy42MzEzNiw3NS40ODYyNCwyMy42MzEzNiwxMTYuOTc4OTlzLTcuODczNyw4MC40OTM5LTIzLjYyMTEsMTE3LjAwMzQ3Yy0xNS43NDc0LDM2LjUxMDEtMzcuMTE4NTEsNjguMjY4NjEtNjQuMTEzMzQsOTUuMjc1NTItMjYuOTk1MzEsMjcuMDA3NDQtNTguNzM5OTEsNDguMzg4MjktOTUuMjMzNjQsNjQuMTQyNTQtMzYuNDkzMjYsMTUuNzU0MjUtNzUuNDg2MjQsMjMuNjMxMzgtMTE2Ljk3ODk5LDIzLjYzMTM1Wm0tLjA1Mjg4LTQ3LjM2Nzc2YzI5LjYyNzk0LDAsNTguMTU4NTQtNS4wMTAyNyw4NS41OTE4MS0xNS4wMzA4MywyNy40MzMyMi0xMC4wMjAwMyw1Mi41MDYxNi0yNC41MjQwMSw3NS4yMTg4Ni00My41MTE5NkwxMDUuOTEwNTcsMTM5LjE4OTMzYy0xOC43ODUzMiwyMi43MTI3LTMzLjIzODc2LDQ3Ljc4NTY0LTQzLjM2MDM4LDc1LjIxODg2LTEwLjEyMTYsMjcuNDMzMjItMTUuMTgyNDEsNTUuOTYzODMtMTUuMTgyNDEsODUuNTkxODEsMCw3MC41MjY1MSwyNC40NzM3NSwxMzAuMjYzNSw3My40MjEyNCwxNzkuMjEwOTksNDguOTQ3NSw0OC45NDc1LDEwOC42ODQ0OSw3My40MjEyNCwxNzkuMjEwOTksNzMuNDIxMjRabTE5NC4wODk0Ni05MS44MjE1NmMxOC45ODc5OS0yMi43MTI2OCwzMy40OTE5Ni00Ny43ODU2NCw0My41MTE5NS03NS4yMTg4OSwxMC4wMjA1Mi0yNy40MzMyMiwxNS4wMzA4My01NS45NjM4MywxNS4wMzA4My04NS41OTE3OSwwLTcwLjUyNjQ4LTI0LjQ3Mzc1LTEzMC4yNjM1LTczLjQyMTI0LTE3OS4yMTA5OXMtMTA4LjY4NDUxLTczLjQyMTI0LTE3OS4yMTA5OS03My40MjEyNGMtMjkuNjk5MDEsMC01OC4yOTgwNCw0Ljk1OTQ3LTg1Ljc5NzA2LDE0Ljg3ODQ3LTI3LjQ5OTA0LDkuOTE5NDgtNTIuNTAzNTYsMjQuNDc0MjgtNzUuMDEzNjEsNDMuNjY0MzFMNDk0LjA4OTQ4LDQ2MC44MTA2OFoiLz48L3N2Zz4=';
  37. const shadowIcon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1ODkuODEyMjYgNTkwLjIwNDEiPjxwYXRoIGQ9Ik01NzYuMzE4MzYsMjk3LjU3NTU2aC0uMTk1OTJjLTcuMDQwODMsLjExMDE3LTEyLjg4MTU5LDUuNzA2MTItMTMuMjg1NzEsMTIuNzM0NjItLjYwMDIyLDExLjAwOTk1LTEuODg2OSwyMS45NTU4MS0zLjgzMDU3LDMyLjc3ODkzLTIuNjk1MzcsMTUuMDA4NTQtNi42NjI3MiwyOS43Nzk0Mi0xMS44OTE4NSw0NC4xNDM1NS0uNTAyMDgsMS40NDQ4OS0uNzcxNDIsMi45NjMyNi0uNzcxNDIsNC40ODE2MywwLC41NTY1MiwuMDQ1MzUsMS4xMDIzNiwuMTEyMjQsMS42NDIwMywuODE5NTIsNi42MDg3LDYuNDkzMjMsMTEuODA0NjksMTMuMzA4MTcsMTEuODI3MzMsNS42ODE2NC0uMDEyMjEsMTAuNzYzMjQtMy42MjQ1MSwxMi42NDg5My04Ljk3NTUyLC4wMTIyNy0uMDEyMjEsLjAxMjI3LS4wMjQ0OCwuMDI0NTQtLjA0ODk1LDQuNzk4NC0xMy4xNTg1MSw4LjYzODM3LTI2LjYyNzc1LDExLjUxNDQ3LTQwLjI5ODk1LDMuMDE0MzQtMTQuMzI4MjUsNC45NjUyMS0yOC44Nzg5Nyw1LjgxNzYzLTQzLjUzMzg3LC4wMDkxNi0uMTU3OSwuMDIyMjItLjMxNTQzLC4wMzExMy0uNDczMzNsLjAxMjI3LS43NzE0MmMwLTcuNDA4MTQtNi4wODU2OS0xMy41MDYwNC0xMy40OTM5LTEzLjUwNjA0WiIvPjxwYXRoIGQ9Ik01MjUuOTY2ODYsNDUxLjEyODM2Yy0xLjYzOC0uNzE0NTQtMy40MzgyOS0xLjExNjA5LTUuMzI1OTktMS4xMTYwOS00LjMxMDI0LDAtOC4zNzU1NSwyLjA2OTQtMTAuOTEwMjgsNS41NzE0MS0uMDI0NDgsLjAzNjc0LS4wNjExNiwuMDczNDktLjA4NTY5LC4xMTAyMy01LjU0Njk0LDcuMTg3NzQtMTEuNDQ4OTcsMTQuMDgxNi0xNy42ODE2NCwyMC42NTcxLTEuMDA0MDMsMS4wNTMwNC0yLjQxMjIzLDEuNjA0MTMtMy44NDQ5MSwxLjUxODM3LTcuOTk5MTUtLjQ3MzM5LTE1Ljg5NzUyLTEuMzE4ODUtMjMuNjkxNzEtMi40ODQ1Ni0xMC41OTI3MS0xLjU4NDI5LTIwLjk4MDgzLTMuNzkyOTctMzEuMTI5NTgtNi41ODY2Ny05LjUyNTc2LTIuNjIyMTktMTguODQxLTUuNzUyODctMjcuOTExMzgtOS4zNzIzOC04LjgzODMyLTMuNTI2OTItMTcuNDQzNi03LjUxMzE4LTI1Ljc5MTE0LTExLjkyNTA1LTguMDQxNDQtNC4yNTAxMi0xNS44NDY1Ni04Ljg4OC0yMy4zODAxMy0xMy45MDM2OS03LjQ5NjctNC45OTEyMS0xNC43MjA5NS0xMC4zNTY5My0yMS42NjM4OC0xNi4wNTIzMS02LjgxMDc5LTUuNTg3MDQtMTMuMzQyNzEtMTEuNDk4MjMtMTkuNTcyMjctMTcuNzExNTUtNi4zMDM5Ni02LjI4NzU0LTEyLjMwNjctMTIuODczNjYtMTcuOTY2MDYtMTkuNzUwMTgtNS42NDI2NC02Ljg1NjE0LTEwLjk0NDc2LTEzLjk5NzAxLTE1Ljg5NzM0LTIxLjM4NjQxLTUuMDk2NjgtNy42MDQ0OS05LjgxMTE2LTE1LjQ3ODc2LTE0LjEyNDIxLTIzLjU5MTk4LTQuMzc5MjEtOC4yMzc0OS04LjM0Nzk2LTE2LjcxNzQxLTExLjg2MzU5LTI1LjQyMDIzLTMuNjk2NjYtOS4xNTA3Ni02Ljg5NzIyLTE4LjU0MzAzLTkuNTc1NDQtMjguMTQwNzUtMi43OTMwMy0xMC4wMDg5MS01LjAxMDA3LTIwLjI0MjU1LTYuNjIzMTctMzAuNjYwNjQtMS43NTcxNC0xMS4zNDg1MS0yLjgwMDg0LTIyLjkxMzMzLTMuMDY2MTYtMzQuNjUwMDktLjA0NTQ3LTIuMDExOTYtLjA3NDUyLTQuMDI3NTktLjA3NDUyLTYuMDQ5MTksMC0xMS4xNjg4OCwuNzEzNjgtMjIuMjY4ODYsMi4wODYzLTMzLjI0NjM0LDIuMDYwMTItMTYuNDc2MTQsNS42Mzk1OS0zMi42Njc0OCwxMC42NjExOS00OC4zNzczOCw4LjU1ODUzLTI2Ljc3NDksMjEuMjkwNDctNTIuMTQ5MzUsMzcuODM1NTctNzUuMTE5MzgsNi4wODg1LTguNDUyODIsMTIuNjkwMjUtMTYuNTgxMywxOS43ODgzMy0yNC4zMzQ0NywuOTkxODgtMS4wODk3OCwyLjQxMjI5LTEuNjY1MzQsMy44ODE2NS0xLjU5MTg2LC42NDIzMywuMDM0NzMsMS4zNTgwOSwuMDgwOTksMi4xMjEzNCwuMTM1MDEsOS43Mjc0OCwuNjg4ODQsMjguMjE2OCwyLjgxNjQ3LDI4LjYyNTYxLDMuMTM0NCw3LjE5OTk1LS4yNjk0MSwxMy4wMjg1Ni02LjI1NzE0LDEzLjAyODU2LTEzLjUxODM3LDAtNy4wMjg1Ni01LjQ4NTcyLTEyLjk0Mjg3LTEyLjQ4OTgxLTEzLjQ4MTYzLS4xMjI0NC0uMDEyMjctLjIzMjY3LS4wMjQ0OC0uMzU1MS0uMDM2NzQtMS40MjgwNC0uMjE2NDktMi44NTc2Ny0uNDIyNTUtNC4yODg2NC0uNjE4MjktOS45ODAyMi0xLjM2NTE3LTIwLjAyODI2LTIuMjI1NzEtMzAuMDk1MDMtMi41ODk5LS4zNTUxLS4wMTIyMS0uNjk3OTQtLjA2MTIyLTEuMDQwODMtLjE0NjkxLS44MzI2NC0uMjA4MTktMS42ODk3Ni0uMzQyODMtMi41NTkxNC0uMzkxODVoLTcuODg1NzRjLTEwLjgyOTI4LDAtMjEuNTI0OSwuNjE0NzUtMzIuMDY2MjIsMS43NzU2My0xNi4wMDI1NiwxLjc2MjI3LTMxLjYzNjg0LDQuODIyMDItNDYuNzk0MjUsOS4wNzgtMjIuMzEyOTMsNi4yNjUyLTQzLjU4NzA0LDE1LjExNTcyLTYzLjQ4MjEyLDI2LjE5ODM2LTQ4LjQ2MzIsMjYuOTk2Ny04OC43MTA2Myw2Ny4yNDQxNC0xMTUuNzA3MzQsMTE1LjcwNzM0LTExLjA4MjcsMTkuODk1MTQtMTkuOTMzMjksNDEuMTY5MzEtMjYuMTk4NDksNjMuNDgyMy00LjI1NTk4LDE1LjE1NzQxLTcuMzE1NzMsMzAuNzkxNjMtOS4wNzgsNDYuNzk0MTktMS4xNjA4OSwxMC41NDEzMi0xLjc3NTYzLDIxLjIzNjk0LTEuNzc1NjMsMzIuMDY2MjIsMCwyLjMwODA0LC4wMzQ4NSw0LjYwODQ2LC4wODg2OCw2LjkwNDU0LC4yNzYyNSwxMS43NzY5OCwxLjI3MSwyMy4zODc3LDIuOTE1MDQsMzQuODAxMTUsMS41MTg0MywxMC41NDEyLDMuNTg3NTIsMjAuOTE0MTIsNi4yMDU2MywzMS4wNzgxOSwyLjUxNjc4LDkuNzcwNjksNS41MjUzOSwxOS4zNTIzNiw5LjAwMDA2LDI4LjcxNjEzLDMuMzA3NjgsOC45MTM3LDcuMDMyOTYsMTcuNjMxNDcsMTEuMTU3OTYsMjYuMTI1ODUsNC4wNTkzOSw4LjM1OTEzLDguNTA2MSwxNi41MDA5MiwxMy4zMDk2MywyNC40MDY1Niw0LjY1OTEyLDcuNjY4MDMsOS42NjYxNCwxNS4xMDQyNSwxNC45ODE3NSwyMi4zMDIwNiw1LjMxNjQxLDcuMTk4ODUsMTAuOTUxNjYsMTQuMTQ4NzQsMTYuODgxODQsMjAuODM0MzUsNS44MzU1MSw2LjU3ODg2LDExLjk1MDkzLDEyLjkwMzY5LDE4LjMzOTQ4LDE4Ljk0NDM0LDYuNDc2MjYsNi4xMjM0MSwxMy4yMTk5MSwxMS45NjYwNiwyMC4yMjIxNywxNy40OTQwMiw2Ljk4NDgsNS41MTQyOCwxNC4yMjgyNywxMC43MTAyNywyMS42OTQxNSwxNS41ODk2Niw3LjY3NTYsNS4wMTY0OCwxNS41OTQ5Nyw5LjY4MjM3LDIzLjczMzcsMTMuOTgyNDgsOC4yNDI5Miw0LjM1NTE2LDE2LjcxMDYzLDguMzI5NzEsMjUuMzgxMjMsMTEuOTAyNTksOS4wNzI2OSwzLjczODY1LDE4LjM2NTA1LDcuMDM1MSwyNy44NTI0OCw5Ljg2MzcxLDkuODE1MTksMi45MjYyNywxOS44MzM2OCw1LjM1Nzk3LDMwLjAzMzE0LDcuMjUwNjcsMTAuOTc0MTIsMi4wMzY1LDIyLjE1NDI0LDMuNDQ4NjEsMzMuNTAwNDMsNC4yMTU3Niw2LjU1MDE3LC40NDI4NywxMy4xNTAzOSwuNjksMTkuODA0NjksLjY5LDUuNzkzNTIsMCwxMS41NjY3MS0uMTkxMjgsMTcuMzE4NzktLjUyOTcyLDE0LjcxNjEzLS44NjU5NywyOS4yNzI1Mi0yLjgyODYxLDQzLjU1OTk0LTUuODQzNjksMTguNjY5MzEtMy45Mzk4MiwzNi44NzcyNi05LjY2Mzc2LDU0LjM2OTM4LTE3LjA4NTU3LDM1LjU2MTQ2LTE1LjA4ODUsNjguMTcyNzktMzcuMTQ0MjMsOTUuNzA2OTctNjUuMjkyMDVsMi4wMjA0NS0yLjQ5NzkyYzguMjY1MzItOC41ODM2OCwxNi4wMDQwOS0xNy42NTcxNywyMy4xNjczLTI3LjE3MTQ1LC4wMTIyNy0uMDEyMjcsLjAyNDU0LS4wMzY3NCwuMDM2OC0uMDQ4OTUsMS44MzY2Ny0yLjM2MzI4LDIuODI4NTUtNS4yNjUzMiwyLjgyODU1LTguMjUzMTEsMC01LjUwNTA3LTMuMzc0MzktMTAuMjcyODktOC4xNDMzNy0xMi4zNTMyN1pNMTY4LjQ5NDA4LDU4LjYwMTE0TDU4LjY5Nzk0LDE2OC4zOTczNGMyNC45NjAwMi00Ni4yNzczNCw2My4xNjE2OC04NC43MDY0MiwxMDkuNzk2MTQtMTA5Ljc5NjJaTTM0LjcwNzE1LDIzMC4xMDQzMUwyMzAuMDM2NDQsMzQuNzc1MDJjOS44NTQzNy0yLjQ2MTA2LDE5LjkzMjA3LTQuMzgxMzUsMzAuMjA0NDEtNS43MTc5LDEuOTM0NjktLjI1NzE0LDMuODQ0OTEsLjY3MzUyLDQuODM2NzMsMi4zNTEwNywxLjAwNDA5LDEuNjg5NzYsLjkwNjEzLDMuODA4MTEtLjI0NDg3LDUuMzg3Ny0uMzg5MTYsLjUzNTY0LS43NjUyNiwxLjA3OTIyLTEuMTUwNTcsMS42MTcxOUwyNy40NTg1NiwyNzQuNjM2NzJjMS4xNjEzMi0xNS4xOTY3MiwzLjYxMzE2LTMwLjA3OTEsNy4yNDg2LTQ0LjUzMjQxWm0tNy40Mzg2LDgyLjQzODZMMjI0LjAwODMsMTE1LjgwMzE2Yy01LjQyNTE3LDE2LjA1MTMzLTkuNDcxOTgsMzIuNTYyODEtMTIuMDczNzksNDkuMzU3NkwzMS41NDEyLDM0NS41NTQwOGMtMi4wOTU3LTEwLjc5NjUxLTMuNTMzODctMjEuODEzOTYtNC4yNzI2NC0zMy4wMTExN1ptMTEuOTQ4MTIsNjMuMDUxODhMMjA4LjQ4NDgsMjA2LjMyNjY2Yy0uMDE4NDMsMS4zNDY1LS4wMzk5MiwyLjY5MjY5LS4wMzk5Miw0LjA0MDcxLDAsMTAuNjQ0MTcsLjU4ODUsMjEuMTc2NjQsMS43MTE1NSwzMS41NzE0N0w0OS40OTQyNiw0MDIuNjAxMDFjLTMuODkzMjUtOC43NzI0LTcuMzMyNzYtMTcuNzgyNDEtMTAuMjc3NTktMjcuMDA2MjNabTIyLjk3MzM5LDUyLjAyNjYxbDE1My4zMTE3MS0xNTMuMzExNzFjMi4yMTE5OCw5LjkwMjIyLDQuOTMwOTEsMTkuNjMxNDEsOC4xMjE1MiwyOS4xNjIyOUw3Ni43OTY5NCw0NTAuMjk4MzRjLTUuMjMyOTctNy4yOTk2Mi0xMC4xMTEzMy0xNC44NjYzMy0xNC42MDY4Ny0yMi42NzY5NFptMzEuMzA5NzUsNDMuNjkwMjVsMTQwLjcwNzI4LTE0MC43MDcyOGMzLjc5NTcyLDguNDU3MDksNy45OTI0OSwxNi43MDY3OSwxMi41NDM3NiwyNC43Mzk5OUwxMTEuODM2MTIsNDkwLjI1OTE2Yy02LjQxMjExLTYuMDE2Ni0xMi41MzMxNC0xMi4zMzg4MS0xOC4zMzYzLTE4Ljk0NzUxWm0zOC43MjQ0MywzNi4yNzU1N2wxMjkuMDg4NzUtMTI5LjA4ODc1YzUuMDY0NjQsNy4yODczNSwxMC40NDUwNywxNC4zNDcwNSwxNi4xMzQwOSwyMS4xNDk3MmwtMTIzLjIwMjIxLDEyMy4yMDIyMWMtNy41OTgwMi00LjcyNzY2LTE0Ljk0NTUtOS44MjQxNi0yMi4wMjA2My0xNS4yNjMxOFptNDYuMjk4NTgsMjguNzAxNDJsMTE2Ljk0NDk1LTExNi45NDQ5NWM2LjIyMDAzLDYuMjEzNjIsMTIuNzIzNzUsMTIuMTUwNTEsMTkuNDgzMDMsMTcuODAwNzJsLTExMC4yMjAyMSwxMTAuMjIwMjhjLTguOTU5OTYtMy4yMzgyMi0xNy43MDg0NC02LjkzMzktMjYuMjA3NzYtMTEuMDc2MDVabTU1LjI1OTg5LDE5Ljc0MDExbDEwMi41ODE2Ny0xMDIuNTgxNjdjNy4zOTcwOSw1LjEyMDYxLDE1LjA0MjkxLDkuOTE1NzcsMjIuOTIxNjMsMTQuMzYyMTJsLTkzLjcwNjg1LDkzLjcwNjkxYy0xMC43OTYyLTEuMTkzNzMtMjEuNDA5ODUtMy4wMzA0LTMxLjc5NjQ1LTUuNDg3MzdabTY3Ljk1Mzc0LDcuMDQ2MjZsODIuNjM0MDktODIuNjM0MDljOC43NDA0MiwzLjg4MzE4LDE3LjcyMDY0LDcuMzQxNjEsMjYuOTAzNjksMTAuMzgwMDdsLTY4LjEyMDQyLDY4LjEyMDQ4Yy0xMy42MiwyLjQ1MDItMjcuNDY2NjcsMy44MzY0OS00MS40MTczNiw0LjEzMzU0Wm05NC41NDIxMS0xOS41NDIxMWw0NC41OTktNDQuNTk5YzQuMTIyMDcsLjg5OTIzLDguMjc2MDYsMS43MTkzNiwxMi40NjUyNywyLjQ0NTY4LDEuOTIyNDksLjMzMDYzLDMuNDY1MzMsMS43NzU1MSwzLjkzMDYsMy42ODU3MywuNDUzMTIsMS44OTc5NS0uMjY5MzUsMy44OTM4Ni0xLjgzNjY3LDUuMDU3MTMtMTguMzIxNzgsMTMuNzA4NTYtMzguMjIxNjIsMjQuODk2NDgtNTkuMTU4MiwzMy40MTA0NloiLz48cGF0aCBkPSJNNTU1Ljg0NDkxLDIzMS44NjkzOGMuMTMyMzIsLjU0ODEsLjMwODExLDEuMDc2MDUsLjUwMzYsMS41OTM1NywxLjk1Nzc2LDUuMTgyMzcsNi45NTM5OCw4Ljc0MTE1LDEyLjU5ODQ1LDguNzQxMTVoLjAzNjc0YzcuMzgzNjcsMCwxMy40Njk0Mi02LjA4NTY5LDEzLjQ2OTQyLTEzLjQ2OTQyLDAtMS4wNTMwNC0uMTM0NzctMi4xMDYxNC0uMzc5NjQtMy4xMzQ3LTEuMTQxNDItNC43MjgyNy0yLjQwOTkxLTkuNDIwNDEtMy43ODMyLTE0LjA3ODgtMi43OTI5Ny05LjQ3NDE4LTYuMDU3NjItMTguNzk1ODQtOS43ODgzMy0yNy45Mjc4Ni01LjM1NjQ1LTEzLjExMTIxLTExLjY1ODg3LTI1LjgzNTYzLTE4Ljg3NzQ0LTM4LjA2MjY4bC0uMDYxMjItLjExMDIzYy0yLjYzMjYzLTMuNzQ2OTUtNy4wMDQwOS01LjkwMjA0LTExLjU5NTk1LTUuNzA2MTItNi43NTYxLC4yNzcxNi0xMi4yMzI0OCw1LjYyMDczLTEyLjgzMzc0LDEyLjI0NzMxLS4wMzYyNSwuMzk5MzUtLjA2MDEyLC44MDItLjA2MDEyLDEuMjA5ODQsMCwyLjA4MTYsLjQ3NzU0LDQuMTM4NzksMS40MDgxNCw2LDMuNjQ2OTEsNi4yMDEwNSw3LjAyNzE2LDEyLjU0NDE5LDEwLjE1MzY5LDE5LjAwNDcsNC4xMzk0Nyw4LjU1MzU5LDcuODIwNTYsMTcuMzE4NTQsMTEuMDIxMywyNi4yNjI0NSwzLjIxMzEzLDguOTc4NTgsNS45NTE4NCwxOC4xMzMsOC4xODgyOSwyNy40MzA3OVoiLz48cGF0aCBkPSJNNDEyLjE2MzI3LDUzLjUxMDE5di4wMTIyN2M1LjM2NjU4LDIuNTk2MDEsMTAuNjM0MjIsNS4zNzczOCwxNS44MDU3Myw4LjMyMDAxLDcuODMxMTIsNC40NTU5MywxNS40MzIxOSw5LjI5NywyMi43Njg2OCwxNC41MTUwOCw3LjI5MjYsNS4xODY4MywxNC4zMjE5LDEwLjc0NTczLDIxLjA2OTQ2LDE2LjY0Njc5LDEuNzkzODgsMS41Njg4NSwzLjU3NDcxLDMuMTUzNTYsNS4zMjc1OCw0Ljc3MTE4bC4wMjQ0OCwuMDI0NDhjMi40MjQ1LDIuMjY1MzIsOS4xOTU5MiwyLjk2MzI2LDkuMTk1OTIsMi45NjMyNiw3LjMyMjUxLS4wOTc5LDEzLjI4NTc3LTYuMTQ2OTEsMTMuMjg1NzctMTMuNDY5MzYsMC0zLjczNDY4LTEuNTU1MTgtNy4zMTAxOC00LjI5Nzk3LTkuODU3MTItMjEuMzE4NDItMTkuNDY5NDItNDUuMzc5NjQtMzUuNjkzOTEtNzEuNDAwMDItNDguMTcxNDUtLjAxMjI3LDAtLjAyNDQ4LDAtLjAyNDQ4LS4wMTIyNy0xLjc4Nzc4LS44NjkzOC0zLjc0Njk1LTEuMzIyNDUtNS43NDI4Ni0xLjM0NjkyaC0uMTU5MThjLTcuMzgzNjcsMC0xMy40Njk0Miw2LjA4NTY5LTEzLjQ2OTQyLDEzLjQ2OTM2LDAsMS43OTc2MSwuMzY1OTEsMy41Mzg1MSwxLjAyOTQ4LDUuMTQzMzEsMS4yNDQwMiwzLjAwODQyLDMuNTUyNDMsNS41MzAwOSw2LjU4Njg1LDYuOTkxMzlaIi8+PC9zdmc+';
  38. const logo = 'data:image/png;base64,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';
  39.  
  40. function semverCompare(current, latest) {
  41. if (current.startsWith(latest + '-'))
  42. return -1;
  43. if (latest.startsWith(current + '-'))
  44. return 1;
  45. return current.localeCompare(latest, undefined, { numeric: true, sensitivity: 'case', caseFirst: 'upper' }) === -1;
  46. }
  47. function init$d(elements) {
  48. GM.xmlHttpRequest({
  49. method: 'GET',
  50. url: `https://github.com/Mikarific/InfiniteCraftHelper/raw/main/gorilla.json`,
  51. onload: (response) => {
  52. if (response.status === 200) {
  53. const responseJSON = JSON.parse(response.responseText);
  54. if (semverCompare(GM.info.script.version, responseJSON.version)) {
  55. const outdatedModal = document.createElement('dialog');
  56. outdatedModal.classList.add('modal');
  57. elements.container.appendChild(outdatedModal);
  58. const outdatedHeader = document.createElement('div');
  59. outdatedHeader.classList.add('modal-header');
  60. const outdatedTitle = document.createElement('h1');
  61. outdatedTitle.classList.add('modal-title');
  62. outdatedTitle.appendChild(document.createTextNode('Infinite Craft Helper is out of date!'));
  63. outdatedHeader.appendChild(outdatedTitle);
  64. const closeButtonContainer = document.createElement('div');
  65. closeButtonContainer.classList.add('close-button-container');
  66. const closeButton = document.createElement('img');
  67. closeButton.src = closeIcon.trim();
  68. closeButton.classList.add('close-button');
  69. closeButtonContainer.appendChild(closeButton);
  70. outdatedHeader.appendChild(closeButtonContainer);
  71. outdatedModal.appendChild(outdatedHeader);
  72. const versionText = document.createElement('div');
  73. versionText.classList.add('modal-text');
  74. versionText.appendChild(document.createTextNode(`You are on v${GM.info.script.version}! The latest verion is v${responseJSON.version}!`));
  75. outdatedModal.appendChild(versionText);
  76. const buttonContainer = document.createElement('div');
  77. buttonContainer.classList.add('modal-button-container');
  78. const updateButton = document.createElement('a');
  79. updateButton.classList.add('item');
  80. updateButton.href = responseJSON.downloadURL;
  81. updateButton.appendChild(document.createTextNode('Update'));
  82. buttonContainer.appendChild(updateButton);
  83. const continueButton = document.createElement('button');
  84. continueButton.classList.add('item');
  85. continueButton.appendChild(document.createTextNode('Continue Anyways'));
  86. buttonContainer.appendChild(continueButton);
  87. outdatedModal.appendChild(buttonContainer);
  88. outdatedModal.showModal();
  89. closeButton.addEventListener('click', (e) => {
  90. outdatedModal.close();
  91. });
  92. continueButton.addEventListener('click', (e) => {
  93. outdatedModal.close();
  94. });
  95. }
  96. }
  97. },
  98. });
  99. }
  100.  
  101. function init$c(elements) {
  102. if (elements.favicon !== null) {
  103. const whiteFaviconLink = elements.favicon.cloneNode();
  104. elements.favicon.media = '(prefers-color-scheme:light)';
  105. whiteFaviconLink.media = '(prefers-color-scheme:dark)';
  106. whiteFaviconLink.href = whiteFavicon.trim();
  107. elements.favicon.after(whiteFaviconLink);
  108. }
  109. }
  110.  
  111. const css = `
  112. .dark-mode .site-title, .dark-mode .instruction-icon, .dark-mode .settings-button, .dark-mode .setting > img, .dark-mode .close-button {
  113. filter: invert(1);
  114. }
  115.  
  116. .dark-mode {
  117. scrollbar-color: var(--border-color) #262626;
  118. }
  119.  
  120. .item {
  121. margin: 4px;
  122. cursor: pointer;
  123. padding: 8px 8px 7px;
  124. border-radius: 5px;
  125. display: inline-block;
  126. -webkit-user-select: none;
  127. -moz-user-select: none;
  128. user-select: none;
  129. border: 1px solid var(--border-color);
  130. transition: background .15s linear;
  131. background: var(--item-bg);
  132. line-height: 1em;
  133. color: var(--text-color);
  134. white-space: nowrap;
  135. }
  136.  
  137. .item:hover {
  138. background: var(--instance-bg-hover);
  139. border: 1px solid var(--instance-border-hover);
  140. }
  141.  
  142. @media screen and (min-width: 1150px) {
  143. .item {
  144. font-size: 16.4px;
  145. padding: 9px 10px 8px;
  146. }
  147. }
  148.  
  149. .pinned {
  150. max-width: 900px;
  151. margin-left: auto;
  152. margin-right: auto;
  153. padding: 9px;
  154. border: 0px;
  155. border-bottom: 1px;
  156. border-style: solid;
  157. border-color: var(--border-color);
  158. }
  159.  
  160. .pinned-title {
  161. margin: 4px;
  162. font-size: 15px;
  163. font-family: Roboto, sans-serif;
  164. color: var(--text-color);
  165. -webkit-user-select: none;
  166. -moz-user-select: none;
  167. user-select: none;
  168. pointer-events: none;
  169. }
  170.  
  171. .sidebar {
  172. width: var(--sidebar-size) !important;
  173. }
  174.  
  175. .resize-bar {
  176. position: absolute;
  177. height: 100%;
  178. width: 5px;
  179. right: calc(var(--sidebar-size) - 3px);
  180. z-index: 10;
  181. cursor: ew-resize;
  182. }
  183.  
  184. .sidebar-header {
  185. display: flex;
  186. position: sticky;
  187. height: auto !important;
  188. top: 0px;
  189. background-color: var(--background-color) !important;
  190. max-width: 900px;
  191. margin-left: auto;
  192. margin-right: auto;
  193. padding: 9px;
  194. border: 0px;
  195. border-bottom: 1px;
  196. border-style: solid;
  197. border-color: var(--border-color);
  198. z-index: 1;
  199. }
  200.  
  201. .sidebar-search {
  202. width: 100%;
  203. }
  204.  
  205. .sidebar-input {
  206. height: 40px !important;
  207. margin: 4px;
  208. border-radius: 5px;
  209. border: 1px solid var(--border-color) !important;
  210. font-family: Roboto, sans-serif;
  211. background-size: 21px 21px !important;
  212. background-position: 10px 10px !important;
  213. color: var(--text-color);
  214. }
  215.  
  216. .settings-details {
  217. display: flex;
  218. margin: 4px;
  219. height: 40px;
  220. border: 1px solid var(--border-color);
  221. border-radius: 5px;
  222. }
  223.  
  224. .settings-summary {
  225. display: flex;
  226. list-style: none;
  227. }
  228.  
  229. .settings-button {
  230. height: 40px;
  231. padding: 8px 8px 7px;
  232. cursor: pointer;
  233. opacity: .8;
  234. -webkit-user-select: none;
  235. -moz-user-select: none;
  236. user-select: none;
  237. aspect-ratio: 1/1;
  238. }
  239.  
  240. .settings-button:hover {
  241. transform: scale(1.05)
  242. }
  243.  
  244. .settings-content {
  245. display: flex;
  246. flex-direction: column;
  247. gap: 5px;
  248. position: absolute;
  249. right: 13px;
  250. padding: 8px 8px 7px;
  251. border: 1px solid var(--border-color);
  252. border-radius: 5px;
  253. background-color: var(--background-color);
  254. }
  255.  
  256. .setting {
  257. display: flex;
  258. gap: 5px;
  259. justify-content: flex-end;
  260. cursor: pointer;
  261. padding: 8px 8px 7px;
  262. border: 1px solid var(--border-color);
  263. border-radius: 5px;
  264. -webkit-user-select: none;
  265. -moz-user-select: none;
  266. user-select: none;
  267. line-height: 1em;
  268. font-family: Roboto, sans-serif;
  269. font-size: 15.4px;
  270. color: var(--text-color);
  271. }
  272.  
  273. .setting:hover {
  274. background: var(--instance-bg-hover);
  275. border: 1px solid var(--instance-border-hover);
  276. }
  277.  
  278. .setting > img {
  279. height: 1em;
  280. opacity: .8;
  281. aspect-ratio: 1 / 1;
  282. }
  283.  
  284. #import-save {
  285. display: none;
  286. }
  287.  
  288. .logo {
  289. width: 85px !important;
  290. right: calc(var(--sidebar-size) + 15px) !important;
  291. }
  292.  
  293. .version {
  294. position: fixed;
  295. top: 85px;
  296. right: calc(var(--sidebar-size) + 15px);
  297. -webkit-user-select: none;
  298. -moz-user-select: none;
  299. user-select: none;
  300. pointer-events: none;
  301. color: var(--text-color);
  302. font-family: Roboto, sans-serif;
  303. font-size: 11px;
  304. }
  305.  
  306. .side-controls {
  307. right: calc(var(--sidebar-size) + 9px) !important;
  308. z-index: 1;
  309. }
  310.  
  311. .random, .discoveries-icon {
  312. width: 21px;
  313. cursor: pointer;
  314. opacity: .8;
  315. -webkit-user-select: none;
  316. -moz-user-select: none;
  317. user-select: none;
  318. }
  319.  
  320. .random:hover, .discoveries-icon:hover {
  321. transform: scale(1.05);
  322. }
  323.  
  324. .modal {
  325. max-width: 75%;
  326. max-height: 75%;
  327. margin: auto;
  328. padding-top: 0px;
  329. border: 1px solid var(--border-color);
  330. border-radius: 5px;
  331. background-color: var(--background-color);
  332. }
  333.  
  334. .modal::backdrop {
  335. background-color: rgb(0 0 0 / .5);
  336. }
  337.  
  338. .modal-header {
  339. position: sticky;
  340. top: 0;
  341. display: flex;
  342. gap: 1rem;
  343. padding-top: 16px;
  344. padding-bottom: 16px;
  345. justify-content: space-between;
  346. background-color: var(--background-color);
  347. }
  348.  
  349. .modal-title {
  350. font-size: 20px;
  351. font-family: Roboto, sans-serif;
  352. line-height: 35px;
  353. color: var(--text-color);
  354. -webkit-user-select: none;
  355. -moz-user-select: none;
  356. user-select: none;
  357. }
  358.  
  359. .modal-text {
  360. font-size: 15px;
  361. font-family: Roboto, sans-serif;
  362. color: var(--text-color);
  363. text-align: center;
  364. -webkit-user-select: none;
  365. -moz-user-select: none;
  366. user-select: none;
  367. pointer-events: none;
  368. }
  369.  
  370. .display-item {
  371. margin: 4px;
  372. padding: 8px 8px 7px;
  373. border-radius: 5px;
  374. display: inline-block;
  375. -webkit-user-select: none;
  376. -moz-user-select: none;
  377. user-select: none;
  378. border: 1px solid var(--border-color);
  379. background: var(--item-bg);
  380. line-height: 1em;
  381. white-space: nowrap;
  382. color: var(--text-color);
  383. }
  384.  
  385. @media screen and (min-width: 1150px) {
  386. .display-item {
  387. font-size: 16.4px;
  388. padding: 9px 10px 8px;
  389. }
  390. }
  391.  
  392. .recipe {
  393. display: flex;
  394. align-items: center;
  395. color: var(--text-color);
  396. -webkit-user-select: none;
  397. -moz-user-select: none;
  398. user-select: none;
  399. }
  400.  
  401. .modal-button-container {
  402. display: flex;
  403. align-items: center;
  404. justify-content: center;
  405. padding-top: 16px;
  406. color: var(--text-color);
  407. -webkit-user-select: none;
  408. -moz-user-select: none;
  409. user-select: none;
  410. }
  411.  
  412. .modal-button-container > .item {
  413. font-family: Roboto, sans-serif;
  414. font-size: 15.4px;
  415. text-decoration: auto;
  416. }
  417.  
  418. .close-button-container {
  419. display: flex;
  420. border: 1px solid var(--border-color);
  421. border-radius: 5px;
  422. }
  423.  
  424. .close-button {
  425. height: 35px;
  426. padding: 8px 8px 7px;
  427. cursor: pointer;
  428. opacity: .8;
  429. -webkit-user-select: none;
  430. -moz-user-select: none;
  431. user-select: none;
  432. }
  433.  
  434. .close-button:hover {
  435. transform: scale(1.05)
  436. }
  437.  
  438. .instance-emoji {
  439. pointer-events: none;
  440. }
  441. `;
  442. function init$b(elements) {
  443. elements.styles.appendChild(document.createTextNode(css.trim()));
  444. document.getElementsByTagName('head')[0].appendChild(elements.styles);
  445. }
  446.  
  447. function setMiddleClickOnMutations(mutations, elements) {
  448. for (const mutation of mutations) {
  449. if (mutation.addedNodes.length > 0) {
  450. for (const node of mutation.addedNodes) {
  451. node.addEventListener('mousedown', (e) => {
  452. e.preventDefault();
  453. if (e instanceof MouseEvent &&
  454. e.button === 1 &&
  455. e.target instanceof HTMLElement &&
  456. (e.target.classList.contains('instance') ||
  457. e.target.classList.contains('instance-discovered-text') ||
  458. e.target.classList.contains('instance-discovered-emoji'))) {
  459. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].playInstanceSound();
  460. const targetElement = e.target.classList.contains('instance-discovered-emoji')
  461. ? e.target.parentElement?.parentElement
  462. : e.target.classList.contains('instance-discovered-text')
  463. ? e.target.parentElement
  464. : e.target;
  465. const { x, y, width, height } = targetElement.getBoundingClientRect();
  466. const data = {
  467. id: unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.instanceId++,
  468. text: targetElement.childNodes[1].textContent?.trim(),
  469. emoji: targetElement.childNodes[0].textContent?.trim(),
  470. discovered: targetElement.classList.contains('instance-discovered'),
  471. disabled: false,
  472. left: x,
  473. top: y,
  474. offsetX: 0.5,
  475. offsetY: 0.5,
  476. hasMoved: false,
  477. fromPanel: false,
  478. };
  479. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance = cloneInto(data, unsafeWindow);
  480. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.instances.push(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance);
  481. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].$nextTick(exportFunction(() => {
  482. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].setInstancePosition(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance, e.clientX - width / 2, e.clientY - height / 2);
  483. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].setInstanceZIndex(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance, data.id);
  484. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance.elem.addEventListener('mouseup', exportFunction((e) => {
  485. if (!unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance.hasMoved) {
  486. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance.hasMoved =
  487. true;
  488. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].calcInstanceSize(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance);
  489. }
  490. }, unsafeWindow));
  491. }, unsafeWindow));
  492. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.mouseDown = true;
  493. }
  494. });
  495. }
  496. }
  497. }
  498. }
  499.  
  500. const craftsModal = document.createElement('dialog');
  501. const craftsTitle = document.createElement('h1');
  502. const craftsContainer = document.createElement('div');
  503. let recipes = {};
  504. async function init$a(elements) {
  505. craftsModal.classList.add('modal');
  506. elements.container.appendChild(craftsModal);
  507. const craftsHeader = document.createElement('div');
  508. craftsHeader.classList.add('modal-header');
  509. craftsTitle.classList.add('modal-title');
  510. craftsTitle.appendChild(document.createTextNode('Crafts'));
  511. craftsHeader.appendChild(craftsTitle);
  512. const closeButtonContainer = document.createElement('div');
  513. closeButtonContainer.classList.add('close-button-container');
  514. const closeButton = document.createElement('img');
  515. closeButton.src = closeIcon.trim();
  516. closeButton.classList.add('close-button');
  517. closeButtonContainer.appendChild(closeButton);
  518. craftsHeader.appendChild(closeButtonContainer);
  519. craftsModal.appendChild(craftsHeader);
  520. craftsContainer.classList.add('crafts-container');
  521. craftsModal.appendChild(craftsContainer);
  522. recipes = JSON.parse((await GM.getValue('recipes')) ?? '{}');
  523. delete recipes['Nothing'];
  524. for (const recipeKey of Object.keys(recipes)) {
  525. for (let i = recipes[recipeKey].length - 1; i >= 0; i--) {
  526. if (recipes[recipeKey][i] === undefined ||
  527. recipes[recipeKey][i] === null ||
  528. recipes[recipeKey][i].length < 2 ||
  529. recipes[recipeKey][i][0].text === recipeKey ||
  530. recipes[recipeKey][i][1].text === recipeKey) {
  531. recipes[recipeKey].splice(i, 1);
  532. }
  533. }
  534. }
  535. await GM.setValue('recipes', JSON.stringify(recipes));
  536. closeButton.addEventListener('click', (e) => {
  537. craftsModal.close();
  538. });
  539. }
  540. async function addElementToCrafts(first, second, result, loading = false) {
  541. const ingredients = [first, second].sort((a, b) => {
  542. return a.text.localeCompare(b.text);
  543. });
  544. if (recipes[result] === undefined)
  545. recipes[result] = [];
  546. if (recipes[result].find((recipe) => recipe[0].text === ingredients[0].text && recipe[1].text === ingredients[1].text) !== undefined)
  547. return;
  548. recipes[result].push([
  549. {
  550. text: ingredients[0].text,
  551. emoji: ingredients[0].emoji ?? '⬜',
  552. },
  553. {
  554. text: ingredients[1].text,
  555. emoji: ingredients[1].emoji ?? '⬜',
  556. },
  557. ]);
  558. if (!loading)
  559. await GM.setValue('recipes', JSON.stringify(recipes));
  560. }
  561. function openCraftsForElement(element) {
  562. craftsTitle.innerHTML = '';
  563. const titleEmoji = document.createElement('span');
  564. titleEmoji.classList.add('display-item-emoji');
  565. titleEmoji.appendChild(document.createTextNode(element.emoji ?? '⬜'));
  566. craftsTitle.appendChild(titleEmoji);
  567. craftsTitle.appendChild(document.createTextNode(` ${element.text} `));
  568. craftsContainer.innerHTML = '';
  569. const elementRecipes = recipes[element.text];
  570. if (elementRecipes === undefined) {
  571. const recipesEmpty = document.createElement('div');
  572. recipesEmpty.classList.add('modal-text');
  573. recipesEmpty.appendChild(document.createTextNode("I don't know how to craft this element!"));
  574. craftsContainer.appendChild(recipesEmpty);
  575. }
  576. else {
  577. const recipeKeys = Object.keys(recipes);
  578. for (const elementRecipe of elementRecipes) {
  579. const recipeDiv = document.createElement('div');
  580. recipeDiv.classList.add('recipe');
  581. const firstDiv = document.createElement('div');
  582. recipeKeys.includes(elementRecipe[0].text)
  583. ? firstDiv.classList.add('item')
  584. : firstDiv.classList.add('display-item');
  585. const firstEmoji = document.createElement('span');
  586. recipeKeys.includes(elementRecipe[0].text)
  587. ? firstEmoji.classList.add('item-emoji')
  588. : firstEmoji.classList.add('display-item-emoji');
  589. firstEmoji.appendChild(document.createTextNode(elementRecipe[0].emoji ?? '⬜'));
  590. firstDiv.appendChild(firstEmoji);
  591. firstDiv.appendChild(document.createTextNode(` ${elementRecipe[0].text} `));
  592. if (recipeKeys.includes(elementRecipe[0].text)) {
  593. firstDiv.addEventListener('click', () => {
  594. openCraftsForElement(elementRecipe[0]);
  595. });
  596. }
  597. recipeDiv.appendChild(firstDiv);
  598. recipeDiv.appendChild(document.createTextNode('+'));
  599. const secondDiv = document.createElement('div');
  600. recipeKeys.includes(elementRecipe[1].text)
  601. ? secondDiv.classList.add('item')
  602. : secondDiv.classList.add('display-item');
  603. const secondEmoji = document.createElement('span');
  604. recipeKeys.includes(elementRecipe[1].text)
  605. ? secondEmoji.classList.add('item-emoji')
  606. : secondEmoji.classList.add('display-item-emoji');
  607. secondEmoji.appendChild(document.createTextNode(elementRecipe[1].emoji ?? '⬜'));
  608. secondDiv.appendChild(secondEmoji);
  609. secondDiv.appendChild(document.createTextNode(` ${elementRecipe[1].text} `));
  610. if (recipeKeys.includes(elementRecipe[1].text)) {
  611. secondDiv.addEventListener('click', () => {
  612. openCraftsForElement(elementRecipe[1]);
  613. });
  614. }
  615. recipeDiv.appendChild(secondDiv);
  616. recipeDiv.appendChild(document.createTextNode('='));
  617. const resultDiv = document.createElement('div');
  618. resultDiv.classList.add('display-item');
  619. const resultEmoji = document.createElement('span');
  620. resultEmoji.classList.add('display-item-emoji');
  621. resultEmoji.appendChild(document.createTextNode(element.emoji ?? '⬜'));
  622. resultDiv.appendChild(resultEmoji);
  623. resultDiv.appendChild(document.createTextNode(` ${element.text} `));
  624. recipeDiv.appendChild(resultDiv);
  625. craftsContainer.appendChild(recipeDiv);
  626. }
  627. }
  628. craftsModal.showModal();
  629. }
  630. async function resetCrafts() {
  631. recipes = {};
  632. await GM.setValue('recipes', '{}');
  633. }
  634.  
  635. const discoveriesModal = document.createElement('dialog');
  636. const discoveriesHeader = document.createElement('div');
  637. const discoveriesEmpty = document.createElement('div');
  638. function init$9(elements) {
  639. const discoveriesImage = document.createElement('img');
  640. discoveriesImage.src = discoveriesIcon.trim();
  641. discoveriesImage.classList.add('discoveries-icon');
  642. elements.sideControls.appendChild(discoveriesImage);
  643. discoveriesModal.classList.add('modal');
  644. elements.container.appendChild(discoveriesModal);
  645. discoveriesHeader.classList.add('modal-header');
  646. const discoveriesTitle = document.createElement('h1');
  647. discoveriesTitle.classList.add('modal-title');
  648. discoveriesTitle.appendChild(document.createTextNode('Your First Discoveries'));
  649. discoveriesHeader.appendChild(discoveriesTitle);
  650. const closeButtonContainer = document.createElement('div');
  651. closeButtonContainer.classList.add('close-button-container');
  652. const closeButton = document.createElement('img');
  653. closeButton.src = closeIcon.trim();
  654. closeButton.classList.add('close-button');
  655. closeButtonContainer.appendChild(closeButton);
  656. discoveriesHeader.appendChild(closeButtonContainer);
  657. discoveriesModal.appendChild(discoveriesHeader);
  658. discoveriesEmpty.classList.add('modal-text');
  659. discoveriesEmpty.appendChild(document.createTextNode("You don't have any first discoveries!"));
  660. discoveriesModal.appendChild(discoveriesEmpty);
  661. const discoveredElements = cloneInto(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements, unsafeWindow).filter((el) => el.discovered === true);
  662. for (const discoveredElement of discoveredElements) {
  663. addElementToDiscoveries(discoveredElement);
  664. }
  665. discoveriesImage.addEventListener('click', (e) => {
  666. discoveriesModal.showModal();
  667. });
  668. closeButton.addEventListener('click', (e) => {
  669. discoveriesModal.close();
  670. });
  671. }
  672. function addElementToDiscoveries(element) {
  673. const recipeKeys = Object.keys(recipes);
  674. const elementDiv = document.createElement('div');
  675. recipeKeys.includes(element.text) ? elementDiv.classList.add('item') : elementDiv.classList.add('display-item');
  676. const elementEmoji = document.createElement('span');
  677. recipeKeys.includes(element.text)
  678. ? elementEmoji.classList.add('item-emoji')
  679. : elementEmoji.classList.add('display-item-emoji');
  680. elementEmoji.appendChild(document.createTextNode(element.emoji ?? '⬜'));
  681. elementDiv.appendChild(elementEmoji);
  682. elementDiv.appendChild(document.createTextNode(` ${element.text} `));
  683. if (recipeKeys.includes(element.text)) {
  684. elementDiv.addEventListener('click', () => {
  685. openCraftsForElement(element);
  686. });
  687. }
  688. discoveriesModal.appendChild(elementDiv);
  689. discoveriesEmpty.style.display = 'none';
  690. }
  691. function resetDiscoveries() {
  692. discoveriesModal.innerHTML = '';
  693. discoveriesModal.appendChild(discoveriesHeader);
  694. discoveriesModal.appendChild(discoveriesEmpty);
  695. discoveriesEmpty.style.display = '';
  696. }
  697.  
  698. let contributeToDatabase = false;
  699. function init$8(elements) {
  700. const settingsDetails = document.createElement('details');
  701. settingsDetails.classList.add('settings-details');
  702. elements.sidebarHeader.appendChild(settingsDetails);
  703. const settingsSummary = document.createElement('summary');
  704. settingsSummary.classList.add('settings-summary');
  705. settingsDetails.appendChild(settingsSummary);
  706. const settingsButton = document.createElement('img');
  707. settingsButton.src = settingsIcon.trim();
  708. settingsButton.classList.add('settings-button');
  709. settingsSummary.appendChild(settingsButton);
  710. settingsDetails.appendChild(elements.settingsContent);
  711. document.addEventListener('click', function (e) {
  712. const target = e.target;
  713. if (!settingsDetails.contains(target)) {
  714. settingsDetails.removeAttribute('open');
  715. }
  716. });
  717. contributeToDatabase = localStorage.getItem('contributeToDatabase') === 'false' ? false : true;
  718. const contributeContainer = document.createElement('div');
  719. contributeContainer.classList.add('setting');
  720. const contributeText = document.createTextNode('Share Crafts?');
  721. contributeContainer.appendChild(contributeText);
  722. const contributeImage = document.createElement('img');
  723. if (!contributeToDatabase) {
  724. contributeImage.src = dontContributeIcon.trim();
  725. }
  726. else {
  727. contributeImage.src = contributeIcon.trim();
  728. }
  729. contributeContainer.appendChild(contributeImage);
  730. elements.settingsContent.appendChild(contributeContainer);
  731. contributeContainer.addEventListener('click', (e) => {
  732. if (!contributeToDatabase) {
  733. contributeToDatabase = true;
  734. contributeImage.src = contributeIcon.trim();
  735. localStorage.setItem('contributeToDatabase', 'true');
  736. }
  737. else {
  738. contributeToDatabase = false;
  739. contributeImage.src = dontContributeIcon.trim();
  740. localStorage.setItem('contributeToDatabase', 'false');
  741. }
  742. });
  743. }
  744.  
  745. const pinnedContainer = document.createElement('div');
  746. const pinnedTitle = document.createElement('div');
  747. let pinnedElements = [];
  748. async function init$7(elements) {
  749. pinnedContainer.classList.add('pinned');
  750. pinnedTitle.classList.add('pinned-title');
  751. pinnedTitle.appendChild(document.createTextNode('Pinned Elements'));
  752. pinnedContainer.appendChild(pinnedTitle);
  753. pinnedElements = JSON.parse((await GM.getValue('pinned')) ?? '[]');
  754. if (pinnedElements.length === 0)
  755. pinnedContainer.style.display = 'none';
  756. for (const pinnedElement of pinnedElements) {
  757. const elementDiv = document.createElement('div');
  758. elementDiv.classList.add('item');
  759. const elementEmoji = document.createElement('span');
  760. elementEmoji.classList.add('item-emoji');
  761. elementEmoji.appendChild(document.createTextNode(pinnedElement.emoji ?? '⬜'));
  762. elementDiv.appendChild(elementEmoji);
  763. elementDiv.appendChild(document.createTextNode(` ${pinnedElement.text} `));
  764. elementDiv.addEventListener('mousedown', (e) => {
  765. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].selectElement(e, cloneInto(pinnedElement, unsafeWindow));
  766. });
  767. pinnedContainer.appendChild(elementDiv);
  768. }
  769. elements.items.before(pinnedContainer);
  770. }
  771. async function pinElement(element, loading = false) {
  772. if (pinnedElements.find((el) => el.text === element.text) === undefined) {
  773. if (!loading)
  774. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].playInstanceSound();
  775. const elementDiv = document.createElement('div');
  776. elementDiv.classList.add('item');
  777. const elementEmoji = document.createElement('span');
  778. elementEmoji.classList.add('item-emoji');
  779. elementEmoji.appendChild(document.createTextNode(element.emoji ?? '⬜'));
  780. elementDiv.appendChild(elementEmoji);
  781. elementDiv.appendChild(document.createTextNode(` ${element.text} `));
  782. elementDiv.addEventListener('mousedown', (e) => {
  783. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].selectElement(e, element);
  784. });
  785. pinnedContainer.appendChild(elementDiv);
  786. if (pinnedElements.length === 0)
  787. pinnedContainer.style.display = '';
  788. pinnedElements.push(element);
  789. if (!loading)
  790. await GM.setValue('pinned', JSON.stringify(pinnedElements));
  791. }
  792. else {
  793. if (!loading)
  794. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.deleteSound.play();
  795. const elementDiv = Array.from(pinnedContainer.querySelectorAll('.item')).find((el) => el.childNodes[1].textContent?.trim() === element.text);
  796. elementDiv?.remove();
  797. if (pinnedElements.length === 1)
  798. pinnedContainer.style.display = 'none';
  799. pinnedElements = pinnedElements.filter((el) => el !== element);
  800. if (!loading)
  801. await GM.setValue('pinned', JSON.stringify(pinnedElements));
  802. }
  803. }
  804. async function resetPinnedElements() {
  805. pinnedContainer.innerHTML = '';
  806. pinnedContainer.appendChild(pinnedTitle);
  807. pinnedContainer.style.display = 'none';
  808. pinnedElements = [];
  809. await GM.setValue('pinned', '[]');
  810. }
  811.  
  812. function init$6(elements) {
  813. // Detect when fetch is monkeypatched because a certain someone made a tool to upload fake recipes.
  814. const iframe = document.createElement('iframe');
  815. document.body.appendChild(iframe);
  816. const cleanFetch = iframe.contentWindow?.fetch?.toString() ?? '';
  817. iframe.remove();
  818. // New Element Crafted
  819. const getCraftResponse = unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].getCraftResponse;
  820. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].getCraftResponse = exportFunction((...args) => new window.Promise(async (resolve) => {
  821. const response = await getCraftResponse(...args);
  822. const args0 = args[0].wrappedJSObject === undefined ? args[0] : args[0].wrappedJSObject;
  823. const args1 = args[1].wrappedJSObject === undefined ? args[1] : args[1].wrappedJSObject;
  824. const ingredients = args0.text.localeCompare(args1.text, 'en') === -1 ? [args0, args1] : [args1, args0];
  825. const first = ingredients[0];
  826. const second = ingredients[1];
  827. const result = {
  828. text: response.result,
  829. emoji: response.emoji,
  830. discovered: response.isNew,
  831. };
  832. if (first.text === '')
  833. return resolve(response);
  834. if (second.text === '')
  835. return resolve(response);
  836. if (result.text === '' || result.text === 'Nothing')
  837. return resolve(response);
  838. if (contributeToDatabase && unsafeWindow.fetch.toString() === cleanFetch) {
  839. GM.xmlHttpRequest({
  840. method: 'POST',
  841. url: `https://infinitecraft.mikarific.com/recipe`,
  842. data: JSON.stringify({
  843. first: {
  844. text: first.text,
  845. emoji: first.emoji,
  846. },
  847. second: {
  848. text: second.text,
  849. emoji: second.emoji,
  850. },
  851. result: {
  852. text: result.text,
  853. emoji: result.emoji,
  854. },
  855. }),
  856. headers: {
  857. 'Content-Type': 'application/json',
  858. Origin: 'https://neal.fun/infinite-craft/',
  859. },
  860. });
  861. }
  862. addElementToCrafts({
  863. text: first.text,
  864. emoji: first.emoji,
  865. }, {
  866. text: second.text,
  867. emoji: second.emoji,
  868. }, result.text);
  869. if (result.discovered) {
  870. addElementToDiscoveries(result);
  871. }
  872. console.log(`${first.text} + ${second.text} = ${result.text}`);
  873. resolve(response);
  874. }), unsafeWindow);
  875. const selectElement = unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].selectElement;
  876. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].selectElement = exportFunction((e, element) => {
  877. element = element.wrappedJSObject === undefined ? element : element.wrappedJSObject;
  878. if (e.button === 2) {
  879. openCraftsForElement(element);
  880. return;
  881. }
  882. if (e.altKey) {
  883. pinElement(element);
  884. return;
  885. }
  886. return selectElement(e, element);
  887. }, unsafeWindow);
  888. const instanceObserver = new MutationObserver((mutations) => {
  889. setMiddleClickOnMutations(mutations);
  890. });
  891. instanceObserver.observe(elements.instances, { childList: true, subtree: true });
  892. const oldResetButton = document.querySelector('.reset');
  893. const resetButton = oldResetButton.cloneNode(true);
  894. oldResetButton.parentNode?.replaceChild(resetButton, oldResetButton);
  895. resetButton.addEventListener('click', async () => {
  896. const confirmation = confirm('Are you sure? This will delete all your progress!');
  897. if (confirmation) {
  898. localStorage.removeItem('infinite-craft-data');
  899. await resetPinnedElements();
  900. await resetCrafts();
  901. location.reload();
  902. }
  903. });
  904. }
  905.  
  906. let sidebarSize = 0;
  907. let resizing = false;
  908. function onResize() {
  909. sidebarSize =
  910. window.innerWidth > 800 ? Math.min(Math.min(Math.max(sidebarSize, 305), 900), window.innerWidth - 100) : 0;
  911. document.documentElement.style.setProperty('--sidebar-size', `${sidebarSize}px`);
  912. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.sidebarSize = sidebarSize;
  913. for (const instance of unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.instances) {
  914. instance.width || unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].calcInstanceSize(instance),
  915. instance.left + instance.width + 10 > window.innerWidth - sidebarSize &&
  916. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].setInstancePosition(instance, window.innerWidth - sidebarSize - instance.width - 10, instance.top),
  917. instance.top + instance.height + 10 > window.innerHeight &&
  918. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].setInstancePosition(instance, instance.left, window.innerHeight - instance.height - 10);
  919. }
  920. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].checkControlsBlur();
  921. }
  922. function init$5(elements) {
  923. sidebarSize =
  924. window.innerWidth > 800
  925. ? unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.sidebarSize > 310
  926. ? 350
  927. : 305
  928. : 0;
  929. document.documentElement.style.setProperty('--sidebar-size', `${sidebarSize}px`);
  930. const resizeBar = document.createElement('div');
  931. resizeBar.classList.add('resize-bar');
  932. elements.sidebar.after(resizeBar);
  933. resizeBar.addEventListener('mousedown', () => {
  934. resizing = true;
  935. });
  936. window.addEventListener('mousemove', (e) => {
  937. if (resizing) {
  938. sidebarSize =
  939. window.innerWidth > 800
  940. ? Math.min(Math.min(Math.max(window.innerWidth - e.clientX, 305), 900), window.innerWidth - 100)
  941. : 13;
  942. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.sidebarSize = sidebarSize;
  943. document.documentElement.style.setProperty('--sidebar-size', `${sidebarSize}px`);
  944. onResize();
  945. }
  946. });
  947. window.addEventListener('mouseup', () => {
  948. resizing = false;
  949. });
  950. window.removeEventListener('resize', unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].onResize);
  951. window.addEventListener('resize', onResize);
  952. }
  953.  
  954. function init$4(elements) {
  955. const uploadContainer = document.createElement('label');
  956. uploadContainer.setAttribute('for', 'import-save');
  957. uploadContainer.classList.add('setting');
  958. const uploadInput = document.createElement('input');
  959. uploadInput.type = 'file';
  960. uploadInput.id = 'import-save';
  961. uploadContainer.appendChild(uploadInput);
  962. const uploadText = document.createTextNode('Import Save File');
  963. uploadContainer.appendChild(uploadText);
  964. const uploadImage = document.createElement('img');
  965. uploadImage.src = uploadIcon.trim();
  966. uploadContainer.appendChild(uploadImage);
  967. elements.settingsContent.appendChild(uploadContainer);
  968. uploadInput.addEventListener('change', async () => {
  969. const file = uploadInput.files !== null ? uploadInput.files[0] : null;
  970. if (file === null || file.type !== 'application/json')
  971. return;
  972. const fileContents = JSON.parse(await file.text());
  973. if (!Object.keys(fileContents).includes('elements'))
  974. return;
  975. const saveFile = [];
  976. for (const element of fileContents.elements) {
  977. if (!Object.keys(element).includes('text'))
  978. continue;
  979. const toPush = {
  980. text: element.text,
  981. discovered: !Object.keys(element).includes('discovered')
  982. ? Object.keys(fileContents).includes('discoveries')
  983. ? fileContents.discoveries.includes(element.text)
  984. : false
  985. : element.discovered,
  986. };
  987. if (Object.keys(element).includes('emoji'))
  988. toPush.emoji = element.emoji;
  989. saveFile.push(toPush);
  990. }
  991. localStorage.setItem('infinite-craft-data', JSON.stringify({
  992. elements: saveFile,
  993. }));
  994. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements = cloneInto(saveFile, unsafeWindow);
  995. await resetCrafts();
  996. if (Object.keys(fileContents).includes('recipes')) {
  997. for (const recipeKey of Object.keys(fileContents.recipes)) {
  998. if (recipeKey !== 'Nothing') {
  999. for (const recipe of fileContents.recipes[recipeKey]) {
  1000. if (recipe[0].text !== recipeKey && recipe[1].text !== recipeKey) {
  1001. addElementToCrafts({
  1002. text: recipe[0].text,
  1003. emoji: recipe[0].emoji,
  1004. }, {
  1005. text: recipe[1].text,
  1006. emoji: recipe[1].emoji,
  1007. }, recipeKey, true);
  1008. }
  1009. }
  1010. }
  1011. }
  1012. await GM.setValue('recipes', JSON.stringify(fileContents.recipes));
  1013. }
  1014. await resetDiscoveries();
  1015. const discoveredElements = cloneInto(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements, unsafeWindow).filter((el) => el.discovered === true);
  1016. for (const discoveredElement of discoveredElements) {
  1017. addElementToDiscoveries(discoveredElement);
  1018. }
  1019. await resetPinnedElements();
  1020. if (Object.keys(fileContents).includes('pinned')) {
  1021. for (let pinnedElement of fileContents.pinned) {
  1022. pinElement(cloneInto(pinnedElement, unsafeWindow), true);
  1023. }
  1024. await GM.setValue('pinned', JSON.stringify(fileContents.pinned));
  1025. }
  1026. });
  1027. const downloadContainer = document.createElement('div');
  1028. downloadContainer.classList.add('setting');
  1029. const downloadText = document.createTextNode('Export Save File');
  1030. downloadContainer.appendChild(downloadText);
  1031. const downloadImage = document.createElement('img');
  1032. downloadImage.src = downloadIcon.trim();
  1033. downloadContainer.appendChild(downloadImage);
  1034. elements.settingsContent.appendChild(downloadContainer);
  1035. downloadContainer.addEventListener('click', (e) => {
  1036. const saveFile = JSON.parse(localStorage.getItem('infinite-craft-data') ?? '');
  1037. saveFile.pinned = pinnedElements;
  1038. saveFile.recipes = recipes;
  1039. const downloadLink = document.createElement('a');
  1040. downloadLink.download = 'infinitecraft.json';
  1041. downloadLink.href = URL.createObjectURL(new Blob([JSON.stringify(saveFile, null, '\t')], {
  1042. type: 'application/json',
  1043. }));
  1044. downloadLink.dataset.downloadurl = ['application/json', downloadLink.download, downloadLink.href].join(':');
  1045. downloadLink.style.display = 'none';
  1046. document.body.appendChild(downloadLink);
  1047. downloadLink.click();
  1048. document.body.removeChild(downloadLink);
  1049. setTimeout(function () {
  1050. URL.revokeObjectURL(downloadLink.href);
  1051. }, 1500);
  1052. });
  1053. }
  1054.  
  1055. /**
  1056. * The MIT License (MIT)
  1057. *
  1058. * Copyright (c) 2015 Marin Atanasov
  1059. *
  1060. * Permission is hereby granted, free of charge, to any person obtaining a copy
  1061. * of this software and associated documentation files (the "Software"), to deal
  1062. * in the Software without restriction, including without limitation the rights
  1063. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  1064. * copies of the Software, and to permit persons to whom the Software is
  1065. * furnished to do so, subject to the following conditions:
  1066. *
  1067. * The above copyright notice and this permission notice shall be included in all
  1068. * copies or substantial portions of the Software.
  1069. *
  1070. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1071. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1072. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1073. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  1074. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  1075. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  1076. * SOFTWARE.
  1077. */
  1078. const characterMap = {
  1079. À: 'A',
  1080. Á: 'A',
  1081. Â: 'A',
  1082. Ã: 'A',
  1083. Ä: 'A',
  1084. Å: 'A',
  1085. Ấ: 'A',
  1086. Ắ: 'A',
  1087. Ẳ: 'A',
  1088. Ẵ: 'A',
  1089. Ặ: 'A',
  1090. Æ: 'AE',
  1091. Ầ: 'A',
  1092. Ằ: 'A',
  1093. Ȃ: 'A',
  1094. Ả: 'A',
  1095. Ạ: 'A',
  1096. Ẩ: 'A',
  1097. Ẫ: 'A',
  1098. Ậ: 'A',
  1099. Ç: 'C',
  1100. Ḉ: 'C',
  1101. È: 'E',
  1102. É: 'E',
  1103. Ê: 'E',
  1104. Ë: 'E',
  1105. Ế: 'E',
  1106. Ḗ: 'E',
  1107. Ề: 'E',
  1108. Ḕ: 'E',
  1109. Ḝ: 'E',
  1110. Ȇ: 'E',
  1111. Ẻ: 'E',
  1112. Ẽ: 'E',
  1113. Ẹ: 'E',
  1114. Ể: 'E',
  1115. Ễ: 'E',
  1116. Ệ: 'E',
  1117. Ì: 'I',
  1118. Í: 'I',
  1119. Î: 'I',
  1120. Ï: 'I',
  1121. Ḯ: 'I',
  1122. Ȋ: 'I',
  1123. Ỉ: 'I',
  1124. Ị: 'I',
  1125. Ð: 'D',
  1126. Ñ: 'N',
  1127. Ò: 'O',
  1128. Ó: 'O',
  1129. Ô: 'O',
  1130. Õ: 'O',
  1131. Ö: 'O',
  1132. Ø: 'O',
  1133. Ố: 'O',
  1134. Ṍ: 'O',
  1135. Ṓ: 'O',
  1136. Ȏ: 'O',
  1137. Ỏ: 'O',
  1138. Ọ: 'O',
  1139. Ổ: 'O',
  1140. Ỗ: 'O',
  1141. Ộ: 'O',
  1142. Ờ: 'O',
  1143. Ở: 'O',
  1144. Ỡ: 'O',
  1145. Ớ: 'O',
  1146. Ợ: 'O',
  1147. Ù: 'U',
  1148. Ú: 'U',
  1149. Û: 'U',
  1150. Ü: 'U',
  1151. Ủ: 'U',
  1152. Ụ: 'U',
  1153. Ử: 'U',
  1154. Ữ: 'U',
  1155. Ự: 'U',
  1156. Ý: 'Y',
  1157. à: 'a',
  1158. á: 'a',
  1159. â: 'a',
  1160. ã: 'a',
  1161. ä: 'a',
  1162. å: 'a',
  1163. ấ: 'a',
  1164. ắ: 'a',
  1165. ẳ: 'a',
  1166. ẵ: 'a',
  1167. ặ: 'a',
  1168. æ: 'ae',
  1169. ầ: 'a',
  1170. ằ: 'a',
  1171. ȃ: 'a',
  1172. ả: 'a',
  1173. ạ: 'a',
  1174. ẩ: 'a',
  1175. ẫ: 'a',
  1176. ậ: 'a',
  1177. ç: 'c',
  1178. ḉ: 'c',
  1179. è: 'e',
  1180. é: 'e',
  1181. ê: 'e',
  1182. ë: 'e',
  1183. ế: 'e',
  1184. ḗ: 'e',
  1185. ề: 'e',
  1186. ḕ: 'e',
  1187. ḝ: 'e',
  1188. ȇ: 'e',
  1189. ẻ: 'e',
  1190. ẽ: 'e',
  1191. ẹ: 'e',
  1192. ể: 'e',
  1193. ễ: 'e',
  1194. ệ: 'e',
  1195. ì: 'i',
  1196. í: 'i',
  1197. î: 'i',
  1198. ï: 'i',
  1199. ḯ: 'i',
  1200. ȋ: 'i',
  1201. ỉ: 'i',
  1202. ị: 'i',
  1203. ð: 'd',
  1204. ñ: 'n',
  1205. ò: 'o',
  1206. ó: 'o',
  1207. ô: 'o',
  1208. õ: 'o',
  1209. ö: 'o',
  1210. ø: 'o',
  1211. ố: 'o',
  1212. ṍ: 'o',
  1213. ṓ: 'o',
  1214. ȏ: 'o',
  1215. ỏ: 'o',
  1216. ọ: 'o',
  1217. ổ: 'o',
  1218. ỗ: 'o',
  1219. ộ: 'o',
  1220. ờ: 'o',
  1221. ở: 'o',
  1222. ỡ: 'o',
  1223. ớ: 'o',
  1224. ợ: 'o',
  1225. ù: 'u',
  1226. ú: 'u',
  1227. û: 'u',
  1228. ü: 'u',
  1229. ủ: 'u',
  1230. ụ: 'u',
  1231. ử: 'u',
  1232. ữ: 'u',
  1233. ự: 'u',
  1234. ý: 'y',
  1235. ÿ: 'y',
  1236. Ā: 'A',
  1237. ā: 'a',
  1238. Ă: 'A',
  1239. ă: 'a',
  1240. Ą: 'A',
  1241. ą: 'a',
  1242. Ć: 'C',
  1243. ć: 'c',
  1244. Ĉ: 'C',
  1245. ĉ: 'c',
  1246. Ċ: 'C',
  1247. ċ: 'c',
  1248. Č: 'C',
  1249. č: 'c',
  1250. C̆: 'C',
  1251. c̆: 'c',
  1252. Ď: 'D',
  1253. ď: 'd',
  1254. Đ: 'D',
  1255. đ: 'd',
  1256. Ē: 'E',
  1257. ē: 'e',
  1258. Ĕ: 'E',
  1259. ĕ: 'e',
  1260. Ė: 'E',
  1261. ė: 'e',
  1262. Ę: 'E',
  1263. ę: 'e',
  1264. Ě: 'E',
  1265. ě: 'e',
  1266. Ĝ: 'G',
  1267. Ǵ: 'G',
  1268. ĝ: 'g',
  1269. ǵ: 'g',
  1270. Ğ: 'G',
  1271. ğ: 'g',
  1272. Ġ: 'G',
  1273. ġ: 'g',
  1274. Ģ: 'G',
  1275. ģ: 'g',
  1276. Ĥ: 'H',
  1277. ĥ: 'h',
  1278. Ħ: 'H',
  1279. ħ: 'h',
  1280. Ḫ: 'H',
  1281. ḫ: 'h',
  1282. Ĩ: 'I',
  1283. ĩ: 'i',
  1284. Ī: 'I',
  1285. ī: 'i',
  1286. Ĭ: 'I',
  1287. ĭ: 'i',
  1288. Į: 'I',
  1289. į: 'i',
  1290. İ: 'I',
  1291. ı: 'i',
  1292. IJ: 'IJ',
  1293. ij: 'ij',
  1294. Ĵ: 'J',
  1295. ĵ: 'j',
  1296. Ķ: 'K',
  1297. ķ: 'k',
  1298. Ḱ: 'K',
  1299. ḱ: 'k',
  1300. K̆: 'K',
  1301. k̆: 'k',
  1302. Ĺ: 'L',
  1303. ĺ: 'l',
  1304. Ļ: 'L',
  1305. ļ: 'l',
  1306. Ľ: 'L',
  1307. ľ: 'l',
  1308. Ŀ: 'L',
  1309. ŀ: 'l',
  1310. Ł: 'l',
  1311. ł: 'l',
  1312. Ḿ: 'M',
  1313. ḿ: 'm',
  1314. M̆: 'M',
  1315. m̆: 'm',
  1316. Ń: 'N',
  1317. ń: 'n',
  1318. Ņ: 'N',
  1319. ņ: 'n',
  1320. Ň: 'N',
  1321. ň: 'n',
  1322. ʼn: 'n',
  1323. N̆: 'N',
  1324. n̆: 'n',
  1325. Ō: 'O',
  1326. ō: 'o',
  1327. Ŏ: 'O',
  1328. ŏ: 'o',
  1329. Ő: 'O',
  1330. ő: 'o',
  1331. Œ: 'OE',
  1332. œ: 'oe',
  1333. P̆: 'P',
  1334. p̆: 'p',
  1335. Ŕ: 'R',
  1336. ŕ: 'r',
  1337. Ŗ: 'R',
  1338. ŗ: 'r',
  1339. Ř: 'R',
  1340. ř: 'r',
  1341. R̆: 'R',
  1342. r̆: 'r',
  1343. Ȓ: 'R',
  1344. ȓ: 'r',
  1345. Ś: 'S',
  1346. ś: 's',
  1347. Ŝ: 'S',
  1348. ŝ: 's',
  1349. Ş: 'S',
  1350. Ș: 'S',
  1351. ș: 's',
  1352. ş: 's',
  1353. Š: 'S',
  1354. š: 's',
  1355. Ţ: 'T',
  1356. ţ: 't',
  1357. ț: 't',
  1358. Ț: 'T',
  1359. Ť: 'T',
  1360. ť: 't',
  1361. Ŧ: 'T',
  1362. ŧ: 't',
  1363. T̆: 'T',
  1364. t̆: 't',
  1365. Ũ: 'U',
  1366. ũ: 'u',
  1367. Ū: 'U',
  1368. ū: 'u',
  1369. Ŭ: 'U',
  1370. ŭ: 'u',
  1371. Ů: 'U',
  1372. ů: 'u',
  1373. Ű: 'U',
  1374. ű: 'u',
  1375. Ų: 'U',
  1376. ų: 'u',
  1377. Ȗ: 'U',
  1378. ȗ: 'u',
  1379. V̆: 'V',
  1380. v̆: 'v',
  1381. Ŵ: 'W',
  1382. ŵ: 'w',
  1383. Ẃ: 'W',
  1384. ẃ: 'w',
  1385. X̆: 'X',
  1386. x̆: 'x',
  1387. Ŷ: 'Y',
  1388. ŷ: 'y',
  1389. Ÿ: 'Y',
  1390. Y̆: 'Y',
  1391. y̆: 'y',
  1392. Ź: 'Z',
  1393. ź: 'z',
  1394. Ż: 'Z',
  1395. ż: 'z',
  1396. Ž: 'Z',
  1397. ž: 'z',
  1398. ſ: 's',
  1399. ƒ: 'f',
  1400. Ơ: 'O',
  1401. ơ: 'o',
  1402. Ư: 'U',
  1403. ư: 'u',
  1404. Ǎ: 'A',
  1405. ǎ: 'a',
  1406. Ǐ: 'I',
  1407. ǐ: 'i',
  1408. Ǒ: 'O',
  1409. ǒ: 'o',
  1410. Ǔ: 'U',
  1411. ǔ: 'u',
  1412. Ǖ: 'U',
  1413. ǖ: 'u',
  1414. Ǘ: 'U',
  1415. ǘ: 'u',
  1416. Ǚ: 'U',
  1417. ǚ: 'u',
  1418. Ǜ: 'U',
  1419. ǜ: 'u',
  1420. Ứ: 'U',
  1421. ứ: 'u',
  1422. Ṹ: 'U',
  1423. ṹ: 'u',
  1424. Ǻ: 'A',
  1425. ǻ: 'a',
  1426. Ǽ: 'AE',
  1427. ǽ: 'ae',
  1428. Ǿ: 'O',
  1429. ǿ: 'o',
  1430. Þ: 'TH',
  1431. þ: 'th',
  1432. Ṕ: 'P',
  1433. ṕ: 'p',
  1434. Ṥ: 'S',
  1435. ṥ: 's',
  1436. X́: 'X',
  1437. x́: 'x',
  1438. Ѓ: 'Г',
  1439. ѓ: 'г',
  1440. Ќ: 'К',
  1441. ќ: 'к',
  1442. A̋: 'A',
  1443. a̋: 'a',
  1444. E̋: 'E',
  1445. e̋: 'e',
  1446. I̋: 'I',
  1447. i̋: 'i',
  1448. Ǹ: 'N',
  1449. ǹ: 'n',
  1450. Ồ: 'O',
  1451. ồ: 'o',
  1452. Ṑ: 'O',
  1453. ṑ: 'o',
  1454. Ừ: 'U',
  1455. ừ: 'u',
  1456. Ẁ: 'W',
  1457. ẁ: 'w',
  1458. Ỳ: 'Y',
  1459. ỳ: 'y',
  1460. Ȁ: 'A',
  1461. ȁ: 'a',
  1462. Ȅ: 'E',
  1463. ȅ: 'e',
  1464. Ȉ: 'I',
  1465. ȉ: 'i',
  1466. Ȍ: 'O',
  1467. ȍ: 'o',
  1468. Ȑ: 'R',
  1469. ȑ: 'r',
  1470. Ȕ: 'U',
  1471. ȕ: 'u',
  1472. B̌: 'B',
  1473. b̌: 'b',
  1474. Č̣: 'C',
  1475. č̣: 'c',
  1476. Ê̌: 'E',
  1477. ê̌: 'e',
  1478. F̌: 'F',
  1479. f̌: 'f',
  1480. Ǧ: 'G',
  1481. ǧ: 'g',
  1482. Ȟ: 'H',
  1483. ȟ: 'h',
  1484. J̌: 'J',
  1485. ǰ: 'j',
  1486. Ǩ: 'K',
  1487. ǩ: 'k',
  1488. M̌: 'M',
  1489. m̌: 'm',
  1490. P̌: 'P',
  1491. p̌: 'p',
  1492. Q̌: 'Q',
  1493. q̌: 'q',
  1494. Ř̩: 'R',
  1495. ř̩: 'r',
  1496. Ṧ: 'S',
  1497. ṧ: 's',
  1498. V̌: 'V',
  1499. v̌: 'v',
  1500. W̌: 'W',
  1501. w̌: 'w',
  1502. X̌: 'X',
  1503. x̌: 'x',
  1504. Y̌: 'Y',
  1505. y̌: 'y',
  1506. A̧: 'A',
  1507. a̧: 'a',
  1508. B̧: 'B',
  1509. b̧: 'b',
  1510. Ḑ: 'D',
  1511. ḑ: 'd',
  1512. Ȩ: 'E',
  1513. ȩ: 'e',
  1514. Ɛ̧: 'E',
  1515. ɛ̧: 'e',
  1516. Ḩ: 'H',
  1517. ḩ: 'h',
  1518. I̧: 'I',
  1519. i̧: 'i',
  1520. Ɨ̧: 'I',
  1521. ɨ̧: 'i',
  1522. M̧: 'M',
  1523. m̧: 'm',
  1524. O̧: 'O',
  1525. o̧: 'o',
  1526. Q̧: 'Q',
  1527. q̧: 'q',
  1528. U̧: 'U',
  1529. u̧: 'u',
  1530. X̧: 'X',
  1531. x̧: 'x',
  1532. Z̧: 'Z',
  1533. z̧: 'z',
  1534. й: 'и',
  1535. Й: 'И',
  1536. ё: 'е',
  1537. Ё: 'Е',
  1538. };
  1539. const removeAccentsRegex = new RegExp(Object.keys(characterMap).join('|'), 'g');
  1540. function removeAccents(string) {
  1541. return string.replace(removeAccentsRegex, (char) => {
  1542. return characterMap[char];
  1543. });
  1544. }
  1545. const rankings = {
  1546. CASE_SENSITIVE_EQUAL: 7,
  1547. EQUAL: 6,
  1548. STARTS_WITH: 5,
  1549. WORD_STARTS_WITH: 4,
  1550. CONTAINS: 3,
  1551. ACRONYM: 2,
  1552. MATCHES: 1,
  1553. NO_MATCH: 0,
  1554. };
  1555. const defaultBaseSortFn = (a, b) => String(a.rankedValue).localeCompare(String(b.rankedValue));
  1556. function matchSorter(items, value, options = {}) {
  1557. const { keys, threshold = rankings.MATCHES, baseSort = defaultBaseSortFn, sorter = (matchedItems) => matchedItems.sort((a, b) => sortRankedValues(a, b, baseSort)), } = options;
  1558. const matchedItems = items.reduce(reduceItemsToRanked, []);
  1559. return sorter(matchedItems).map(({ item }) => item);
  1560. function reduceItemsToRanked(matches, item, index) {
  1561. const rankingInfo = getHighestRanking(item, keys, value, options);
  1562. const { rank, keyThreshold = threshold } = rankingInfo;
  1563. if (rank >= keyThreshold) {
  1564. matches.push({ ...rankingInfo, item, index });
  1565. }
  1566. return matches;
  1567. }
  1568. }
  1569. matchSorter.rankings = rankings;
  1570. function getHighestRanking(item, keys, value, options) {
  1571. if (!keys) {
  1572. const stringItem = item;
  1573. return {
  1574. rankedValue: stringItem,
  1575. rank: getMatchRanking(stringItem, value, options),
  1576. keyIndex: -1,
  1577. keyThreshold: options.threshold,
  1578. };
  1579. }
  1580. const valuesToRank = getAllValuesToRank(item, keys);
  1581. return valuesToRank.reduce(({ rank, rankedValue, keyIndex, keyThreshold }, { itemValue, attributes }, i) => {
  1582. let newRank = getMatchRanking(itemValue, value, options);
  1583. let newRankedValue = rankedValue;
  1584. const { minRanking, maxRanking, threshold } = attributes;
  1585. if (newRank < minRanking && newRank >= rankings.MATCHES) {
  1586. newRank = minRanking;
  1587. }
  1588. else if (newRank > maxRanking) {
  1589. newRank = maxRanking;
  1590. }
  1591. if (newRank > rank) {
  1592. rank = newRank;
  1593. keyIndex = i;
  1594. keyThreshold = threshold;
  1595. newRankedValue = itemValue;
  1596. }
  1597. return { rankedValue: newRankedValue, rank, keyIndex, keyThreshold };
  1598. }, {
  1599. rankedValue: item,
  1600. rank: rankings.NO_MATCH,
  1601. keyIndex: -1,
  1602. keyThreshold: options.threshold,
  1603. });
  1604. }
  1605. function getMatchRanking(testString, stringToRank, options) {
  1606. testString = prepareValueForComparison(testString, options);
  1607. stringToRank = prepareValueForComparison(stringToRank, options);
  1608. if (stringToRank.length > testString.length) {
  1609. return rankings.NO_MATCH;
  1610. }
  1611. if (testString === stringToRank) {
  1612. return rankings.CASE_SENSITIVE_EQUAL;
  1613. }
  1614. testString = testString.toLowerCase();
  1615. stringToRank = stringToRank.toLowerCase();
  1616. if (testString === stringToRank) {
  1617. return rankings.EQUAL;
  1618. }
  1619. if (testString.startsWith(stringToRank)) {
  1620. return rankings.STARTS_WITH;
  1621. }
  1622. if (testString.includes(` ${stringToRank}`)) {
  1623. return rankings.WORD_STARTS_WITH;
  1624. }
  1625. if (testString.includes(stringToRank)) {
  1626. return rankings.CONTAINS;
  1627. }
  1628. else if (stringToRank.length === 1) {
  1629. return rankings.NO_MATCH;
  1630. }
  1631. if (getAcronym(testString).includes(stringToRank)) {
  1632. return rankings.ACRONYM;
  1633. }
  1634. return getClosenessRanking(testString, stringToRank);
  1635. }
  1636. function getAcronym(string) {
  1637. let acronym = '';
  1638. const wordsInString = string.split(' ');
  1639. for (const wordInString of wordsInString) {
  1640. const splitByHyphenWords = wordInString.split('-');
  1641. for (const splitByHyphenWord of splitByHyphenWords) {
  1642. acronym += splitByHyphenWord.substr(0, 1);
  1643. }
  1644. }
  1645. return acronym;
  1646. }
  1647. function getClosenessRanking(testString, stringToRank) {
  1648. let matchingInOrderCharCount = 0;
  1649. let charNumber = 0;
  1650. function findMatchingCharacter(matchChar, string, index) {
  1651. for (let j = index, J = string.length; j < J; j++) {
  1652. const stringChar = string[j];
  1653. if (stringChar === matchChar) {
  1654. matchingInOrderCharCount += 1;
  1655. return j + 1;
  1656. }
  1657. }
  1658. return -1;
  1659. }
  1660. function getRanking(spread) {
  1661. const spreadPercentage = 1 / spread;
  1662. const inOrderPercentage = matchingInOrderCharCount / stringToRank.length;
  1663. const ranking = rankings.MATCHES + inOrderPercentage * spreadPercentage;
  1664. return ranking;
  1665. }
  1666. const firstIndex = findMatchingCharacter(stringToRank[0], testString, 0);
  1667. if (firstIndex < 0) {
  1668. return rankings.NO_MATCH;
  1669. }
  1670. charNumber = firstIndex;
  1671. for (let i = 1, I = stringToRank.length; i < I; i++) {
  1672. const matchChar = stringToRank[i];
  1673. charNumber = findMatchingCharacter(matchChar, testString, charNumber);
  1674. const found = charNumber > -1;
  1675. if (!found) {
  1676. return rankings.NO_MATCH;
  1677. }
  1678. }
  1679. const spread = charNumber - firstIndex;
  1680. return getRanking(spread);
  1681. }
  1682. function sortRankedValues(a, b, baseSort) {
  1683. const aFirst = -1;
  1684. const bFirst = 1;
  1685. const { rank: aRank, keyIndex: aKeyIndex } = a;
  1686. const { rank: bRank, keyIndex: bKeyIndex } = b;
  1687. const same = aRank === bRank;
  1688. if (same) {
  1689. if (aKeyIndex === bKeyIndex) {
  1690. return baseSort(a, b);
  1691. }
  1692. else {
  1693. return aKeyIndex < bKeyIndex ? aFirst : bFirst;
  1694. }
  1695. }
  1696. else {
  1697. return aRank > bRank ? aFirst : bFirst;
  1698. }
  1699. }
  1700. function prepareValueForComparison(value, { keepDiacritics }) {
  1701. value = `${value}`;
  1702. if (!keepDiacritics) {
  1703. value = removeAccents(value);
  1704. }
  1705. return value;
  1706. }
  1707. function getItemValues(item, key) {
  1708. if (typeof key === 'object') {
  1709. key = key.key;
  1710. }
  1711. let value;
  1712. if (typeof key === 'function') {
  1713. value = key(item);
  1714. }
  1715. else if (item == null) {
  1716. value = null;
  1717. }
  1718. else if (Object.hasOwn(item, key)) {
  1719. value = item[key];
  1720. }
  1721. else if (key.includes('.')) {
  1722. return getNestedValues(key, item);
  1723. }
  1724. else {
  1725. value = null;
  1726. }
  1727. if (value == null) {
  1728. return [];
  1729. }
  1730. if (Array.isArray(value)) {
  1731. return value;
  1732. }
  1733. return [String(value)];
  1734. }
  1735. function getNestedValues(path, item) {
  1736. const keys = path.split('.');
  1737. let values = [item];
  1738. for (let i = 0, I = keys.length; i < I; i++) {
  1739. const nestedKey = keys[i];
  1740. let nestedValues = [];
  1741. for (let j = 0, J = values.length; j < J; j++) {
  1742. const nestedItem = values[j];
  1743. if (nestedItem == null)
  1744. continue;
  1745. if (Object.hasOwn(nestedItem, nestedKey)) {
  1746. const nestedValue = nestedItem[nestedKey];
  1747. if (nestedValue != null) {
  1748. nestedValues.push(nestedValue);
  1749. }
  1750. }
  1751. else if (nestedKey === '*') {
  1752. nestedValues = nestedValues.concat(nestedItem);
  1753. }
  1754. }
  1755. values = nestedValues;
  1756. }
  1757. if (Array.isArray(values[0])) {
  1758. const result = [];
  1759. return result.concat(...values);
  1760. }
  1761. return values;
  1762. }
  1763. function getAllValuesToRank(item, keys) {
  1764. const allValues = [];
  1765. for (let j = 0, J = keys.length; j < J; j++) {
  1766. const key = keys[j];
  1767. const attributes = getKeyAttributes(key);
  1768. const itemValues = getItemValues(item, key);
  1769. for (let i = 0, I = itemValues.length; i < I; i++) {
  1770. allValues.push({
  1771. itemValue: itemValues[i],
  1772. attributes,
  1773. });
  1774. }
  1775. }
  1776. return allValues;
  1777. }
  1778. const defaultKeyAttributes = {
  1779. maxRanking: Infinity,
  1780. minRanking: -Infinity,
  1781. };
  1782. function getKeyAttributes(key) {
  1783. if (typeof key === 'string') {
  1784. return defaultKeyAttributes;
  1785. }
  1786. return { ...defaultKeyAttributes, ...key };
  1787. }
  1788.  
  1789. function init$3(elements) {
  1790. elements.sidebarHeader.prepend(elements.searchBar);
  1791. window.addEventListener('keydown', () => {
  1792. if (document.activeElement !== elements.searchBar) {
  1793. elements.searchBar.focus();
  1794. }
  1795. });
  1796. elements.searchBar.addEventListener('input', (e) => {
  1797. if (e.inputType === 'insertText' &&
  1798. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.searchQuery.trim().length === 1) {
  1799. elements.sidebar.scrollTo(0, 0);
  1800. }
  1801. });
  1802. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._computedWatchers.sortedElements.getter =
  1803. exportFunction(() => {
  1804. const query = unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.searchQuery.trim();
  1805. if (query === '') {
  1806. const elements = [...unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements];
  1807. if (unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.showDiscoveredOnly) {
  1808. return cloneInto(elements.filter((el) => el.discovered), unsafeWindow);
  1809. }
  1810. if (unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.sortBy === 'name') {
  1811. return cloneInto(elements, unsafeWindow).sort((a, b) => a.text.localeCompare(b.text, undefined, { numeric: true }));
  1812. }
  1813. if (unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.sortBy === 'emoji') {
  1814. return cloneInto(elements, unsafeWindow).sort((a, b) => {
  1815. const emojiA = a.emoji ?? '⬜';
  1816. const emojiB = b.emoji ?? '⬜';
  1817. return emojiA.localeCompare(emojiB);
  1818. });
  1819. }
  1820. return unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements;
  1821. }
  1822. else {
  1823. return cloneInto(matchSorter(cloneInto(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements, unsafeWindow), unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.searchQuery, {
  1824. keys: ['text'],
  1825. }), unsafeWindow);
  1826. }
  1827. }, unsafeWindow);
  1828. }
  1829.  
  1830. function init$2(elements) {
  1831. const randomImage = document.createElement('img');
  1832. randomImage.src = randomIcon.trim();
  1833. randomImage.classList.add('random');
  1834. elements.sideControls.appendChild(randomImage);
  1835. randomImage.addEventListener('click', (e) => {
  1836. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].playInstanceSound();
  1837. const randomElement = unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements[Math.floor(Math.random() * unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.elements.length)];
  1838. const data = {
  1839. id: unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.instanceId++,
  1840. text: randomElement.text,
  1841. emoji: randomElement.emoji,
  1842. discovered: randomElement.discovered,
  1843. disabled: false,
  1844. left: 0,
  1845. top: 0,
  1846. offsetX: 0.5,
  1847. offsetY: 0.5,
  1848. };
  1849. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance = cloneInto(data, unsafeWindow);
  1850. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.instances.push(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance);
  1851. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].$nextTick(exportFunction(() => {
  1852. const randomPosition = Math.random() * Math.PI * 2;
  1853. const cos = 50 * Math.cos(randomPosition);
  1854. const sin = 50 * Math.sin(randomPosition);
  1855. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].setInstancePosition(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance, (window.innerWidth - unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.sidebarSize) / 2 +
  1856. cos, window.innerHeight / 2 - 40 + sin);
  1857. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].setInstanceZIndex(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance, data.id);
  1858. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].calcInstanceSize(unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.selectedInstance);
  1859. }, unsafeWindow));
  1860. });
  1861. }
  1862.  
  1863. function init$1(elements) {
  1864. elements.logo.src = logo.trim();
  1865. const versionNumber = document.createElement('p');
  1866. versionNumber.appendChild(document.createTextNode(`v${GM.info.script.version}`));
  1867. versionNumber.classList.add('version');
  1868. elements.logo.after(versionNumber);
  1869. }
  1870.  
  1871. let theme = 'shadow';
  1872. const shadowCSS = `
  1873. .container.dark-mode {
  1874. --border-color: #525252 !important;
  1875. --item-bg: #18181b !important;
  1876. --instance-bg: linear-gradient(180deg,#22252b,#18181b 80%) !important;
  1877. --instance-bg-hover: linear-gradient(180deg,#3d4249,#18181b 80%) !important;
  1878. --instance-border: #525252 !important;
  1879. --instance-border-hover: #a3a3a3 !important;
  1880. --sidebar-bg: #18181b !important;
  1881. --background-color: #18181b !important;
  1882. --discoveries-bg-active: #423a24 !important;
  1883. --text-color: #fff !important;
  1884. }
  1885.  
  1886. .dark-mode {
  1887. scrollbar-color: #525252 #262626 !important;
  1888. }
  1889.  
  1890. .dark-mode .sidebar-controls:after {
  1891. background: linear-gradient(180deg, rgba(24,24,27,0), rgba(24,24,27,.9)) !important;
  1892. }
  1893. `;
  1894. const shadowStyles = document.createElement('style');
  1895. shadowStyles.appendChild(document.createTextNode(shadowCSS.trim()));
  1896. async function init(elements) {
  1897. const oldTheme = localStorage.getItem('theme');
  1898. if (oldTheme !== null && oldTheme === 'light')
  1899. theme = 'light';
  1900. localStorage.removeItem('theme');
  1901. const storedTheme = await GM.getValue('theme');
  1902. if (storedTheme === 'light')
  1903. theme = 'light';
  1904. if (storedTheme === 'dark')
  1905. theme = 'dark';
  1906. await GM.setValue('theme', theme);
  1907. if (theme === 'light' && unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.isDarkMode) {
  1908. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].toggleDarkMode();
  1909. }
  1910. else if (theme === 'shadow' && !unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.isDarkMode) {
  1911. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].toggleDarkMode();
  1912. }
  1913. else if (theme === 'dark' && !unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0]._data.isDarkMode) {
  1914. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].toggleDarkMode();
  1915. }
  1916. if (theme === 'shadow') {
  1917. document.getElementsByTagName('head')[0].appendChild(shadowStyles);
  1918. }
  1919. const darkModeIcon = elements.darkModeIcon.cloneNode(true);
  1920. darkModeIcon.src = shadowIcon;
  1921. if (theme === 'light')
  1922. darkModeIcon.src = '/infinite-craft/dark-mode.svg';
  1923. if (theme === 'dark')
  1924. darkModeIcon.src = '/infinite-craft/dark-mode-on.svg';
  1925. elements.darkModeIcon.parentNode?.replaceChild(darkModeIcon, elements.darkModeIcon);
  1926. const toggleDarkMode = unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].toggleDarkMode;
  1927. unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].toggleDarkMode = exportFunction(async () => {
  1928. if (theme === 'light') {
  1929. toggleDarkMode();
  1930. darkModeIcon.src = shadowIcon;
  1931. document.getElementsByTagName('head')[0].appendChild(shadowStyles);
  1932. theme = 'shadow';
  1933. }
  1934. else if (theme === 'shadow') {
  1935. darkModeIcon.src = '/infinite-craft/dark-mode-on.svg';
  1936. shadowStyles.remove();
  1937. theme = 'dark';
  1938. }
  1939. else if (theme === 'dark') {
  1940. toggleDarkMode();
  1941. darkModeIcon.src = '/infinite-craft/dark-mode.svg';
  1942. theme = 'light';
  1943. }
  1944. await GM.setValue('theme', theme);
  1945. }, unsafeWindow);
  1946. darkModeIcon.addEventListener('click', unsafeWindow.$nuxt.$root.$children[1].$children[0].$children[0].toggleDarkMode);
  1947. }
  1948.  
  1949. window.addEventListener('load', async () => {
  1950. const sidebarHeader = document.createElement('div');
  1951. sidebarHeader.classList.add('sidebar-header');
  1952. const settingsContent = document.createElement('div');
  1953. settingsContent.classList.add('settings-content');
  1954. const elements = {
  1955. favicon: document.querySelector('link[rel="icon"]'),
  1956. container: document.querySelector('.container'),
  1957. instances: document.querySelector('.instances'),
  1958. styles: document.createElement('style'),
  1959. sideControls: document.querySelector('.side-controls'),
  1960. darkModeIcon: document.querySelector('.dark-mode-icon'),
  1961. sidebar: document.querySelector('.sidebar'),
  1962. sidebarHeader: sidebarHeader,
  1963. searchBar: document.querySelector('.sidebar-search'),
  1964. settingsContent: settingsContent,
  1965. items: document.querySelector('.items'),
  1966. getItems: () => {
  1967. return Array.from(document.querySelectorAll('.items div.item'));
  1968. },
  1969. instruction: document.querySelector('.instruction'),
  1970. sort: document.querySelector('.sort'),
  1971. particles: document.querySelector('.particles'),
  1972. logo: document.querySelector('.logo'),
  1973. };
  1974. elements.items.before(elements.sidebarHeader);
  1975. init$d(elements);
  1976. init$c(elements);
  1977. init$b(elements);
  1978. init$6(elements);
  1979. init$8(elements);
  1980. init$5(elements);
  1981. init$4(elements);
  1982. init$3(elements);
  1983. init$7(elements);
  1984. init$2(elements);
  1985. await init$a(elements);
  1986. init$9(elements);
  1987. init$1(elements);
  1988. init(elements);
  1989. }, false);
  1990. window.addEventListener('contextmenu', (e) => {
  1991. e.preventDefault();
  1992. });
  1993.  
  1994. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址