Enhanced Past Tense Verb Highlighter

Hide past tense verbs, show base form on hover, and reveal past tense on click with improved accuracy

// ==UserScript==
// @name         Enhanced Past Tense Verb Highlighter
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  Hide past tense verbs, show base form on hover, and reveal past tense on click with improved accuracy
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 扩展的不规则动词词典
    const irregularVerbs = {
    'arose': 'arise',
    'awoke': 'awake',
    'was': 'be',
    'were': 'be',
    'bore': 'bear',
    'beat': 'beat',
    'became': 'become',
    'began': 'begin',
    'bent': 'bend',
    'bet': 'bet',
    'bound': 'bind',
    'bit': 'bite',
    'bled': 'bleed',
    'blew': 'blow',
    'broke': 'break',
    'bred': 'breed',
    'brought': 'bring',
    'broadcast': 'broadcast',
    'built': 'build',
    'burnt': 'burn',
    'burned': 'burn',
    'burst': 'burst',
    'bought': 'buy',
    'caught': 'catch',
    'chose': 'choose',
    'clung': 'cling',
    'came': 'come',
    'cost': 'cost',
    'crept': 'creep',
    'cut': 'cut',
    'dealt': 'deal',
    'dug': 'dig',
    'did': 'do',
    'drew': 'draw',
    'dreamt': 'dream',
    'dreamed': 'dream',
    'drank': 'drink',
    'drove': 'drive',
    'ate': 'eat',
    'fell': 'fall',
    'fed': 'feed',
    'felt': 'feel',
    'fought': 'fight',
    'found': 'find',
    'flew': 'fly',
    'forbade': 'forbid',
    'forgot': 'forget',
    'forgave': 'forgive',
    'froze': 'freeze',
    'got': 'get',
    'gave': 'give',
    'went': 'go',
    'ground': 'grind',
    'grew': 'grow',
    'hung': 'hang',
    'had': 'have',
    'heard': 'hear',
    'hid': 'hide',
    'hit': 'hit',
    'held': 'hold',
    'hurt': 'hurt',
    'kept': 'keep',
    'knelt': 'kneel',
    'knew': 'know',
    'laid': 'lay',
    'led': 'lead',
    'leant': 'lean',
    'leaned': 'lean',
    'learnt': 'learn',
    'learned': 'learn',
    'left': 'leave',
    'lent': 'lend',
    'lay': 'lie',
    'lied': 'lie',
    'lit': 'light',
    'lighted': 'light',
    'lost': 'lose',
    'made': 'make',
    'meant': 'mean',
    'met': 'meet',
    'mowed': 'mow',
    'overtook': 'overtake',
    'paid': 'pay',
    'put': 'put',
    'read': 'read',
    'rode': 'ride',
    'rang': 'ring',
    'rose': 'rise',
    'ran': 'run',
    'sawed': 'saw',
    'said': 'say',
    'saw': 'see',
    'sold': 'sell',
    'sent': 'send',
    'set': 'set',
    'sewed': 'sew',
    'shook': 'shake',
    'shed': 'shed',
    'shone': 'shine',
    'asked': 'ask',
    'believed': 'believe',
    'called': 'call',
    'changed': 'change',
    'continued': 'continue',
    'cooked': 'cook',
    'danced': 'dance',
    'enjoyed': 'enjoy',
    'followed': 'follow',
    'happened': 'happen',
    'helped': 'help',
    'included': 'include',
    'jumped': 'jump',
    'liked': 'like',
    'lived': 'live',
    'looked': 'look',
    'moved': 'move',
    'needed': 'need',
    'opened': 'open',
    'played': 'play',
    'provided': 'provide',
    'rained': 'rain',
    'seemed': 'seem',
    'showed': 'show',
    'started': 'start',
    'studied': 'study',
    'talked': 'talk',
    'tried': 'try',
    'turned': 'turn',
    'used': 'use',
    'visited': 'visit',
    'walked': 'walk',
    'wanted': 'want',
    'watched': 'watch',
    'worked': 'work',
'phoned': 'phone',
'celebrated': 'celebrate'
    };

    // 添加 CSS 样式
    const style = document.createElement('style');
    style.textContent = `
        .verb-tooltip {
            color: transparent;
            border-bottom: 1px dotted black;
            cursor: help;
            position: relative;
        }
        .verb-tooltip.show-past {
            color: inherit;
            background-color: yellow;
            transition: color 0.3s, background-color 0.3s;
        }
        .verb-tooltip::before {
            content: attr(data-base-form);
            position: absolute;
            bottom: 100%;
            left: 50%;
            transform: translateX(-50%);
            background-color: #333;
            color: white;
            padding: 5px;
            border-radius: 3px;
            font-size: 14px;
            white-space: nowrap;
            opacity: 0;
            transition: opacity 0.3s;
            pointer-events: none;
        }
        .verb-tooltip:hover::before {
            opacity: 1;
        }
    `;
    document.head.appendChild(style);

    // 遍历文本节点的函数
    function walkTextNodes(node) {
        if (node.nodeType === Node.TEXT_NODE) {
            processTextNode(node);
        } else {
            for (let child of node.childNodes) {
                walkTextNodes(child);
            }
        }
    }

    // 处理文本节点的函数
    function processTextNode(textNode) {
        const text = textNode.nodeValue;
        const regex = /\b(?!(?:hundred|thousand|indeed|need|filled|used|shared|argued)\b)(\w+ed|went|saw|was|were)\b/g;
        let match;
        let lastIndex = 0;
        const fragments = [];
    
        while ((match = regex.exec(text)) !== null) {
            const verb = match[1];
            const baseForm = getBaseForm(verb);
            
            fragments.push(
                document.createTextNode(text.slice(lastIndex, match.index)),
                createHiddenSpan(verb, baseForm)
            );
            
            lastIndex = regex.lastIndex;
        }
    
        if (fragments.length > 0) {
            fragments.push(document.createTextNode(text.slice(lastIndex)));
            const span = document.createElement('span');
            fragments.forEach(fragment => span.appendChild(fragment));
            textNode.parentNode.replaceChild(span, textNode);
        }
    }

    // 改进的获取动词原形的函数
    function getBaseForm(verb) {
        // 检查是否为不规则动词
        if (irregularVerbs[verb]) {
            return irregularVerbs[verb];
        }
        
        // 处理规则动词
        if (verb.endsWith('ed')) {
            // 如果动词以'eed'结尾,只去掉最后一个'd'
            if (verb.endsWith('eed')) {
                return verb.slice(0, -1);
            }
            // 如果动词以'e'结尾加'd',只去掉'd'
            if (verb.length > 3 && verb[verb.length - 3] === 'e') {
                return verb.slice(0, -1);
            }
            // 处理双写辅音字母的情况,如'stopped' -> 'stop'
            if (verb.length > 4 && verb[verb.length - 3] === verb[verb.length - 4]) {
                return verb.slice(0, -3);
            }
            // 处理以'ied'结尾的情况,如'cried' -> 'cry'
            if (verb.endsWith('ied')) {
                return verb.slice(0, -3) + 'y';
            }
            // 处理以'e'结尾的动词,去掉'ed'
            if (verb.length > 3 && verb[verb.length - 3] !== 'e') {
                return verb.slice(0, -2);
            }
        }
        
        // 如果不符合上述规则,返回原形
        return verb;
    }

    // 创建隐藏的span元素
    function createHiddenSpan(verb, baseForm) {
        const span = document.createElement('span');
        span.textContent = verb;
        span.setAttribute('data-base-form', baseForm);
        span.setAttribute('data-past-form', verb);
        span.classList.add('verb-tooltip');
        
        // 添加点击事件监听器
        span.addEventListener('click', function(e) {
            e.preventDefault(); // 防止可能的链接点击
            this.classList.toggle('show-past');
            
            // 3秒后自动隐藏
            setTimeout(() => {
                this.classList.remove('show-past');
            }, 3000);
        });
        
        return span;
    }

    // 在页面加载完成后执行脚本
    window.addEventListener('load', function() {
        walkTextNodes(document.body);
    });
})();