网页高亮关键字

对网页上的文字进行高亮显示,如果对你有帮助,可以随意修改使用

От 30.04.2023. Виж последната версия.

// ==UserScript==
// @name         网页高亮关键字
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  对网页上的文字进行高亮显示,如果对你有帮助,可以随意修改使用
// @author       You
// @include           *
// @grant        GM_addStyle
// @license MIT

// ==/UserScript==
(function () {

     // 高亮
    class HIGHTLIGHT {
        // 需要高亮的关键字
        static words = ["最", "引", "抖音", "直播", "网红", "投币", "游戏","0","1","2","3","4","5","6","7"]

        // 检测规则
        static reg = new RegExp(`(${this.words.join("|")})`, "g")

        static highlightStyle = `
                        .mt_highlight{
                            background-color: rgb(255, 21, 21);
                            border-radius: 2px;
                            box-shadow: 0px 0px 1px 1px rgba(0, 0, 0,0.1);
                            cursor: pointer;
                            color: white;
                            padding: 1px 1px;
                        }
                        `

        /**
         * @description: 返回需要被高亮的节点map{textNode,未来会被修改成目标的值}
         * @param {map} nodeMap
         * @return {void}
         */
        static highlight(nodeMap) {
            nodeMap.forEach((value, node) => {
                let newInnerHTML = value.replace(this.reg, `<span class="mt_highlight">$1</span>`)

                if (value != newInnerHTML) {

                    let newNode = document.createElement("span")
                    newNode.innerHTML = newInnerHTML
                    node.parentElement.replaceChild(newNode, node)

                }
            })
        }

    }



    /**
     * @description: 遍历找出所有文本节点
     * @param {*} node
     * @return {*} 节点map
     */
    function textMap(node) {
        // 存储文本节点
        let nodeMap = new Map()

        const walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT, (textNode) => {
            if (textNode.parentElement.nodeName === "SCRIPT" |
                textNode.parentElement.nodeName === "script" |
                textNode.parentElement.nodeName === "style" |
                textNode.parentElement.nodeName === "STYLE" |
                textNode.parentElement.className === "mt_highlight"
            ) {
                return NodeFilter.FILTER_SKIP
            }

            if (textNode.data.length < 20) {
                return textNode.data.replace(/[\n \t]/g, "").length ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
            }

            return NodeFilter.FILTER_ACCEPT
        })

        while ((textNode = walker.nextNode())) {
            nodeMap.set(textNode, textNode.data)
        }

        return nodeMap
    }


    class ThreadWork {
        static strFun = (() => {

        }).toString()

        static url = window.URL.createObjectURL(new Blob(["(" + this.strFun + ")()"], { type: "text/javascript" }))

        static addWorker() {
            new Worker(this.url);
        }
    }


   

    /**
     * @description: 动态检测新节点,并执行高亮
     * @return {*}
     */
    function watch() {
        // 选择需要观察变动的节点
        const targetNode = document.body;

        // 观察器的配置(需要观察什么变动)
        const config = { attributes: false, childList: true, subtree: true, characterData: true };

        // 当观察到变动时执行的回调函数
        const callback = function (mutationsList, observer) {
            let nodeMap = new Map
            setTimeout(() => {
                mutationsList.forEach(node => { nodeMap.set(node.target) })
                nodeMap.forEach((value, node) => {
                    doOnce(node)
                })
            }, 1);
        };

        // 创建一个观察器实例并传入回调函数
        const observer = new MutationObserver(callback);

        // 以上述配置开始观察目标节点
        observer.observe(targetNode, config);
    }



    ///////////////////////////////////////////////////////////

    GM_addStyle(HIGHTLIGHT.highlightStyle)
    // 静态页面的检测
    let nodeMap = textMap(document.body)
    console.log(nodeMap);
    HIGHTLIGHT.highlight(nodeMap)
    nodeMap.clear()

    // 动态更新内容的检测
    // 减少节点的重复检测
    let doOnce = ((wait) => {
        let timer = null;
        // 存储动态更新的节点
        let elMap = new Map

        return (el) => {
            // 添加节点
            elMap.set(el)
            if (!timer) {
                timer = setTimeout(() => {
                    //console.log(elMap);
                    elMap.forEach((value, el) => {
                        setTimeout(() => {

                            let nodeMap = textMap(el)
                            HIGHTLIGHT.highlight(nodeMap)
                            nodeMap = null

                        }, 1);
                    })
                    elMap.clear()
                    timer = null
                }, wait);
            }
        }
    })(100)

    watch()

}
)()