// ==UserScript== // @name:zh-CN Ant Design 组件菜单 (^4.0.0) // @name Ant Design Components Dashboard (React) (^4.0.0) // @namespace https://github.com/xianghongai/Ant-Design-Components-Dashboard-React // @version 0.0.1 // @description:zh-CN 更方便的查看 Ant Design (React) 组件 // @description Better view for Ant Design (React) // @author Nicholas Hsiang / 山茶树和葡萄树 // @icon https://xinlu.ink/favicon.ico // @match https://ant.design/components/* // @grant none // @downloadURL none // ==/UserScript== (function () { "use strict"; const bodyContainer = document.querySelector("body"); const titleText = "Ant Design of React"; const gridSelector = ".aside-container.menu-site"; const columnSelector = ".ant-menu-item-group"; const columnTitleSelector = ".ant-menu-item-group-title"; const menuListSelector = ".ant-menu-item-group-list"; const menuItemSelector = ".ant-menu-item-group-list .ant-menu-item"; const helpEnable = true; const helpSelector = ".api-container"; const removeSelector = gridSelector + ">li:not(.ant-menu-item-group)"; function initialDashboard() { initialToggle(); initialStyle(); initialMenu(); initialHelp(); handleEvent(); resetLayout(); } let interval = null; function ready() { const originEle = document.querySelector(gridSelector); if (originEle) { clearInterval(interval); // Dashboard initialDashboard(); // Other } } interval = setInterval(ready, 1000); // #region MENU /** 生成 Menu */ function initialMenu() { // Wrapper const wrapperEle = document.createElement("section"); wrapperEle.classList.add("hs-dashboard__wrapper", "hs-hide"); // Header const headerEle = document.createElement("header"); headerEle.classList.add("hs-dashboard__header"); // Title const titleEle = document.createElement("h1"); titleEle.classList.add("hs-dashboard__title"); titleEle.innerText = titleText || ""; // Title → Header headerEle.appendChild(titleEle); // Menu const containerEle = document.createElement("div"); containerEle.classList.add("hs-dashboard__container"); // 0. 移除一些不要的元素 if (removeSelector) { const removeEle = document.querySelectorAll(removeSelector); if (removeEle) { removeEle.forEach((element) => { element.remove(); }); } } // 1. 先从页面上获取 DOM const menuEle = document.querySelector(gridSelector); // .cloneNode(true); menuEle.classList.add("hs-dashboard__grid"); // 追加新的样式 // Menu → Container containerEle.appendChild(menuEle); // 2. 内部元素追加新的样式 // 2.1 column const columnEle = containerEle.querySelectorAll(columnSelector); columnEle.forEach((element) => { element.classList.add("hs-dashboard__column"); }); // 2.2 title const columnTitleEle = containerEle.querySelectorAll(columnTitleSelector); columnTitleEle.forEach((element) => { element.classList.add("hs-dashboard__item-title"); }); // 2.3 menu list const menuListEle = containerEle.querySelectorAll(menuListSelector); menuListEle.forEach((element) => { element.classList.add("hs-dashboard__list"); }); // 2.4 menu item const menuItemEle = containerEle.querySelectorAll(menuItemSelector); menuItemEle.forEach((element) => { element.classList.add("hs-dashboard__item"); }); // header,container → wrapper wrapperEle.appendChild(headerEle); wrapperEle.appendChild(containerEle); // wrapper → body bodyContainer.appendChild(wrapperEle); } // #endregion MENU // #region Event /** 注册事件 */ function handleEvent() { const wrapperEle = document.querySelector(".hs-dashboard__wrapper"); bodyContainer.addEventListener("click", (event) => { const targetEle = event.target; const isItem = getParents(targetEle, ".hs-dashboard__item") || hasClass(targetEle, "hs-dashboard__item") || (getParents(targetEle, ".hs-dashboard__column") && getParents(targetEle, ".hs-dashboard__list")); const isToggle = getParents(targetEle, ".hs-dashboard__toggle-menu") || hasClass(targetEle, "hs-dashboard__toggle-menu"); const isHelp = getParents(targetEle, ".hs-dashboard__toggle-help") || hasClass(targetEle, "hs-dashboard__toggle-help"); if (isItem) { clearStyle(wrapperEle); } else if (isToggle) { wrapperEle.classList.toggle("hs-hide"); bodyContainer.classList.toggle("hs-body-overflow_hide"); } else if (isHelp) { clearStyle(wrapperEle); handleHelp(); } }); } function clearStyle(wrapperEle) { wrapperEle.classList.add("hs-hide"); bodyContainer.classList.remove("hs-body-overflow_hide"); } // #endregion Event // #region HELP /** 是否启用‘页面滚动至指定位置’ */ function initialHelp() { if (!helpEnable) { const ele = document.querySelector(".hs-dashboard__toggle-help"); ele.classList.add("hs-hide"); } } /** 页面滚动至指定位置 */ function handleHelp() { if (!helpSelector) { return false; } const helpEle = document.querySelector(helpSelector); const top = helpEle.getBoundingClientRect().top + window.pageYOffset; window.scrollTo({ top, behavior: "smooth", }); } // #endregion HELP // #region STYLE /** 添加样式 */ function initialStyle() { const tpl = initialStyleTpl(); const headEle = document.head || document.getElementsByTagName("head")[0]; const styleEle = document.createElement("style"); styleEle.type = "text/css"; if (styleEle.styleSheet) { styleEle.styleSheet.cssText = tpl; } else { styleEle.appendChild(document.createTextNode(tpl)); } headEle.appendChild(styleEle); } /** 样式表 */ function initialStyleTpl() { return ` .hs-hide { display: none !important; } .hs-body-overflow_hide { height: 100% !important; overflow: hidden !important; } /* #region toggle */ .hs-dashboard__toggle { position: fixed; z-index: 99999; top: 5px; right: 5px; } .hs-dashboard__toggle-item { width: 28px; height: 28px; margin-top: 10px; margin-bottom: 10px; overflow: hidden; line-height: 30px !important; border-radius: 50%; border: 1px solid #ccc; text-align: center; color: #555; background-color: #fff; cursor: pointer; transition: all 0.2s; } .hs-dashboard__toggle-item:hover { border-color: #aaa; color: #111; } .hs-dashboard__toggle-icon { font-style: normal !important; } /* #endregion toggle */ /* #region wrapper */ .hs-dashboard__wrapper { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 99998; overflow-y: auto; background-color: #fff; font-size: 16px; } .hs-dashboard__wrapper::-webkit-scrollbar { width: 8px; height: 6px; background: rgba(0, 0, 0, 0.1); } .hs-dashboard__wrapper::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.3); } .hs-dashboard__wrapper::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.1); } /* #endregion wrapper */ .hs-dashboard__header { padding-top: 10px; text-align: center; } .hs-dashboard__title { margin: 0; padding-top: 10px; padding-bottom: 10px; font-size: 1em; font-weight: normal; } /* #region grid */ .hs-dashboard__grid { display: flex; justify-content: space-evenly; /* justify-content: space-around; */ margin: 0; padding: 0; list-style: none; } .hs-dashboard__column { padding-right: 10px; padding-left: 10px; } .hs-dashboard__column a { text-decoration: none; } .hs-dashboard__column { list-style: none; } .hs-dashboard__column ul { padding: 0; } .hs-dashboard__column li { list-style: none; } .hs-dashboard__column .hs-dashboard__item-title { display: block; margin-top: 0 !important; } /* #endregion grid */ /* #region custom */ .fixed-widgets { z-index: 9; } body[data-theme='dark'] .hs-dashboard__wrapper, body[data-theme='dark'] .hs-menu-wrapper.ant-menu { color: rgba(255,255,255,0.65); background-color: #141414; } body[data-theme='dark'] .hs-dashboard__title { color: rgba(255,255,255,0.65); } .hs-dashboard__column .hs-dashboard__list .hs-dashboard__item, .hs-dashboard__column .hs-dashboard__list .ant-menu-item { height: 36px; line-height: 36px; } /* #endregion custom */ `; } // #endregion STYLE // #region TOGGLE /** 生成 Dashboard 开关 */ function initialToggle() { const tpl = initialToggleTpl(); const ele = document.createElement("section"); // ele.className = 'hs-dashboard__toggle'; // ele.setAttribute("class", "hs-dashboard__toggle"); ele.classList.add("hs-dashboard__toggle"); ele.innerHTML = tpl; // toggle → body bodyContainer.appendChild(ele); } /** Dashboard 开关 DOM */ function initialToggleTpl() { return `