// ==UserScript== // @name Ant Design 组件菜单 (^4.4.3) // @namespace https://xianghongai.github.io/ // @version 0.0.5 // @description 快速预览 Ant Design 组件菜单面板 // @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"; 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 `
`; } // #endregion TOGGLE // #region COMMON function hasClass(el, className) { if (el.classList) { return el.classList.contains(className); } else { return !!el.className.match(new RegExp("(\\s|^)" + className + "(\\s|$)")); } } function getParents(elem, selector) { // Element.matches() polyfill if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function (s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; }; } // Get the closest matching element for (; elem && elem !== document; elem = elem.parentNode) { if (elem.matches(selector)) return elem; } return null; } // #endregion function resetLayout() { const pageSider = document.querySelector(".main-wrapper>.ant-row>.main-menu"); const pageContainer = document.querySelector(".main-wrapper>.ant-row>.ant-col+.ant-col"); pageSider.classList.add("hs-hide"); pageContainer.classList.remove("ant-col-md-18", "ant-col-lg-18", "ant-col-xl-19", "ant-col-xxl-20"); pageContainer.classList.add("ant-col-md-24", "ant-col-lg-24", "ant-col-xl-24", "ant-col-xxl-24"); } })();