Highlight Trump Name & Hide Cursor on Hover on Whitehouse.gov (For Accessibility)

Highlights mentions of Donald J. Trump on www.whitehouse.gov with bold/larger font and hides the cursor when hovering over them for better visibility.

目前為 2025-04-22 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Highlight Trump Name & Hide Cursor on Hover on Whitehouse.gov (For Accessibility)
// @name:zh-CN   高亮白宫网站上的特朗普名字,并在悬停时隐藏光标 (视障辅助)
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Highlights mentions of Donald J. Trump on www.whitehouse.gov with bold/larger font and hides the cursor when hovering over them for better visibility.
// @description:zh-CN 在 www.whitehouse.gov 网站上将“Donald J. Trump”及其变体的字体加粗加大,并在鼠标悬停时隐藏光标,以提高可见性。
// @author       Lyragosa
// @match        *://www.whitehouse.gov/*
// @grant        GM_addStyle
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- 配置 ---
    const highlightStyleClass = 'highlighted-trump-name-vz'; // 自定义CSS类名,避免冲突
    const patternsToHighlight = [
        /\bPresident\s+Donald\s+J\.\s+Trump\b/gi, // President Donald J. Trump
        /\bPresident\s+Trump\b/gi,              // President Trump
        /\bDonald\s+J\.\s+Trump\b/gi,          // Donald J. Trump
        /\bTrump\b/gi                         // 单独的 "Trump"
    ];
    // --- CSS 样式 ---
    // 更新:增加了 :hover 规则来隐藏光标
    const cssStyle = `
        .${highlightStyleClass} {
            font-weight: bold !important;
            font-size: 1.2em !important; /* 比周围文字大20% */
            /* 可以添加其他样式 */
        }
        /* 新增:当鼠标悬停在高亮的span上时,隐藏光标 */
        .${highlightStyleClass}:hover {
            cursor: none !important;
        }
    `;

    // --- 注入CSS样式 ---
    GM_addStyle(cssStyle);

    // --- 核心处理函数 ---
    function highlightTextInNode(node) {
        const walker = document.createTreeWalker(
            node,
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function(textNode) {
                    if (textNode.parentNode.nodeName === 'SCRIPT' || textNode.parentNode.nodeName === 'STYLE') {
                        return NodeFilter.FILTER_REJECT;
                    }
                    if (textNode.parentNode.classList.contains(highlightStyleClass)) {
                        return NodeFilter.FILTER_REJECT;
                    }
                    if (textNode.nodeValue.trim() === '') {
                        return NodeFilter.FILTER_SKIP;
                    }
                    for (const pattern of patternsToHighlight) {
                        pattern.lastIndex = 0;
                        if (pattern.test(textNode.nodeValue)) {
                            return NodeFilter.FILTER_ACCEPT;
                        }
                    }
                    return NodeFilter.FILTER_SKIP;
                }
            },
            false
        );

        let textNode;
        const nodesToProcess = [];
        while(textNode = walker.nextNode()) {
            nodesToProcess.push(textNode);
        }

        for (const nodeToProcess of nodesToProcess) {
            let currentNode = nodeToProcess;
            let nodeReplaced = false; // 标记节点是否已被替换

            for (const pattern of patternsToHighlight) {
                if (nodeReplaced) break; // 如果节点已被替换,跳过后续模式对此节点的处理

                pattern.lastIndex = 0;
                let match;
                let lastIndex = 0;
                const fragment = document.createDocumentFragment();
                let foundMatchInPattern = false;

                while ((match = pattern.exec(currentNode.nodeValue)) !== null) {
                    foundMatchInPattern = true;
                    const matchedText = match[0];
                    const matchIndex = match.index;

                    if (matchIndex > lastIndex) {
                        fragment.appendChild(document.createTextNode(currentNode.nodeValue.substring(lastIndex, matchIndex)));
                    }

                    const span = document.createElement('span');
                    span.className = highlightStyleClass;
                    span.textContent = matchedText;
                    fragment.appendChild(span);

                    lastIndex = pattern.lastIndex;
                 }

                 if (foundMatchInPattern) {
                     if (lastIndex < currentNode.nodeValue.length) {
                         fragment.appendChild(document.createTextNode(currentNode.nodeValue.substring(lastIndex)));
                     }
                     if (currentNode.parentNode) {
                         currentNode.parentNode.replaceChild(fragment, currentNode);
                         nodeReplaced = true; // 标记此原始节点已被替换
                     }
                 }
            }
        }
    }

    // --- 初始执行 ---
    highlightTextInNode(document.body);

    // --- 监听DOM变化 (处理动态加载的内容) ---
    const observer = new MutationObserver(function(mutationsList) {
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                mutation.addedNodes.forEach(function(addedNode) {
                    if (addedNode.nodeType === Node.ELEMENT_NODE) {
                        // 检查添加的节点本身或其父节点是否是高亮节点,避免递归触发
                        if (!addedNode.classList || !addedNode.classList.contains(highlightStyleClass)) {
                             if (!addedNode.parentNode || !addedNode.parentNode.classList || !addedNode.parentNode.classList.contains(highlightStyleClass)){
                                highlightTextInNode(addedNode);
                            }
                        }
                    }
                });
            }
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

})();