Greasy Fork

来自缓存

Greasy Fork is available in English.

文本选中高亮相同内容

在网页中选中一些文字时,自动将页面中相同的文字高亮显示

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         文本选中高亮相同内容
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  在网页中选中一些文字时,自动将页面中相同的文字高亮显示
// @author       damu
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    let lastHighlightClass = 'tm-highlighted-text';

    function removeHighlights() {
        document.querySelectorAll('.' + lastHighlightClass).forEach(el => {
            const parent = el.parentNode;
            parent.replaceChild(document.createTextNode(el.textContent), el);
            parent.normalize(); // 合并相邻文本节点
        });
    }

    function highlightText(text) {
        if (!text || text.trim().length < 2) return;
        const regex = new RegExp(text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');

        // 获取当前选中的范围
        const selection = window.getSelection();
        const selectedNode = selection.anchorNode; // 获取选区起点所在的节点

        const treeWalker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function (node) {
                    // 过滤掉脚本、样式、隐藏元素、表单控件等
                    const parent = node.parentNode;
                    if (!parent || !parent.offsetParent) return NodeFilter.FILTER_REJECT;
                    const tag = parent.nodeName.toLowerCase();
                    if (['script', 'style', 'textarea', 'input', 'button', 'select'].includes(tag))
                        return NodeFilter.FILTER_REJECT;

                    // 如果是当前选中的文本节点,则跳过
                    if (node === selectedNode) return NodeFilter.FILTER_REJECT;

                    return NodeFilter.FILTER_ACCEPT;
                }
            },
            false
        );

        let node;
        while (node = treeWalker.nextNode()) {
            const matches = [...node.textContent.matchAll(regex)];
            if (matches.length === 0) continue;

            let currentNode = node;
            matches.reverse().forEach(match => {
                const start = match.index;
                const end = start + match[0].length;

                const before = currentNode.textContent.slice(0, start);
                const matched = currentNode.textContent.slice(start, end);
                const after = currentNode.textContent.slice(end);

                const span = document.createElement('span');
                span.textContent = matched;
                span.className = lastHighlightClass;
                span.style.backgroundColor = 'yellow';
                span.style.color = 'black';

                const afterNode = document.createTextNode(after);
                const matchedNode = span;
                const beforeNode = document.createTextNode(before);

                const parent = currentNode.parentNode;
                parent.insertBefore(afterNode, currentNode.nextSibling);
                parent.insertBefore(matchedNode, afterNode);
                parent.insertBefore(beforeNode, matchedNode);
                parent.removeChild(currentNode);

                currentNode = beforeNode;
            });
        }
    }

    document.addEventListener('mouseup', () => {
        setTimeout(() => {
            const selection = window.getSelection();
            const selectedText = selection.toString().trim();
            removeHighlights();
            if (selectedText.length >= 2) {
                highlightText(selectedText);
            }
        }, 10); // 延迟以确保 selection 获取正确
    });
})();