// ==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()
}
})()