Enhance English Reading Experience

Add spaces after commas and periods in <p> tags for better English reading experience

// ==UserScript==
// @name         Enhance English Reading Experience
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Add spaces after commas and periods in <p> tags for better English reading experience
// @author       Dragontx
// @license      MIT
// @icon         https://www.google.com/s2/favicons?domain=example.com
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 缓存已处理的p标签,标签页级
    const enhancedSet = new Set();

    function enhanceParagraphs() {
        const paragraphs = document.querySelectorAll('p');
        // console.log('[EnhanceEnglish] 检测到', paragraphs.length, '个<p>标签');
        let enhancedCount = 0;
        paragraphs.forEach(p => {
            if (!enhancedSet.has(p)) {
                // 只处理纯文本节点,保留标签结构
                function processNode(node) {
                    if (node.nodeType === Node.TEXT_NODE) {
                        // 替换英文逗号和句号后的空格,但跳过数字中的逗号和句号
                        const nbsp3 = '\u00A0\u00A0\u00A0';
                        const nbsp7 = '\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0';
                        let text = node.textContent;
                        // 处理非数字之间的逗号
                        text = text.replace(/([^0-9]),(?!\s*[0-9])/g, '$1,' + nbsp3);
                        // 处理非数字之间的句号
                        text = text.replace(/([^0-9])\.(?!\s*[0-9])/g, '$1.' + nbsp7);
                        node.textContent = text;
                    } else if (node.nodeType === Node.ELEMENT_NODE) {
                        node.childNodes.forEach(processNode);
                    }
                }
                p.childNodes.forEach(processNode);
                enhancedSet.add(p);
            }
        });
        // console.log('[EnhanceEnglish] 本次处理新增', enhancedCount, '个<p>');
    }

    // 延迟加载文本的处理
    let scrollTimeout = null;
    function onScroll() {
        if (scrollTimeout) clearTimeout(scrollTimeout);
        scrollTimeout = setTimeout(() => {
            // console.log('[EnhanceEnglish] 触发滚动增量处理');
            enhanceParagraphs();
        }, 300);
    }

    // 页面加载后处理一次
    window.addEventListener('DOMContentLoaded', () => {
        // console.log('[EnhanceEnglish] DOMContentLoaded');
        enhanceParagraphs();
    });
    // 监听滚动事件,增量处理新出现的p标签
    window.addEventListener('scroll', onScroll, { passive: true });
    // 监听DOM变动(如SPA、异步加载)
    const observer = new MutationObserver(() => {
        // console.log('[EnhanceEnglish] MutationObserver触发');
        enhanceParagraphs();
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();