使用MutationObserver监听元素变动,处理动态数据的繁体中文内容,并支持标题转换。
// ==UserScript== // @name 馒头繁转简 // @namespace http://tampermonkey.net/ // @version 2025.09.15 // @description 使用MutationObserver监听元素变动,处理动态数据的繁体中文内容,并支持标题转换。 // @author myderr // @match https://m-team.cc/* // @match https://kp.m-team.cc/* // @match https://next.m-team.cc/* // @match https://wiki.m-team.cc/* // @match https://zp.m-team.io/* // @match https://ticket.m-team.io/* // @icon https://www.google.com/s2/favicons?sz=64&domain=m-team.cc // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/t2cn.js // @grant unsafeWindow // @run-at document-start // @license MIT // ==/UserScript== (function() { 'use strict'; // ================================================================================= // 1. 初始化转换器 // ================================================================================= const converter = OpenCC.Converter({ from: 'hk', to: 'cn' }); const convertText = (text) => { if (!text || typeof text !== 'string') return text; return converter(text); }; // ================================================================================= // 2. 遍历和转换 DOM 节点的函数 // ================================================================================= function traverseAndConvert(node) { // 排除一些不需要转换的标签 if (node.nodeType === 1 && (node.tagName === 'SCRIPT' || node.tagName === 'STYLE' || node.tagName === 'TEXTAREA')) { return; } // 如果是文本节点并且包含中文字符,直接转换 if (node.nodeType === 3 && /[\u4e00-\u9fa5]/.test(node.nodeValue)) { const originalText = node.nodeValue; const simplifiedText = convertText(originalText); if (originalText !== simplifiedText) { node.nodeValue = simplifiedText; } } // 如果是元素节点,遍历其所有子节点 if (node.nodeType === 1) { node.childNodes.forEach(traverseAndConvert); } } // ================================================================================= // 3. DOM 变更监视 (处理 Body 内的动态内容) // ================================================================================= const bodyObserver = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(node => { traverseAndConvert(node); }); } } }); // ================================================================================= // 4. 启动脚本 (核心逻辑) // ================================================================================= window.addEventListener('DOMContentLoaded', () => { // --- 针对 Body 的处理 --- // 首次转换页面上已有的静态内容 traverseAndConvert(document.body); // 开始监视 Body 未来的变化 bodyObserver.observe(document.body, { childList: true, subtree: true }); // --- 【新增】针对 Title 的处理 --- const titleElement = document.querySelector('head > title'); if (titleElement) { // 首次转换页面标题 document.title = convertText(document.title); // 创建一个专门监视 title 变化的观察者 const titleObserver = new MutationObserver(() => { const newTitle = document.title; const convertedTitle = convertText(newTitle); if (newTitle !== convertedTitle) { // 断开观察,防止修改标题触发无限循环 titleObserver.disconnect(); document.title = convertedTitle; // 修改完毕后,重新开始观察 titleObserver.observe(titleElement, { childList: true }); } }); // 开始观察 title 元素内的子节点(即文本)变化 titleObserver.observe(titleElement, { childList: true }); } }); })();