您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hides MAL-Sync popups that contain "Chapter: X/X" so they don't appear after finishing a chapter.
// ==UserScript== // @name Hide MAL-Sync Chapter Popups // @namespace http://tampermonkey.net/ // @version 1.2 // @description Hides MAL-Sync popups that contain "Chapter: X/X" so they don't appear after finishing a chapter. // @author YourName // @match (Insert your urls here) // @run-at document-end // @grant none // @license MIT // ==/UserScript== (function () { const CHAPTER_PATTERN = /Chapter\s*[::]\s*\d+(?:\s*[\//]\s*(?:\d+|[\??]))?/i; const FLASH_SEL = '.flash.type-update.flashinfo'; const SENTINEL = 'data-hidden-by-hide-malsync'; // avoid double work const normalize = (s) => (s || '') .replace(/\u00A0/g, ' ') // nbsp -> space .replace(/\s+/g, ' ') // collapse whitespace .trim(); function shouldHide(el) { const txt = normalize(el.textContent); return CHAPTER_PATTERN.test(txt); } function removeBox(node) { const box = node.matches?.(FLASH_SEL) ? node : node.closest?.(FLASH_SEL); if (!box || box.getAttribute(SENTINEL) === '1') return; box.setAttribute(SENTINEL, '1'); box.remove(); } function sweep(root = document) { root.querySelectorAll(FLASH_SEL).forEach((el) => { if (shouldHide(el)) removeBox(el); }); } function observe(root) { const mo = new MutationObserver((muts) => { for (const m of muts) { if (m.type === 'childList') { m.addedNodes.forEach((n) => { if (n.nodeType !== 1) return; if (n.matches?.(FLASH_SEL)) { if (shouldHide(n)) removeBox(n); } else { n.querySelectorAll?.(FLASH_SEL).forEach((el) => { if (shouldHide(el)) removeBox(el); }); } }); } else if (m.type === 'characterData') { const el = m.target.parentElement?.closest?.(FLASH_SEL); if (el && shouldHide(el)) removeBox(el); } else if (m.type === 'attributes') { const t = m.target; if (t instanceof Element && t.matches(FLASH_SEL) && shouldHide(t)) removeBox(t); } } }); mo.observe(root, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ['class', 'style'], }); } function watchIframe(iframe) { const hook = () => { try { const d = iframe.contentDocument; if (!d) return; sweep(d); observe(d); } catch {} }; iframe.addEventListener('load', hook); hook(); } function start() { sweep(document); observe(document); document.querySelectorAll('iframe').forEach(watchIframe); setInterval(() => sweep(document), 1500); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', start, { once: true }); } else { start(); } })();