Eink Polish

优化网页与浏览器插件在 eink 设备上的显示

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Eink Polish
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  优化网页与浏览器插件在 eink 设备上的显示
// @author       chen
// @match        https://*/*
// @icon         none
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict'; // 开启严格模式,让浏览器更规范地执行代码

    // 1. 定义我们要强制生效的 CSS 样式
    const css = `
        p, h1, h2, h3, h4, h5, h6, a, div, ul, ol, table {
            /* --- 基础清理:禁用动画和特效 --- */
            animation: none !important;     /* 禁用所有动画 */
            transition: none !important;    /* 禁用所有渐变过渡 */
            box-shadow: none !important;    /* 禁用所有元素阴影 */
            filter: none !important;        /* 禁用所有滤镜(比如模糊效果) */

            /* --- 文字 --- */
            font-weight: bold !important;   /* 加粗,提高墨水屏上的辨识度 */
            color: #000 !important;       /* 强制纯黑文字 */
            text-shadow:                    /* 给文字加物理描边,对抗发虚 */
                -1px -1px 0 #FFF,
                1px -1px 0 #FFF,
                -1px  1px 0 #FFF,
                1px  1px 0 #FFF;

            /* --- 控件 --- */
            border-color: #333333 !important;      /* 让边框变成深色,防止按钮背景变白后找不到按钮在哪里 */
            
        }
    `;

    // 2. 核心动作:把上面的 CSS 注入到指定的“区域”
    function injectStyle(target) {
        // 如果这个区域已经打过我们留下的标记,说明注入过了,直接跳过,防止重复添加
        if (target.__styleInjected) return;

        // 创建一个 <style> 标签,并把我们的 CSS 文本塞进去
        const style = document.createElement('style');
        style.textContent = css;

        // 把 <style> 标签正式插入到目标区域中
        target.appendChild(style);

        // 给这个区域打上标记,表示“我已经处理过啦”
        target.__styleInjected = true;
    }

    // 3. 扫描网页节点:寻找并处理那些带有 Shadow DOM 的元素
    // 因为你提到“不存在嵌套情况”,所以我们只需要查一次表面即可,不需要无限往下深挖
    function scanAndInject(node) {
        // 第一步:如果当前检查的这个元素自身就是一个带有 Shadow DOM 的节点,直接注入
        if (node.shadowRoot) {
            injectStyle(node.shadowRoot);
        }

        // 第二步:如果这个元素是个正常的 HTML 标签(比如 <div>),找找它肚子里有没有带 Shadow DOM 的子元素
        if (node.querySelectorAll) {
            // querySelectorAll('*') 会把当前节点下的所有子孙元素都找出来
            node.querySelectorAll('*').forEach(el => {
                if (el.shadowRoot) {
                    injectStyle(el.shadowRoot);
                }
            });
        }
    }

    // ==========================================
    // 下面是脚本的执行主流程
    // ==========================================

    // 【新增修复】原代码漏掉了最关键的一步:给网页本身(主 DOM)注入样式!
    // 我们必须先给主网页注入,这样网页大部分内容的动画和阴影才会被消除
    injectStyle(document.head || document.documentElement);

    // 页面结构刚加载完时,进行一次全局扫描(主要是扫出已经存在的 Shadow DOM)
    window.addEventListener('DOMContentLoaded', () => {
        scanAndInject(document.body);
    });

    // 创建一个“监视器” (MutationObserver)
    // 作用:现在很多网页(比如 Substack)往下滑动时会动态加载新文章或评论
    // 这个监视器就是盯着网页,一旦有新元素加进来,立刻对新元素进行扫描和去动画处理
    const observer = new MutationObserver(mutations => {
        mutations.forEach(m => {
            m.addedNodes.forEach(newNode => {
                // nodeType === 1 代表它是一个正常的 HTML 标签元素(排除了普通的纯文本文字)
                if (newNode.nodeType === 1) {
                    scanAndInject(newNode);
                }
            });
        });
    });

    // 启动监视器,盯着整个网页 (document)
    // childList: true 监视子元素的增加或删除
    // subtree: true 不仅监视儿子,连孙子、曾孙子(所有后代)的变动也要监视
    observer.observe(document, {
        childList: true,
        subtree: true
    });

})();