您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
dom manipulation util
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/499616/1565714/dom%20util.js
const HtmlSanitizer = { tempElement: document.createElement("div"), sanitize: function (/** @type {string} */ htmlString) { this.tempElement.innerText = htmlString; return this.tempElement.innerHTML; }, }; const trustedHTMLPolicy = window.trustedTypes.createPolicy('mmHtmlPolicy', { createHTML: (input) => input // Add sanitization logic here if necessary }); class HtmlString extends String { /**@type {HTMLElement|null} */ element = null; /**@param {string} value */ constructor(value) { super(value); } /**@returns {HTMLElement} */ asElement() { if (this.element !== null) { return this.element; } const temp = document.createElement("div"); temp.innerHTML = trustedHTMLPolicy.createHTML(this.valueOf()); if (temp.childElementCount > 1) { throw new Error("html template does not accept more than 1 element"); } this.element = /**@type {HTMLElement} */ (temp.firstElementChild); return /**@type {HTMLElement} */ (this.element); } } /** * @param {string} selector * @param {HTMLElement|Document} rootElement * @returns {HTMLElement|null} */ function $findElm(selector, rootElement = document) { return /**@type {HTMLElement|null} */ (rootElement.querySelector(selector)); } /** * @param {string} selector * @param {HTMLElement|Document} rootElement * @returns {HTMLElement} */ function $findElmStrictly(selector, rootElement = document) { const element = /**@type {HTMLElement|null} */ (rootElement.querySelector(selector)); if (element === null) { throw new Error(`Element with selector '${selector}' not found`); } return element; } /** * @param {string} selector * @returns {NodeListOf<HTMLElement>} */ function $findAll(selector) { return /**@type {NodeListOf<HTMLElement>} */ (document.querySelectorAll(selector)); } /**@typedef {string|HtmlString|number|boolean} TInterpolatedValue */ /** * safe html interpolation * @param {TemplateStringsArray} literalValues * @param {TInterpolatedValue[]|TInterpolatedValue[][]} interpolatedValues * @returns {HtmlString} */ function html(literalValues, ...interpolatedValues) { let result = ""; interpolatedValues.forEach((currentInterpolatedVal, idx) => { let literalVal = literalValues[idx]; let interpolatedVal = ""; if (Array.isArray(currentInterpolatedVal)) { interpolatedVal = currentInterpolatedVal.join("\n"); } else if (typeof currentInterpolatedVal !== "boolean") { interpolatedVal = currentInterpolatedVal.toString(); } const isSanitize = !literalVal.endsWith("$"); if (isSanitize) { result += literalVal; result += HtmlSanitizer.sanitize(interpolatedVal); } else { literalVal = literalVal.slice(0, -1); result += literalVal; result += interpolatedVal; } }); result += literalValues.slice(-1); return new HtmlString(result); } /** * wait for element to be added to the DOM * @param {string} selector * @param {number} timeout * @param {(element: HTMLElement) => void} callback * @returns {CallableFunction | null} callback to stop observing */ function waitForElement(selector, timeout, callback) { let matchingElement = /**@type {HTMLElement|null} */ (document.querySelector(selector)); if (matchingElement) { callback(matchingElement); return null; } const observer = new MutationObserver((mutations) => { for (let mutation of mutations) { if (!mutation.addedNodes) continue; for (let node of mutation.addedNodes) { if (node.matches && node.matches(selector)) { callback(node); observer.disconnect(); clearTimeout(timeoutId); return; } if (node.querySelector) { matchingElement = /**@type {HTMLElement|null} */ (node.querySelector(selector)); if (matchingElement !== null) { callback(matchingElement); observer.disconnect(); clearTimeout(timeoutId); return; } } } } }); observer.observe(document.documentElement, { childList: true, subtree: true, attributes: false, characterData: false, }); const timeoutId = setTimeout(() => { observer.disconnect(); console.log(`Timeout reached: Element "${selector}" not found`); }, timeout); return () => { observer.disconnect(); }; } /** * Smoothly scrolls the page to the given element with an optional offset above it. * * @param {HTMLElement} el - The target element to scroll to. * @param {number} [offset=20] - The number of pixels to offset above the element. * @returns {void} */ function scrollToElementWithOffset(el, offset = 20) { const rect = el.getBoundingClientRect(); const scrollTop = window.pageYOffset || document.documentElement.scrollTop; const targetY = rect.top + scrollTop - offset; window.scrollTo({ top: targetY, behavior: 'smooth' }); } /** * Appends a <style> tag with class 'mm-styles' and the given CSS rules to the document head. * * @param {string} cssText - The CSS rules to insert into the style tag. * @returns {HTMLStyleElement} The created style element. */ function addStyles(cssText) { const styleEl = document.createElement('style'); styleEl.className = 'mm-styles'; styleEl.textContent = cssText; document.head.appendChild(styleEl); return styleEl; }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址