// ==UserScript== // @name GitHub 阅读助手 // @name:zh-CN GitHub 阅读助手 // @name:en GitHub Enhancer Tools // @description 增强功能:一键查看仓库主页、仓库封面、仓库分析,一键仓库智能分析,一键下载文件和文件夹,一键预览 HTML 文件,一键 JSdelivr 浏览仓库。 // @description:zh-CN 增强功能:一键查看仓库主页、仓库封面、仓库分析,一键仓库智能分析,一键下载文件和文件夹,一键预览 HTML 文件,一键 JSdelivr 浏览仓库。 // @description:en Enhanced Features: One-click access to repository homepage, repository cover and repository analysis; one-click intelligent repository analysis; one-click download of files and folders; one-click preview of HTML files; one-click browsing of repositories via JSDelivr. // @namespace https://www.runningcheese.com/userscripts // @author RunningCheese // @version 1.0 // @match https://github.com/* // @icon https://t1.gstatic.cn/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://github.com // @license MIT // ==/UserScript== (function () { 'use strict' const iconUrl = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2aWV3Qm94PSIwIDAgNTAwIDUwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAxLCAtMi4zNDkwMDQ5ODM5MDE5Nzc1LCAtMTIuNDc0OTk1NjEzMDk4MDg4KSI+CiAgICA8cGF0aCBkPSJNIDI0OS43NDkgMjQuOTUgTCAyMDUuNDcyIDE4Mi4zMDEgTCAyMDUuNDcyIDM0MS4xNTMgTCAyNDkuNzQ5IDUwMCBMIDI5NS4yNzkgMzQxLjE1MyBMIDI5NS4yNzkgMTgyLjMwMSBMIDI0OS43NDkgMjQuOTUgWiIgY2xhc3M9InN0MSIgc3R5bGU9ImZpbGw6IHJnYigxODksIDcyLCA1OSk7Ii8+CiAgICA8cGF0aCBmaWxsPSIjZTY0ZTNkIiBkPSJNIDI0OS43NDkgMjQuOTUgTCAzMC40MTMgMTAzLjk1MiBMIDYxLjU3NyAzOTYuMDc4IEwgMjQ5Ljc0OSA1MDAiIHN0eWxlPSIiLz4KICAgIDxwYXRoIGQ9Ik0gMjQ5Ljc0OSA1MDAgTCA0MzguODg4IDM5NS4wMSBMIDQ3NC4yODUgMTAyLjkxMyBMIDI0OS43NDkgMjQuOTUiIGNsYXNzPSJzdDEiIHN0eWxlPSJmaWxsOiByZ2IoMTg5LCA3MiwgNTkpOyIvPgogICAgPHBhdGggZD0iTSAyMDkuOTQ3IDM3Ny43NzUgQyAxODguNjE2IDM3MS4xMDYgMTY5LjMwOCAzNTkuMTkgMTUzLjc3OCAzNDMuMTE3IEwgMTUzLjczOSAzNDMuMDg4IEMgMTM4LjkwNiAzMjcuNzgzIDEyNy45NjIgMzA5LjEzNSAxMjEuODMyIDI4OC43MiBDIDEyNS40MjYgMjkyLjAyOCAxMjkuMjEgMjk1LjEwMyAxMzMuMTgxIDI5Ny45NDMgQyAxMzMuMjM4IDI5OC4wNDkgMTMzLjI5MSAyOTguMTc3IDEzMy4zMzkgMjk4LjMyOSBDIDEzMy4yOTEgMjk4LjE2NyAxMzMuMjM4IDI5OC4wMzggMTMzLjE4MSAyOTcuOTQzIEMgMTQwLjcyMyAzMDMuMjIgMTQ4LjgzIDMwNy42MzQgMTU3LjM1NyAzMTEuMDk5IEMgMTU5Ljg5OCAzMTIuMSAxNjIuNDcxIDMxMy4wMjUgMTY1LjA4NCAzMTMuODc5IEMgMTY1LjI0MiAzMTMuOTY0IDE2NS40MjcgMzEzLjk2NCAxNjUuNTg0IDMxNC4wMjEgQyAxNjYuMDM3IDMxNC4xOTMgMTY2LjQ5OSAzMTQuMzUgMTY2Ljk2NyAzMTQuNDk0IEMgMTY4LjA0NCAzMjUuMjYgMTc2LjEyOSAzMzQuMDEyIDE4Ni43ODIgMzM1LjkzMyBDIDE5MC44NzEgMzUyLjQyNSAxOTguNjU2IDM2Ni41MjUgMjA5Ljk0NyAzNzcuNzc1IE0gMjE4LjIxMiAxODguMjU5IEMgMjE4LjIxMiAxOTIuODc4IDIxOS40NzEgMTk3LjIwMSAyMjEuNjc4IDIwMC44NDggQyAyMDMuODYgMjI1LjgzOSAxOTEuNjMgMjUyLjk2NiAxODYuMzM4IDI3OS44MTEgQyAxODUuNzUyIDI4Mi43OTYgMTg1LjI1MiAyODUuNzM2IDE4NC44NDIgMjg4LjYzNSBDIDE3OC43MjYgMjkwLjI0NiAxNzMuNTgzIDI5NC4yMzUgMTcwLjM2IDI5OS40OTggQyAxNzAuMTg0IDI5OS40NzggMTcwLjAxNyAyOTkuNDMgMTY5Ljg2IDI5OS4zNTQgQyAxNjkuNTMxIDI5OS4yNjggMTY5LjI4OCAyOTkuMTU1IDE2OC45OTMgMjk5LjA1NCBDIDE1My45OTIgMjk0LjEwMiAxNDAuMzQ1IDI4NS43MzEgMTI5LjEzNSAyNzQuNjA2IEMgMTI3LjYwNCAyNzMuMDc2IDEyNi4xMjYgMjcxLjQ5OSAxMjQuNjk3IDI2OS44NzMgTCAxMjQuMTE2IDI2OS4xNzcgTCAxMjIuNDc2IDI2Ny4yMjMgTCAxMjEuODAzIDI2Ni4zNzkgQyAxMjEuNjEzIDI2Ni4xMzYgMTIxLjQ0MiAyNjUuOTIxIDEyMS4yNzggMjY1Ljc0MSBMIDEyMS4wMzUgMjY1LjQxMiBDIDEyMC43NSAyNjUuMDc3IDEyMC40OTggMjY0Ljc1OSAxMjAuMjc4IDI2NC40NDQgTCAxMTkuOTU0IDI2NC4wMjkgTCAxMTkuODk3IDI2My45MTQgQyAxMTkuNzEgMjYzLjcxNCAxMTkuNTU0IDI2My40NDMgMTE5LjM2OCAyNjMuMjE4IEMgMTE4LjU4NiAyNjIuMTc1IDExNy44MzggMjYxLjEwMyAxMTcuMTI4IDI2MC4wMTEgQyAxMTYuOTg5IDI1OS44NDggMTE2Ljg3IDI1OS42NjMgMTE2Ljc3NSAyNTkuNDUzIEwgMTE2LjQ4OSAyNTkuMDY3IEMgMTE0LjE1MyAyMjQuMjg5IDEyNS41NTQgMTg5Ljk4IDE0OC4yMzQgMTYzLjUxNiBDIDE2NC40NiAxNDQuNTE2IDE4NS42OTQgMTMwLjQ1NSAyMDkuNTE4IDEyMi45MjcgQyAyMDkuOSAxMjUuNTMxIDIxMC4zNTIgMTI4LjE2MiAyMTAuODcyIDEzMC44MTEgQyAyMTMuNjA5IDE0NC41OTcgMjE4LjE4NCAxNTguNDk2IDIyNC40IDE3Mi4xMjQgQyAyMjAuNTM5IDE3Ni4zOTkgMjE4LjIxMiAxODIuMDcyIDIxOC4yMTIgMTg4LjI1OSBNIDIwMy45OSAzMTIuMDcyIEMgMjA0LjAxOCAzMTUuNzkgMjAyLjQxMSAzMTkuMzMxIDE5OS41OTkgMzIxLjc2MyBDIDE5NS4zNTYgMzI1LjQ5NCAxODkuMTc0IDMyNi4wMTkgMTg0LjM3NCAzMjMuMDQ1IEMgMTgyLjI2OCAzMjEuNzY2IDE4MC41NzYgMzE5LjkxMiAxNzkuNDk5IDMxNy43MDEgQyAxNzguNjUgMzE1Ljk0NyAxNzguMjE3IDMxNC4wMjEgMTc4LjIzMSAzMTIuMDcyIEMgMTc4LjIzMSAzMDcuOTMgMTgwLjIzMyAzMDQuMDQgMTgzLjYwMyAzMDEuNjMzIEMgMTg5LjU4IDI5Ny4zMjQgMTk3Ljk1IDI5OC45MTYgMjAxLjkyIDMwNS4xMjcgQyAyMDMuMjk0IDMwNy4xODEgMjA0LjAxMyAzMDkuNjAzIDIwMy45OSAzMTIuMDcyIE0gMjU1LjMyMSAxODguMjU5IEMgMjU1LjM2MyAxOTUuMzg1IDI0OS41ODcgMjAxLjE3NiAyNDIuNDY2IDIwMS4xNjMgQyAyNDEuODM2IDIwMS4xNjMgMjQxLjIyNyAyMDEuMTM0IDI0MC42NCAyMDEuMDc3IEMgMjQwLjUyNSAyMDEuMDI4IDI0MC40MDcgMjAxIDI0MC4yODIgMjAwLjk5IEMgMjMwLjQ5MSAxOTkuNTM3IDIyNS45NDUgMTg4LjAzIDIzMi4wOTggMTgwLjI4IEMgMjM0LjYgMTc3LjEyNCAyMzguNDM4IDE3NS4zMjIgMjQyLjQ2NiAxNzUuNDE3IEwgMjQzLjAwNCAxNzUuNDE3IEMgMjQ5Ljg3MyAxNzUuNzQyIDI1NS4yODIgMTgxLjM4NiAyNTUuMzIxIDE4OC4yNTkiIGNsYXNzPSJzdDMiIHN0eWxlPSJmaWxsOiByZ2IoMjU0LCAyMDAsIDQ3KTsiLz4KICAgIDxwYXRoIGQ9Ik0gMzgzLjI2NyAyNTAuMjU4IEMgMzgzLjI2NyAyNjMuMTkxIDM4MS40MjYgMjc1LjY2IDM3OC4wMTggMjg3LjQ2NiBDIDM2Ni4yMTIgMjg0LjI2MyAzNTQuNzUyIDI3OS44OTcgMzQzLjgwNCAyNzQuNDM0IEMgMzQ0Ljc0MyAyNjkuNzczIDM0NC4yODQgMjY0LjkzOSAzNDIuNDkzIDI2MC41MzUgQyAzNTYuNDkyIDI0Ni41NSAzNjguNDggMjMwLjY5MSAzNzguMTE5IDIxMy40MDggQyAzODEuNDU1IDIyNS4xMDkgMzgzLjI2NyAyMzcuNDk3IDM4My4yNjcgMjUwLjI1OCBNIDM3MC44NSAxOTMuOTkzIEMgMzY5LjkzNSAxOTUuOTkxIDM2OC45ODEgMTk3Ljk2NCAzNjcuOTg1IDE5OS45MjIgQyAzNTguNzU3IDIxNy45NyAzNDYuNzk2IDIzNC40ODEgMzMyLjUzMSAyNDguODc3IEMgMzI0LjE2IDI0My44MjQgMzEzLjU3MyAyNDQuMjk1IDMwNS42ODQgMjUwLjA3MyBDIDI5OC4yNDUgMjQ0LjE5IDI5MS4xNTIgMjM3Ljg3IDI4NC40NDUgMjMxLjE1MyBDIDI3NS45NTUgMjIyLjY3OSAyNjguMTA5IDIxMy41ODQgMjYwLjk3IDIwMy45NDEgQyAyNjcuNjY3IDE5Ni4wODEgMjY4LjYyOSAxODQuODMxIDI2My4zNjIgMTc1Ljk0MiBDIDI3OS44NyAxNTkuOTU5IDI5OC42OTIgMTQ2LjU2IDMxOS4yMDMgMTM2LjE5OCBDIDM0MS43MzQgMTQ5Ljk1NCAzNTkuNzAxIDE3MC4wNiAzNzAuODUgMTkzLjk5MyBNIDMzMi44NzQgMjY5LjY0MyBDIDMzMy4zMTcgMjc5LjU0NCAzMjIuODc4IDI4Ni4yMTMgMzE0LjA4NCAyODEuNjQ3IEMgMzEwLjAwNCAyNzkuNTMgMzA3LjM2MiAyNzUuMzkyIDMwNy4xNTMgMjcwLjgwMyBMIDMwNy41NTQgMjcwLjQ4OCBDIDMwNy40MDEgMjcwLjM5MyAzMDcuMjU4IDI3MC4yODMgMzA3LjEyNCAyNzAuMTU5IEwgMzA3LjExIDI2OS42MyBDIDMwNy4xNjIgMjYxLjAyMSAzMTUuNDYxIDI1NC44NjMgMzIzLjcyMiAyNTcuMzEzIEMgMzI5LjEzNyAyNTguOTg2IDMzMi44NDUgMjYzLjk3NyAzMzIuODc0IDI2OS42NDMgTSAzMzYuMjIgMjg3LjY2NyBDIDMyNy45NjggMjk1LjEzMiAzMTUuNjk1IDI5Ni4wMTggMzA2LjQ1NyAyODkuODE2IEMgMzA1Ljg5NSAyOTAuMTg4IDMwNS4zNTEgMjkwLjUzMiAzMDQuODE3IDI5MC44NDEgQyAyODcuODE1IDMwMS43MDkgMjY5LjIzNSAzMDkuODc0IDI0OS43MzQgMzE1LjA1MSBMIDI0OS43MzQgMzgzLjgxOSBDIDMwMy41MzUgMzgzLjgxOSAzNTIuMDgzIDM1MS41NDQgMzcyLjg5OCAzMDEuOTMzIEMgMzYwLjIzNSAyOTguMzk2IDM0Ny45NTEgMjkzLjYyIDMzNi4yMiAyODcuNjY3IiBjbGFzcz0ic3Q0IiBzdHlsZT0iZmlsbDogcmdiKDIyMywgMTU2LCAzOCk7Ii8+CiAgICA8cGF0aCBkPSJNIDI0OS43NDkgMzE1LjA1MSBDIDIzOC42MjMgMzE3Ljk1OSAyMjcuMjMxIDMxOS43MTMgMjE1Ljc0OSAzMjAuMjc5IEwgMjEzLjkyMyAzMjAuMzk0IEMgMjExLjc3MyAzMjYuMjM4IDIwNy40NSAzMzEgMjAxLjk2MyAzMzMuNzkzIEMgMjA1LjQ1NyAzNDYuNzUzIDIxMS43NzMgMzU4LjAwMyAyMjAuNzY4IDM2Ni45NjkgQyAyMjguMjM4IDM3NC40MzggMjM3LjMzMiAzODAuMDgyIDI0Ny43MjIgMzgzLjc5IEwgMjQ5Ljc0OSAzODMuODE5IEwgMjQ5Ljc0OSAzMTUuMDUxIFoiIGNsYXNzPSJzdDMiIHN0eWxlPSJmaWxsOiByZ2IoMjU0LCAyMDAsIDQ3KTsiLz4KICAgIDxwYXRoIGQ9Ik0gMjk1LjczOCAyNjkuNjQzIEMgMjk1Ljc0NyAyNjcuMTc0IDI5Ni4wOTkgMjY0LjgwNiAyOTYuNzkgMjYyLjU0NyBDIDI3OS4wNjQgMjQ4LjYzOCAyNjMuMjQ4IDIzMi40NiAyNDkuNzQ5IDIxNC40MTggTCAyNDkuNzQ5IDI5OS4xODMgQyAyNjYuNDcxIDI5NC4yODMgMjgyLjQwOSAyODcuMDI3IDI5Ny4wOSAyNzcuNjQyIEMgMjk2LjE5NSAyNzUuMDc0IDI5NS43MzggMjcyLjM3MSAyOTUuNzM4IDI2OS42NDMiIGNsYXNzPSJzdDQiIHN0eWxlPSJmaWxsOiByZ2IoMjIzLCAxNTYsIDM4KTsiLz4KICAgIDxwYXRoIGQ9Ik0gMjQ5Ljc0OSAyMTQuNDE4IEMgMjQ5LjEwNSAyMTMuNTc5IDI0OC40NTIgMjEyLjgwNyAyNDcuODY2IDIxMS45NCBDIDI0My4wNDMgMjEzLjA0NiAyMzcuOTkgMjEyLjY1IDIzMy4zOTkgMjEwLjggQyAyMTcuMjMxIDIzMy42OTQgMjA2LjEzOSAyNTguNDI4IDIwMS4zMiAyODIuNzc2IEMgMjAwLjg3NyAyODUuMDgzIDIwMC40ODEgMjg3LjM0MiAyMDAuMTM4IDI4OS41NDUgQyAyMDYuOTM5IDI5Mi4zMjggMjEyLjIyNiAyOTguMDQzIDIxNC4zMzcgMzA1LjExMiBDIDIxNC41NDcgMzA1LjA2NSAyMTQuNzY3IDMwNS4wNDYgMjE0Ljk5NSAzMDUuMDU1IEMgMjI2LjUyNiAzMDQuNTAzIDIzOC4xODYgMzAyLjQ5MSAyNDkuNzQ5IDI5OS4xODMgTCAyNDkuNzQ5IDIxNC40MTggWiIgY2xhc3M9InN0MyIgc3R5bGU9ImZpbGw6IHJnYigyNTQsIDIwMCwgNDcpOyIvPgogICAgPHBhdGggZD0iTSAyNDkuNzQ5IDExNi43NTUgTCAyNDkuNzQ5IDE2NS4xNCBDIDI1MC40MzkgMTY1LjM1NiAyNTEuMTMxIDE2NS42MTggMjUxLjgxNyAxNjUuOTIyIEMgMjY3LjA2MSAxNTEuMDIyIDI4NC4xODIgMTM4LjE3NyAzMDIuNzQ5IDEyNy43MDQgQyAyODYuMDIzIDEyMC40NDkgMjY3Ljk4MSAxMTYuNzIxIDI0OS43NDkgMTE2Ljc1NSIgY2xhc3M9InN0NCIgc3R5bGU9ImZpbGw6IHJnYigyMjMsIDE1NiwgMzgpOyIvPgogICAgPHBhdGggZD0iTSAyNDkuNzQ5IDExNi43NTUgQyAyNDEuMDY1IDExNi43NTUgMjMyLjYzNiAxMTcuNTU2IDIyNC40NzIgMTE5LjE1MyBDIDIyNC44MjggMTIxLjk2IDIyNS4zMyAxMjQuOTExIDIyNS45MTEgMTI3Ljc5IEMgMjI4LjMwOCAxNDAuMDQ5IDIzMi4zMTMgMTUyLjM4MSAyMzcuNzMyIDE2NC40OTggQyAyNDEuNzI3IDE2My42OTYgMjQ1Ljg1OSAxNjMuOTE2IDI0OS43NDkgMTY1LjE0IEwgMjQ5Ljc0OSAxMTYuNzU1IFoiIGNsYXNzPSJzdDMiIHN0eWxlPSJmaWxsOiByZ2IoMjU0LCAyMDAsIDQ3KTsiLz4KICA8L2c+Cjwvc3ZnPg==' const previewIconUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBmaWxsPSIjZjA4ODNlIj48cGF0aCBkPSJNMTIgNC41QzcgNC41IDIuNzMgNy42MSAxIDEyYzEuNzMgNC4zOSA2IDcuNSAxMSA3LjVzOS4yNy0zLjExIDExLTcuNWMtMS43My00LjM5LTYtNy41LTExLTcuNXpNMTIgMTdjLTIuNzYgMC01LTIuMjQtNS01czIuMjQtNSA1LTUgNSAyLjI0IDUgNS0yLjI0IDUtNSA1em0wLThjLTEuNjYgMC0zIDEuMzQtMyAzczEuMzQgMyAzIDMgMy0xLjM0IDMtMy0xLjM0LTMtMy0zeiIvPjwvc3ZnPg==' const deepWikiIconUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjExMCAxMTAgNDYwIDUwMCI+PHBhdGggc3R5bGU9ImZpbGw6IzIxYzE5YSIgY2xhc3M9IiIgZD0iTTQxOC43MywzMzIuMzdjOS44NC01LjY4LDIyLjA3LTUuNjgsMzEuOTEsMGwyNS40OSwxNC43MWMuODIuNDgsMS42OS44LDIuNTgsMS4wNi4xOS4wNi4zNy4xMS41NS4xNi44Ny4yMSwxLjc2LjM0LDIuNjUuMzUuMDQsMCwuMDguMDIuMTMuMDIuMSwwLC4xOS0uMDMuMjktLjA0LjgzLS4wMiwxLjY0LS4xMywyLjQ1LS4zMi4xNC0uMDMuMjgtLjA1LjQyLS4wOS44Ny0uMjQsMS43LS41OSwyLjUtMS4wMy4wOC0uMDQuMTctLjA2LjI1LS4xbDUwLjk3LTI5LjQzYzMuNjUtMi4xMSw1LjktNi4wMSw1LjktMTAuMjJ2LTU4Ljg2YzAtNC4yMi0yLjI1LTguMTEtNS45LTEwLjIybC01MC45Ny0yOS40M2MtMy42NS0yLjExLTguMTUtMi4xMS0xMS44MSwwbC01MC45NywyOS40M2MtLjA4LjA0LS4xMy4xMS0uMi4xNi0uNzguNDgtMS41MSwxLjAyLTIuMTUsMS42Ni0uMS4xLS4xOC4yMS0uMjguMzEtLjU3LjYtMS4wOCwxLjI2LTEuNTEsMS45Ny0uMDcuMTItLjE1LjIyLS4yMi4zNC0uNDQuNzctLjc3LDEuNi0xLjAzLDIuNDctLjA1LjE5LS4xLjM3LS4xNC41Ni0uMjIuODktLjM3LDEuODEtLjM3LDIuNzZ2MjkuNDNjMCwxMS4zNi02LjExLDIxLjk1LTE1Ljk1LDI3LjYzLTkuODQsNS42OC0yMi4wNiw1LjY4LTMxLjkxLDBsLTI1LjQ5LTE0LjcxYy0uODItLjQ4LTEuNjktLjgtMi41Ny0xLjA2LS4xOS0uMDYtLjM3LS4xMS0uNTYtLjE2LS44OC0uMjEtMS43Ni0uMzQtMi42NS0uMzQtLjEzLDAtLjI2LjAyLS40LjAyLS44NC4wMi0xLjY2LjEzLTIuNDcuMzItLjEzLjAzLS4yNy4wNS0uNC4wOS0uODcuMjQtMS43MS42LTIuNTEsMS4wNC0uMDguMDQtLjE2LjA2LS4yNC4xbC01MC45NywyOS40M2MtMy42NSwyLjExLTUuOSw2LjAxLTUuOSwxMC4yMnY1OC44NmMwLDQuMjIsMi4yNSw4LjExLDUuOSwxMC4yMmw1MC45NywyOS40M2MuMDguMDQuMTcuMDYuMjQuMS44LjQ0LDEuNjQuNzksMi41LDEuMDMuMTQuMDQuMjguMDYuNDIuMDkuODEuMTksMS42Mi4zLDIuNDUuMzIuMSwwLC4xOS4wNC4yOS4wNC4wNCwwLC4wOC0uMDIuMTMtLjAyLjg5LDAsMS43Ny0uMTMsMi42NS0uMzUuMTktLjA0LjM3LS4xLjU2LS4xNi44OC0uMjYsMS43NS0uNTksMi41OC0xLjA2bDI1LjQ5LTE0LjcxYzkuODQtNS42OCwyMi4wNi01LjY4LDMxLjkxLDAsOS44NCw1LjY4LDE1Ljk1LDE2LjI3LDE1Ljk1LDI3LjYzdjI5LjQzYzAsLjk1LjE1LDEuODcuMzcsMi43Ni4wNS4xOS4wOS4zNy4xNC41Ni4yNS44Ni41OSwxLjY5LDEuMDMsMi40Ny4wNy4xMi4xNS4yMi4yMi4zNC40My43MS45NCwxLjM3LDEuNTEsMS45Ny4xLjEuMTguMjEuMjguMzEuNjUuNjMsMS4zNywxLjE4LDIuMTUsMS42Ni4wNy4wNC4xMy4xMS4yLjE2bDUwLjk3LDI5LjQzYzEuODMsMS4wNSwzLjg2LDEuNTgsNS45LDEuNThzNC4wOC0uNTMsNS45LTEuNThsNTAuOTctMjkuNDNjMy42NS0yLjExLDUuOS02LjAxLDUuOS0xMC4yMnYtNTguODZjMC00LjIyLTIuMjUtOC4xMS01LjktMTAuMjJsLTUwLjk3LTI5LjQzYy0uMDgtLjA0LS4xNi0uMDYtLjI0LS4xLS44LS40NC0xLjY0LS44LTIuNTEtMS4wNC0uMTMtLjA0LS4yNi0uMDUtLjM5LS4wOS0uODItLjItMS42NS0uMzEtMi40OS0uMzMtLjEzLDAtLjI1LS4wMi0uMzgtLjAyLS44OSwwLTEuNzguMTMtMi42Ni4zNS0uMTguMDQtLjM2LjEtLjU0LjE1LS44OC4yNi0xLjc1LjU5LTIuNTgsMS4wN2wtMjUuNDksMTQuNzJjLTkuODQsNS42OC0yMi4wNyw1LjY4LTMxLjksMC05Ljg0LTUuNjgtMTUuOTUtMTYuMjctMTUuOTUtMjcuNjNzNi4xMS0yMS45NSwxNS45NS0yNy42M1oiLz48cGF0aCBzdHlsZT0iZmlsbDojMzk2OWNhIiBkPSJNMTQxLjA5LDMxNy42NWw1MC45NywyOS40M2MxLjgzLDEuMDUsMy44NiwxLjU4LDUuOSwxLjU4czQuMDgtLjUzLDUuOS0xLjU4bDUwLjk3LTI5LjQzYy4wOC0uMDQuMTMtLjExLjItLjE2Ljc4LS40OCwxLjUxLTEuMDIsMi4xNS0xLjY2LjEtLjEuMTgtLjIxLjI4LS4zMS41Ny0uNiwxLjA4LTEuMjYsMS41MS0xLjk3LjA3LS4xMi4xNS0uMjIuMjItLjM0LjQ0LS43Ny43Ny0xLjYsMS4wMy0yLjQ3LjA1LS4xOS4xLS4zNy4xNC0uNTYuMjItLjg5LjM3LTEuODEuMzctMi43NnYtMjkuNDNjMC0xMS4zNiw2LjExLTIxLjk1LDE1Ljk2LTI3LjYzczIyLjA2LTUuNjgsMzEuOTEsMGwyNS40OSwxNC43MWMuODIuNDgsMS42OS44LDIuNTcsMS4wNi4xOS4wNi4zNy4xMS41Ni4xNi44Ny4yMSwxLjc2LjM0LDIuNjQuMzUuMDQsMCwuMDkuMDIuMTMuMDIuMSwwLC4xOS0uMDQuMjktLjA0LjgzLS4wMiwxLjY1LS4xMywyLjQ1LS4zMi4xNC0uMDMuMjgtLjA1LjQxLS4wOS44Ny0uMjQsMS43MS0uNiwyLjUxLTEuMDQuMDgtLjA0LjE2LS4wNi4yNC0uMWw1MC45Ny0yOS40M2MzLjY1LTIuMTEsNS45LTYuMDEsNS45LTEwLjIydi01OC44NmMwLTQuMjItMi4yNS04LjExLTUuOS0xMC4yMmwtNTAuOTctMjkuNDNjLTMuNjUtMi4xMS04LjE1LTIuMTEtMTEuODEsMGwtNTAuOTcsMjkuNDNjLS4wOC4wNC0uMTMuMTEtLjIuMTYtLjc4LjQ4LTEuNTEsMS4wMi0yLjE1LDEuNjYtLjEuMS0uMTguMjEtLjI4LjMxLS41Ny42LTEuMDgsMS4yNi0xLjUxLDEuOTctLjA3LjEyLS4xNS4yMi0uMjIuMzQtLjQ0Ljc3LS43NywxLjYtMS4wMywyLjQ3LS4wNS4xOS0uMS4zNy0uMTQuNTYtLjIyLjg5LS4zNywxLjgxLS4zNywyLjc2djI5LjQzYzAsMTEuMzYtNi4xMSwyMS45NS0xNS45NSwyNy42My05Ljg0LDUuNjgtMjIuMDcsNS42OC0zMS45MSwwbC0yNS40OS0xNC43MWMtLjgyLS40OC0xLjY5LS44LTIuNTgtMS4wNi0uMTktLjA2LS4zNy0uMTEtLjU1LS4xNi0uODgtLjIxLTEuNzYtLjM0LTIuNjUtLjM1LS4xMywwLS4yNi4wMi0uNC4wMi0uODMuMDItMS42Ni4xMy0yLjQ3LjMyLS4xMy4wMy0uMjcuMDUtLjQuMDktLjg3LjI0LTEuNzEuNi0yLjUxLDEuMDQtLjA4LjA0LS4xNi4wNi0uMjQuMWwtNTAuOTcsMjkuNDNjLTMuNjUsMi4xMS01LjksNi4wMS01LjksMTAuMjJ2NTguODZjMCw0LjIyLDIuMjUsOC4xMSw1LjksMTAuMjJaIi8+PHBhdGggc3R5bGU9ImZpbGw6IzAyOTRkZSIgY2xhc3M9IiIgZD0iTTM5Ni44OCw0ODQuMzVsLTUwLjk3LTI5LjQzYy0uMDgtLjA0LS4xNy0uMDYtLjI0LS4xLS44LS40NC0xLjY0LS43OS0yLjUxLTEuMDMtLjE0LS4wNC0uMjctLjA2LS40MS0uMDktLjgxLS4xOS0xLjY0LS4zLTIuNDctLjMyLS4xMywwLS4yNi0uMDItLjM5LS4wMi0uODksMC0xLjc4LjEzLTIuNjYuMzUtLjE4LjA0LS4zNi4xLS41NC4xNS0uODguMjYtMS43Ni41OS0yLjU4LDEuMDdsLTI1LjQ5LDE0LjcyYy05Ljg0LDUuNjgtMjIuMDYsNS42OC0zMS45LDAtOS44NC01LjY4LTE1Ljk2LTE2LjI3LTE1Ljk2LTI3LjYzdi0yOS40M2MwLS45NS0uMTUtMS44Ny0uMzctMi43Ni0uMDUtLjE5LS4wOS0uMzctLjE0LS41Ni0uMjUtLjg2LS41OS0xLjY5LTEuMDMtMi40Ny0uMDctLjEyLS4xNS0uMjItLjIyLS4zNC0uNDMtLjcxLS45NC0xLjM3LTEuNTEtMS45Ny0uMS0uMS0uMTgtLjIxLS4yOC0uMzEtLjY1LS42My0xLjM3LTEuMTgtMi4xNS0xLjY2LS4wNy0uMDQtLjEzLS4xMS0uMi0uMTZsLTUwLjk3LTI5LjQzYy0zLjY1LTIuMTEtOC4xNS0yLjExLTExLjgxLDBsLTUwLjk3LDI5LjQzYy0zLjY1LDIuMTEtNS45LDYuMDEtNS45LDEwLjIydjU4Ljg2YzAsNC4yMiwyLjI1LDguMTEsNS45LDEwLjIybDUwLjk3LDI5LjQzYy4wOC4wNC4xNy4wNi4yNS4xLjguNDQsMS42My43OSwyLjUsMS4wMy4xNC4wNC4yOS4wNi40My4wOS44LjE5LDEuNjEuMywyLjQzLjMyLjEsMCwuMi4wNC4zLjA0LjA0LDAsLjA5LS4wMi4xMy0uMDIuODgsMCwxLjc3LS4xMywyLjY0LS4zNC4xOS0uMDQuMzctLjEuNTYtLjE2Ljg4LS4yNiwxLjc1LS41OSwyLjU3LTEuMDZsMjUuNDktMTQuNzFjOS44NC01LjY4LDIyLjA2LTUuNjgsMzEuOTEsMCw5Ljg0LDUuNjgsMTUuOTUsMTYuMjcsMTUuOTUsMjcuNjN2MjkuNDNjMCwuOTUuMTUsMS44Ny4zNywyLjc2LjA1LjE5LjA5LjM3LjE0LjU2LjI1Ljg2LjU5LDEuNjksMS4wMywyLjQ3LjA3LjEyLjE1LjIyLjIyLjM0LjQzLjcxLjk0LDEuMzcsMS41MSwxLjk3LjEuMS4xOC4yMS4yOC4zMS42NS42MywxLjM3LDEuMTgsMi4xNSwxLjY2LjA3LjA0LjEzLjExLjIuMTZsNTAuOTcsMjkuNDNjMS44MywxLjA1LDMuODYsMS41OCw1LjksMS41OHM0LjA4LS41Myw1LjktMS41OGw1MC45Ny0yOS40M2MzLjY1LTIuMTEsNS45LTYuMDEsNS45LTEwLjIydi01OC44NmMwLTQuMjItMi4yNS04LjExLTUuOS0xMC4yMloiLz48L3N2Zz4=' const codeWikiIconUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9Ii0yMCAtMjAgMzIwIDMyMCI+PHBhdGggZmlsbD0iIzAwN2FmNCIgZD0iTTExOS4xNjYgNC4wMTNhNTYuMSA1Ni4xIDAgMCAxIDQxLjY2OCAwbDExMy4yODkgNDUuMzE2YzcuODM2IDMuMTM1IDcuODM2IDE0LjIyOCAwIDE3LjM2M0wyMDYuMzQgOTMuODA1Yy00LjY5NCAxLjg3Ny00LjY5NCA4LjUyMSAwIDEwLjM5OWw2Ny43ODIgMjcuMTE0YzcuODM3IDMuMTM0IDcuODM2IDE0LjIyNyAwIDE3LjM2MmwtNjcuNzgxIDI3LjExM2MtNC42OTQgMS44NzctNC42OTQgOC41MjIgMCAxMC4zOTlsNjcuNzgxIDI3LjExM2M3LjgzNyAzLjEzNCA3LjgzNiAxNC4yMjggMCAxNy4zNjJsLTExMy4yODkgNDUuMzE3YTU2LjEgNTYuMSAwIDAgMS00MS42NjcgMEw1Ljg3NyAyMzAuNjY3Yy03LjgzNi0zLjEzNC03LjgzNi0xNC4yMjcgMC0xNy4zNjJsNjcuNzgtMjcuMTEzYzQuNjk1LTEuODc3IDQuNjk1LTguNTIyIDAtMTAuMzk5TDUuODc4IDE0OC42OGMtNy44MzYtMy4xMzUtNy44MzYtMTQuMjI4IDAtMTcuMzYybDY3Ljc4Mi0yNy4xMTRjNC42OTQtMS44NzggNC42OTQtOC41MjIgMC0xMC40TDUuODc5IDY2LjY5M2MtNy44MzctMy4xMzUtNy44MzctMTQuMjI4IDAtMTcuMzYzeiIvPjxwYXRoIGZpbGw9InVybCgjYSkiIGQ9Ik0xMTkuMTY2IDQuMDEzYTU2LjEgNTYuMSAwIDAgMSA0MS42NjggMGwxMTMuMjg5IDQ1LjMxNmM3LjgzNiAzLjEzNSA3LjgzNiAxNC4yMjggMCAxNy4zNjNMMjA2LjM0IDkzLjgwNWMtNC42OTQgMS44NzctNC42OTQgOC41MjEgMCAxMC4zOTlsNjcuNzgyIDI3LjExNGM3LjgzNyAzLjEzNCA3LjgzNiAxNC4yMjcgMCAxNy4zNjJsLTY3Ljc4MSAyNy4xMTNjLTQuNjk0IDEuODc3LTQuNjk0IDguNTIyIDAgMTAuMzk5bDY3Ljc4MSAyNy4xMTNjNy44MzcgMy4xMzQgNy44MzYgMTQuMjI4IDAgMTcuMzYybC0xMTMuMjg5IDQ1LjMxN2E1Ni4xIDU2LjEgMCAwIDEtNDEuNjY3IDBMNS44NzcgMjMwLjY2N2MtNy44MzYtMy4xMzQtNy44MzYtMTQuMjI3IDAtMTcuMzYybDY3Ljc4LTI3LjExM2M0LjY5NS0xLjg3NyA0LjY5NS04LjUyMiAwLTEwLjM5OUw1Ljg3OCAxNDguNjhjLTcuODM2LTMuMTM1LTcuODM2LTE0LjIyOCAwLTE3LjM2Mmw2Ny43ODItMjcuMTE0YzQuNjk0LTEuODc4IDQuNjk0LTguNTIyIDAtMTAuNEw1Ljg3OSA2Ni42OTNjLTcuODM3LTMuMTM1LTcuODM3LTE0LjIyOCAwLTE3LjM2M3oiLz48cGF0aCBmaWxsPSJ1cmwoI2IpIiBkPSJNMTE5LjE2NiA0LjAxM2E1Ni4xIDU2LjEgMCAwIDEgNDEuNjY4IDBsMTEzLjI4OSA0NS4zMTZjNy44MzYgMy4xMzUgNy44MzYgMTQuMjI4IDAgMTcuMzYzTDIwNi4zNCA5My44MDVjLTQuNjk0IDEuODc3LTQuNjk0IDguNTIxIDAgMTAuMzk5bDY3Ljc4MiAyNy4xMTRjNy44MzcgMy4xMzQgNy44MzYgMTQuMjI3IDAgMTcuMzYybC02Ny43ODEgMjcuMTEzYy00LjY5NCAxLjg3Ny00LjY5NCA4LjUyMiAwIDEwLjM5OWw2Ny43ODEgMjcuMTEzYzcuODM3IDMuMTM0IDcuODM2IDE0LjIyOCAwIDE3LjM2MmwtMTEzLjI4OSA0NS4zMTdhNTYuMSA1Ni4xIDAgMCAxLTQxLjY2NyAwTDUuODc3IDIzMC42NjdjLTcuODM2LTMuMTM0LTcuODM2LTE0LjIyNyAwLTE3LjM2Mmw2Ny43OC0yNy4xMTNjNC42OTUtMS44NzcgNC42OTUtOC41MjIgMC0xMC4zOTlMNS44NzggMTQ4LjY4Yy03LjgzNi0zLjEzNS03LjgzNi0xNC4yMjggMC0xNy4zNjJsNjcuNzgyLTI3LjExNGM0LjY5NC0xLjg3OCA0LjY5NC04LjUyMiAwLTEwLjRMNS44NzkgNjYuNjkzYy03LjgzNy0zLjEzNS03LjgzNy0xNC4yMjggMC0xNy4zNjN6Ii8+PHBhdGggZmlsbD0idXJsKCNjKSIgZD0iTTExOS4xNjcgNC4wMTJhNTYuMSA1Ni4xIDAgMCAxIDQxLjY2NyAwTDI3NC4xMjMgNDkuMzNjNy44MzYgMy4xMzQgNy44MzYgMTQuMjI2IDAgMTcuMzZMMjA2LjM0IDkzLjgwNmMtNC42OTQgMS44NzctNC42OTQgOC41MjEgMCAxMC4zOTlsNjcuNzgyIDI3LjExNGM3LjgzNiAzLjEzNCA3LjgzNiAxNC4yMjggMCAxNy4zNjJsLTY3Ljc4MSAyNy4xMTNjLTQuNjkzIDEuODc4LTQuNjkzIDguNTIyIDAgMTAuMzk5bDY3Ljc4MSAyNy4xMTNjNy44MzYgMy4xMzUgNy44MzYgMTQuMjI4IDAgMTcuMzYybC0xMTMuMjg4IDQ1LjMxN2E1Ni4xIDU2LjEgMCAwIDEtNDEuNjY4IDBMNS44NzcgMjMwLjY2N2MtNy44MzYtMy4xMzQtNy44MzYtMTQuMjI3IDAtMTcuMzYybDY3Ljc4LTI3LjExM2M0LjY5NC0xLjg3NyA0LjY5NC04LjUyMSAwLTEwLjM5OUw1Ljg3NyAxNDguNjhjLTcuODM2LTMuMTM0LTcuODM2LTE0LjIyNyAwLTE3LjM2Mmw2Ny43ODMtMjcuMTE0YzQuNjkzLTEuODc4IDQuNjkzLTguNTIyIDAtMTAuNEw1Ljg3OCA2Ni42OTJjLTcuODM2LTMuMTM1LTcuODM2LTE0LjIyNyAwLTE3LjM2MXoiLz48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImEiIHgxPSI4Mi40NDciIHgyPSIxMjcuNTU3IiB5MT0iMjU5Ljc3MyIgeTI9IjE2MS43NzMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9Ii4yMDYiIHN0b3AtY29sb3I9IiMwOGI5NjIiLz48c3RvcCBvZmZzZXQ9Ii45ODciIHN0b3AtY29sb3I9IiMwOGI5NjIiIHN0b3Atb3BhY2l0eT0iMCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJiIiB4MT0iOTkuNTU4IiB4Mj0iMTUwLjg5MSIgeTE9IjQzLjU1MyIgeTI9IjEzOS45OTYiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjZjk0NTQzIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZjk0NTQzIiBzdG9wLW9wYWNpdHk9IjAiLz48L2xpbmVhckdyYWRpZW50PjxyYWRpYWxHcmFkaWVudCBpZD0iYyIgY3g9IjAiIGN5PSIwIiByPSIxIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDQzOC4xMTQgMCAwIDQzOC4xMSAxMS45IDEzOS45NzIpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iI2ZhYmMxMiIvPjxzdG9wIG9mZnNldD0iLjQyMyIgc3RvcC1jb2xvcj0iI2ZhYmMxMiIgc3RvcC1vcGFjaXR5PSIwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PC9zdmc+' const zReadIconUrl = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTSAxMS4xOTkgMjcuNTIgQyAxMS4xOTkgMjguMjI3IDEwLjYyNiAyOC44IDkuOTE5IDI4LjggTCA0LjQ3OSAyOC44IEMgMy43NzIgMjguOCAzLjE5OSAyOC4yMjcgMy4xOTkgMjcuNTIgTCAzLjE5OSAyMi4wOCBDIDMuMTk5IDIxLjM3MyAzLjc3MiAyMC44IDQuNDc5IDIwLjggTCA5Ljc4NiAyMC44IEwgMjAuODAxIDkuNzg1IEwgMjAuODAxIDQuNDggQyAyMC44MDEgMy43NzMgMjEuMzc0IDMuMiAyMi4wODEgMy4yIEwgMjcuNTIxIDMuMiBDIDI4LjIyOCAzLjIgMjguODAxIDMuNzczIDI4LjgwMSA0LjQ4IEwgMjguODAxIDkuOTIgQyAyOC44MDEgMTAuNjI3IDI4LjIyOCAxMS4yIDI3LjUyMSAxMS4yIEwgMjIuMjE0IDExLjIgTCAxMS4xOTkgMjIuMjE1IFogTSAxMS4xOTkgNC40OCBMIDExLjE5OSA5LjkyIEMgMTEuMTk5IDEwLjYyNyAxMC42MjYgMTEuMiA5LjkxOSAxMS4yIEwgNC40NzkgMTEuMiBDIDMuNzcyIDExLjIgMy4xOTkgMTAuNjI3IDMuMTk5IDkuOTIgTCAzLjE5OSA0LjQ4IEMgMy4xOTkgMy43NzMgMy43NzIgMy4yIDQuNDc5IDMuMiBMIDkuOTE5IDMuMiBDIDEwLjYyNiAzLjIgMTEuMTk5IDMuNzczIDExLjE5OSA0LjQ4IFoiIHN0eWxlPSJmaWxsOiByZ2IoMzEsIDM1LCA0MCk7Ii8+CiAgPHBhdGggZD0iTTggMjRMMjQgOEw4IDI0WiIgZmlsbD0iIzAwMDAwMCIvPgogIDxwYXRoIGQ9Ik04IDI0TDI0IDgiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHlsZT0iZmlsbDogcmdiKDMxLCAzNSwgNDApOyIvPgo8L3N2Zz4=' const ossinsightIconUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDE2IDE2Ij48cmVjdCB4PSIwLjc1IiB5PSIwLjc1IiB3aWR0aD0iMTQuNSIgaGVpZ2h0PSIxNC41IiByeD0iMyIgc3Ryb2tlPSIjMUYyMzI4IiBzdHJva2Utd2lkdGg9IjEiLz48cmVjdCB4PSI0IiB5PSIxMCIgd2lkdGg9IjEuOCIgaGVpZ2h0PSIzIiByeD0iMC41IiBzdHJva2U9IiMxRjIzMjgiIHN0cm9rZS13aWR0aD0iMS4xIi8+PHJlY3QgeD0iNyIgeT0iNyIgd2lkdGg9IjEuOCIgaGVpZ2h0PSI2IiByeD0iMC41IiBzdHJva2U9IiMxRjIzMjgiIHN0cm9rZS13aWR0aD0iMS4xIi8+PHJlY3QgeD0iMTAiIHk9IjUiIHdpZHRoPSIxLjgiIGhlaWdodD0iOCIgcng9IjAuNSIgc3Ryb2tlPSIjMUYyMzI4IiBzdHJva2Utd2lkdGg9IjEuMSIvPjwvc3ZnPg==' const homepageIconUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDE2IDE2Ij48cmVjdCB4PSIwLjc1IiB5PSIwLjc1IiB3aWR0aD0iMTQuNSIgaGVpZ2h0PSIxNC41IiByeD0iMyIgc3Ryb2tlPSIjMUYyMzI4IiBzdHJva2Utd2lkdGg9IjEiLz48cGF0aCBkPSJNMyA4bDUtNC41IDUgNC41IiBzdHJva2U9IiMxRjIzMjgiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48cGF0aCBkPSJNNC41IDcuNXY2aDN2LTMuNWgxdjMuNWgzdi02IiBzdHJva2U9IiMxRjIzMjgiIHN0cm9rZS13aWR0aD0iMS4yIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9zdmc+' const coverIconUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgdmlld0JveD0iMCAwIDE2IDE2Ij48cmVjdCB4PSIwLjc1IiB5PSIwLjc1IiB3aWR0aD0iMTQuNSIgaGVpZ2h0PSIxNC41IiByeD0iMyIgc3Ryb2tlPSIjMUYyMzI4IiBzdHJva2Utd2lkdGg9IjEiLz48Y2lyY2xlIGN4PSI1LjUiIGN5PSI1LjUiIHI9IjEuNCIgc3Ryb2tlPSIjMUYyMzI4IiBzdHJva2Utd2lkdGg9IjEiLz48cGF0aCBkPSJNMi41IDEyLjVsMy00IDIuNSAzIDItMi41IDMuNSA0IiBzdHJva2U9IiMxRjIzMjgiIHN0cm9rZS13aWR0aD0iMSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9zdmc+' const buildDeepWikiUrl = (pathname) => `https://deepwiki.com${pathname}` const buildCodeWikiUrl = (hostname, pathname) => `https://codewiki.google/${hostname}${pathname}` const buildZReadUrl = (pathname) => `https://zread.ai${pathname}` const buildOssinsightUrl = (pathname) => `https://ossinsight.io/analyze${pathname}` // ====== GitHub Folder & File Downloader ====== const folderDownloadStyle = document.createElement('style') folderDownloadStyle.textContent = ` .github-download-icon { cursor: pointer; transition: transform 0.1s ease; } .github-download-icon:hover { transform: scale(1.1); } ` document.head.appendChild(folderDownloadStyle) async function downloadFile(url, fileName) { try { const response = await fetch(url) const blob = await response.blob() const link = document.createElement('a') link.href = window.URL.createObjectURL(blob) link.download = fileName link.style.display = 'none' document.body.appendChild(link) link.click() document.body.removeChild(link) } catch (error) { console.error('Download failed:', error) } } function replaceFolderIcons(row) { const folderSvgs = row.querySelectorAll('.react-directory-filename-column svg.icon-directory') folderSvgs.forEach(svg => { if (svg.dataset.replaced) return svg.innerHTML = `` svg.classList.add('github-download-icon') svg.dataset.replaced = 'true' const folderLink = row.querySelector('a[href*="/tree/"]') if (folderLink) { const fullUrl = folderLink.href const downloadUrl = `https://downgit.evecalm.com/#/home?url=${encodeURIComponent(fullUrl)}` svg.addEventListener('click', (e) => { e.preventDefault() e.stopPropagation() window.open(downloadUrl, '_blank') }) } }) } function replaceFileIcons(row) { const fileSvgs = row.querySelectorAll('.react-directory-filename-column svg.color-fg-muted') fileSvgs.forEach(svg => { if (svg.dataset.replaced) return svg.innerHTML = `` svg.setAttribute('viewBox', '0 0 16 16') svg.classList.add('github-download-icon') svg.dataset.replaced = 'true' const fileLink = row.querySelector('a[href]') if (fileLink) { const downloadUrl = fileLink.href .replace('github.com', 'raw.githubusercontent.com') .replace('/blob/', '/') const fileName = fileLink.textContent.trim() svg.addEventListener('click', (e) => { e.preventDefault() e.stopPropagation() downloadFile(downloadUrl, fileName) }) } }) } function replaceIcons() { const directoryRows = document.querySelectorAll('tr.react-directory-row') directoryRows.forEach(row => { replaceFolderIcons(row) replaceFileIcons(row) }) } // ====== End folder & file downloader ====== function runFileButtons(copyPathButton) { const url = new URL(window.location.href) const { pathname } = url const isFile = pathname.includes('/blob/') const isFolder = pathname.includes('/tree/') let link let htmlPreviewLink = null if (isFolder) { const index = pathname.indexOf('/tree/') const author = pathname.slice(1, index) let rest = pathname.slice(index + 6) const version = rest.slice(0, rest.indexOf('/')) const filepath = rest.slice(rest.indexOf('/')) link = `https://cdn.jsdelivr.net/gh/${author}@${version}${filepath}/` } else if (isFile) { const index = pathname.indexOf('/blob/') const author = pathname.slice(1, index) let rest = pathname.slice(index + 6) const version = rest.slice(0, rest.indexOf('/')) const filepath = rest.slice(rest.indexOf('/')) link = `https://cdn.jsdelivr.net/gh/${author}@${version}${filepath}` if (/\.html?$/i.test(filepath)) { htmlPreviewLink = `https://htmlpreview.github.io/?https://raw.githubusercontent.com/${author}/${version}${filepath}` } } else { return } if (htmlPreviewLink) { let previewButton = document.querySelector('button[aria-label="Preview HTML"]') if (!previewButton) { const copyPathButtonWrapper = copyPathButton.parentElement const container = copyPathButtonWrapper.parentElement const previewNode = copyPathButtonWrapper.cloneNode(true) previewButton = previewNode.querySelector('button') previewButton.setAttribute('title', 'Preview HTML') previewButton.setAttribute('aria-label', 'Preview HTML') previewButton.innerHTML = `` container.appendChild(previewNode) Array.from(previewNode.children).forEach(child => child.getAttribute('title') !== 'Preview HTML' && previewNode.removeChild(child)) } previewButton.onclick = () => { window.open(htmlPreviewLink) } } let actionButton = document.querySelector('button[aria-label="Open JsDelivr Link"]') if (!actionButton) { const copyPathButtonWrapper = copyPathButton.parentElement const container = copyPathButtonWrapper.parentElement const actionNode = copyPathButtonWrapper.cloneNode(true) actionButton = actionNode.querySelector('button') actionButton.setAttribute('title', 'Open JsDelivr Link') actionButton.setAttribute('aria-label', 'Open JsDelivr Link') actionButton.innerHTML = `` container.appendChild(actionNode) Array.from(actionNode.children).forEach(child => child.getAttribute('title') !== 'Open JsDelivr Link' && actionNode.removeChild(child)) } actionButton.onclick = () => { window.open(link) } } // ====== Repo Header Buttons ====== const HEADER_CONTAINER_ID = 'gek-header-buttons' const HEADER_SELECTOR = 'strong[itemprop="name"] a' function addHeaderButtons() { const titleLink = document.querySelector(HEADER_SELECTOR) if (!titleLink || document.getElementById(HEADER_CONTAINER_ID)) return const pathParts = window.location.pathname.split('/').filter(Boolean) if (pathParts.length < 2) return const owner = pathParts[0] const repo = pathParts[1] const titleParent = titleLink.closest('strong') if (titleParent) { titleParent.style.whiteSpace = 'nowrap' } const container = document.createElement('span') container.id = HEADER_CONTAINER_ID container.style.display = 'inline-flex' container.style.alignItems = 'center' container.style.gap = '8px' container.style.marginLeft = '8px' container.style.whiteSpace = 'nowrap' const sizeBadge = document.createElement('span') sizeBadge.textContent = 'loading...' sizeBadge.classList.add('Label') sizeBadge.style.fontSize = '11px' sizeBadge.style.fontWeight = '500' container.appendChild(sizeBadge) fetch(`https://api.github.com/repos/${owner}/${repo}`) .then(r => r.json()) .then(data => { const kb = data.size || 0 if (kb >= 1048576) sizeBadge.textContent = `${(kb / 1048576).toFixed(2)} GB` else if (kb >= 1024) sizeBadge.textContent = `${(kb / 1024).toFixed(1)} MB` else sizeBadge.textContent = `${kb} KB` }) .catch(() => { sizeBadge.textContent = 'n/a' }) const homeLink = document.createElement('a') const h = window.location if (h.host === 'github.com' && h.href.includes('.html')) { homeLink.href = 'https://htmlpreview.github.io/?' + h.href } else { homeLink.href = 'https://' + owner + '.github.io/' + repo } homeLink.target = '_blank' homeLink.title = 'GitHub Pages' homeLink.classList.add('Link', 'Link--muted') homeLink.style.display = 'inline-flex' homeLink.style.alignItems = 'center' const homeImg = document.createElement('img') homeImg.src = homepageIconUrl homeImg.style.width = '18px' homeImg.style.height = '18px' homeImg.style.display = 'block' homeLink.appendChild(homeImg) container.appendChild(homeLink) const ogImage = document.querySelector('meta[property="og:image"]') if (ogImage && ogImage.content) { const coverLink = document.createElement('a') coverLink.href = ogImage.content coverLink.target = '_blank' coverLink.title = 'View cover image' coverLink.classList.add('Link', 'Link--muted') coverLink.style.display = 'inline-flex' coverLink.style.alignItems = 'center' const coverImg = document.createElement('img') coverImg.src = coverIconUrl coverImg.style.width = '18px' coverImg.style.height = '18px' coverImg.style.display = 'block' coverLink.appendChild(coverImg) container.appendChild(coverLink) } const ossLink = document.createElement('a') ossLink.href = buildOssinsightUrl(window.location.pathname) ossLink.target = '_blank' ossLink.classList.add('Link', 'Link--muted') ossLink.style.display = 'inline-flex' ossLink.style.alignItems = 'center' const ossImg = document.createElement('img') ossImg.src = ossinsightIconUrl ossImg.style.width = '18px' ossImg.style.height = '18px' ossImg.style.display = 'block' ossLink.appendChild(ossImg) container.appendChild(ossLink) const strongEl = titleLink.closest('strong') const parentEl = strongEl ? strongEl.parentElement : titleLink.parentElement const labelEl = parentEl && parentEl.querySelector('.Label') || titleLink labelEl.insertAdjacentElement('afterend', container) } // ====== Repo Sidebar Extensions ====== const SIDEBAR_CONTAINER_ID = 'gek-sidebar-extensions' const SIDEBAR_INJECTION_SELECTOR = '.BorderGrid-cell .hide-sm.hide-md' function addSidebarExtensions() { const targetElement = document.querySelector(SIDEBAR_INJECTION_SELECTOR) if (!targetElement || document.getElementById(SIDEBAR_CONTAINER_ID)) return const url = new URL(window.location.href) const { pathname, hostname } = url const wrapper = document.createElement('div') wrapper.id = SIDEBAR_CONTAINER_ID const addItem = (href, name, icon) => { const row = document.createElement('div') row.classList.add('mt-2') const link = document.createElement('a') link.href = href link.target = '_blank' link.classList.add('Link', 'Link--muted') link.style.display = 'inline-flex' link.style.alignItems = 'center' link.style.gap = '8px' const img = document.createElement('img') img.src = icon img.style.width = '16px' img.style.height = '16px' img.style.display = 'block' link.appendChild(img) link.appendChild(document.createTextNode(name)) row.appendChild(link) wrapper.appendChild(row) } addItem(buildDeepWikiUrl(pathname), 'DeepWiki', deepWikiIconUrl) addItem(buildCodeWikiUrl(hostname, pathname), 'CodeWiki', codeWikiIconUrl) addItem(buildZReadUrl(pathname), 'Zread', zReadIconUrl) targetElement.insertAdjacentElement('afterend', wrapper) } // ====== Unified Immediate Injection ====== const injected = {} const injectWhenReady = (id, selector, fn) => { if (injected[id]) return const el = document.querySelector(selector) if (!el) return injected[id] = true fn(el) } const globalObserver = new MutationObserver(() => { injectWhenReady('header', HEADER_SELECTOR, () => addHeaderButtons()) injectWhenReady('sidebar', SIDEBAR_INJECTION_SELECTOR, () => addSidebarExtensions()) injectWhenReady('fileBtns', '[aria-label="Copy path"]', (el) => runFileButtons(el)) injectWhenReady('dirIcons', 'tr.react-directory-row', () => replaceIcons()) }) globalObserver.observe(document.documentElement, { childList: true, subtree: true }) document.addEventListener('turbo:load', () => { Object.keys(injected).forEach(k => delete injected[k]) }) document.addEventListener('turbo:render', () => { Object.keys(injected).forEach(k => delete injected[k]) }) const init = () => { injectWhenReady('header', HEADER_SELECTOR, () => addHeaderButtons()) injectWhenReady('sidebar', SIDEBAR_INJECTION_SELECTOR, () => addSidebarExtensions()) injectWhenReady('fileBtns', '[aria-label="Copy path"]', (el) => runFileButtons(el)) injectWhenReady('dirIcons', 'tr.react-directory-row', () => replaceIcons()) } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init) } else { init() } })()