您需要先安装一个扩展,例如 篡改猴、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或关注我们的公众号极客氢云获取最新地址