Greasy Fork

来自缓存

Greasy Fork is available in English.

无图模式-Icerayer

阻止网页加载图片和视频,减少流量消耗,支持自定义配置

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         无图模式-Icerayer
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  阻止网页加载图片和视频,减少流量消耗,支持自定义配置
// @author       Icerayer
// @match        *://*/*
// @exclude      data:*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    
    // 配置项 - 可通过油猴脚本菜单或GM_setValue进行配置
    const config = {
        blockImages: true,              // 阻止图片加载
        blockBase64Images: true,        // 阻止Base64编码图片
        blockSVGFill: true,             // 阻止SVG中的图片填充
        blockVideos: true,              // 阻止视频加载
        blockBackgroundImages: true,    // 阻止背景图片
        blockIframeImages: false,       // 阻止iframe中的图片(可能受同源策略限制)
        usePlaceholder: false,          // 使用占位符替代图片
        placeholderType: 'stripes',     // 占位符类型: 'stripes', 'solid'
        placeholderOpacity: '30',       // 占位符透明度
        excludedSelectors: ['.ytp-gradient-bottom', '.ytp-gradient-top'], // 排除的元素选择器
        excludedDomains: [],            // 排除的域名列表
        debug: false,                   // 调试模式
        forceBlockExternalStyles: true, // 强制阻止外部样式表中的背景图片
        useGlobalStyleOverride: true,   // 使用全局样式覆盖作为最后防线
        updateDebounceTime: 50          // 更新防抖时间(毫秒)
    };
    
    // 尝试从GM存储加载配置
    try {
        const savedConfig = JSON.parse(GM_getValue('noImageModeConfig', '{}'));
        Object.assign(config, savedConfig);
    } catch (e) {
        console.log('加载配置失败,使用默认配置:', e.message);
    }
    
    // 检查当前域名是否在排除列表中
    function isExcludedDomain() {
        const hostname = window.location.hostname;
        return config.excludedDomains.some(domain => hostname.includes(domain));
    }
    
    // 如果当前域名在排除列表中,则不执行后续代码
    if (isExcludedDomain()) {
        console.log('当前域名在排除列表中,无图模式已禁用');
        return;
    }

    // 方法1: 拦截并取消图片请求
    const observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            mutation.addedNodes.forEach(function(node) {
                // 处理单个节点
                if (node.nodeType === 1) {
                    processNode(node);
                }
            });
        });
    });

    function processNode(node) {
        // 检查是否为排除的元素
        for (const selector of config.excludedSelectors) {
            if (node.matches(selector) || node.closest(selector)) {
                return;
            }
        }
        
        // 检查当前节点是否为图片
        if (node.tagName === 'IMG') {
            if (config.blockImages) {
                blockImage(node);
            }
        }
        // 检查当前节点是否为视频
        else if (node.tagName === 'VIDEO') {
            if (config.blockVideos) {
                blockVideos(); // 处理所有视频,包括当前节点
            }
        }
        // 检查当前节点是否为SVG
        else if (node.tagName === 'SVG' || node.tagName === 'image' && node.namespaceURI === 'http://www.w3.org/2000/svg') {
            if (config.blockSVGFill) {
                blockSVGFillImages(); // 处理所有SVG中的图片,包括当前节点
            }
        }

        // 检查子节点中的图片
        if (config.blockImages) {
            const images = node.querySelectorAll('img');
            images.forEach(blockImage);
        }
        
        // 处理Base64图片
        if (config.blockBase64Images) {
            const base64Images = node.querySelectorAll('img[src^="data:image/"]');
            base64Images.forEach(blockImage);
        }

        // 处理背景图片 - 包括内联样式和计算样式
        if (config.blockBackgroundImages) {
            // 1. 检查并清除内联样式中的背景图片
            if (node.style && node.style.backgroundImage && node.style.backgroundImage !== 'none') {
                node.style.backgroundImage = 'none';
            }
            
            // 2. 检查并清除计算样式中的背景图片
            const computedStyle = window.getComputedStyle(node);
            if (computedStyle.backgroundImage !== 'none') {
                node.style.backgroundImage = 'none';
            }
            
            // 3. 检查所有可能包含背景图片的样式属性
            const backgroundProperties = ['background', 'backgroundImage', 'backgroundUrl'];
            backgroundProperties.forEach(prop => {
                if (node.style[prop] && node.style[prop] !== 'none' && node.style[prop].includes('url')) {
                    node.style[prop] = 'none';
                }
            });
        }
    }

    function blockImage(img) {
        // 检查是否为排除的元素
        for (const selector of config.excludedSelectors) {
            if (img.matches(selector) || img.closest(selector)) {
                return;
            }
        }
        
        // 保存原始src以备恢复(可选功能)
        if (img.src && !img.dataset.originalSrc) {
            img.dataset.originalSrc = img.src;
            // 标记为被阻止的图片
            img.dataset.imageBlocked = 'true';
        }
        
        // 清空图片源
        img.src = '';
        img.srcset = '';
        
        // 根据配置设置显示样式
        if (config.usePlaceholder) {
            img.style.display = 'block';
            img.style.minHeight = '20px';
            img.style.backgroundColor = 'transparent';
            img.style.backgroundImage = config.placeholderType === 'stripes' 
                ? `linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee), linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee)` 
                : `linear-gradient(to right, #eee 0%, #eee 100%)`;
            img.style.backgroundSize = config.placeholderType === 'stripes' ? '20px 20px' : '100% 100%';
            img.style.backgroundPosition = config.placeholderType === 'stripes' ? '0 0, 10px 10px' : '0 0';
            img.style.opacity = config.placeholderOpacity / 100;
        } else {
            img.style.display = 'none';
        }
    }
    
    // 处理Base64编码图片
    function blockBase64Images() {
        if (!config.blockBase64Images) return;
        
        // 1. 处理图片元素中的Base64图片
        const base64Images = document.querySelectorAll('img[src^="data:image/"]');
        base64Images.forEach(img => {
            if (!img.dataset.imageBlocked) {
                blockImage(img);
            }
        });
        
        // 2. 处理CSS内联样式中的Base64背景图片
        const elementsWithBase64Background = document.querySelectorAll('[style*="url(data:image"]');
        elementsWithBase64Background.forEach(element => {
            // 检查是否为排除的元素
            for (const selector of config.excludedSelectors) {
                if (element.matches(selector) || element.closest(selector)) {
                    return;
                }
            }
            
            // 移除背景图片
            if (element.style.backgroundImage && element.style.backgroundImage.includes('data:image')) {
                element.style.backgroundImage = 'none';
            }
            // 处理background简写属性
            if (element.style.background && element.style.background.includes('data:image')) {
                element.style.background = '';
            }
        });
    }
    
    // 处理SVG中的图片填充
    function blockSVGFillImages() {
        if (!config.blockSVGFill) return;
        
        // 处理SVG中的image元素
        const svgImages = document.querySelectorAll('svg image[href^="data:image/"], svg image[xlink\:href^="data:image/"]');
        svgImages.forEach(img => {
            if (!img.dataset.imageBlocked) {
                // 保存原始地址
                if (img.href && !img.dataset.originalHref) {
                    img.dataset.originalHref = img.href;
                }
                if (img.getAttributeNS('http://www.w3.org/1999/xlink', 'href') && !img.dataset.originalXlinkHref) {
                    img.dataset.originalXlinkHref = img.getAttributeNS('http://www.w3.org/1999/xlink', 'href');
                }
                
                // 清空图片地址
                if (img.href.baseVal !== undefined) {
                    img.href.baseVal = '';
                } else {
                    img.removeAttribute('href');
                }
                img.removeAttributeNS('http://www.w3.org/1999/xlink', 'href');
                img.dataset.imageBlocked = 'true';
            }
        });
        
        // 处理SVG中的pattern和fill属性中的URL
        const svgElements = document.querySelectorAll('svg [fill^="url("], svg [stroke^="url("]');
        svgElements.forEach(element => {
            if (!element.dataset.fillBlocked) {
                if (element.getAttribute('fill') && element.getAttribute('fill').includes('url(')) {
                    element.dataset.originalFill = element.getAttribute('fill');
                    element.removeAttribute('fill');
                }
                if (element.getAttribute('stroke') && element.getAttribute('stroke').includes('url(')) {
                    element.dataset.originalStroke = element.getAttribute('stroke');
                    element.removeAttribute('stroke');
                }
                element.dataset.fillBlocked = 'true';
            }
        });
    }
    
    // 处理视频内容
    function blockVideos() {
        if (!config.blockVideos) return;
        
        const videos = document.querySelectorAll('video');
        videos.forEach(video => {
            // 检查是否为排除的元素
            for (const selector of config.excludedSelectors) {
                if (video.matches(selector) || video.closest(selector)) {
                    return;
                }
            }
            
            // 保存原始属性
            if (video.src && !video.dataset.originalSrc) {
                video.dataset.originalSrc = video.src;
            }
            if (video.poster && !video.dataset.originalPoster) {
                video.dataset.originalPoster = video.poster;
            }
            
            // 暂停视频并清空源
            video.pause();
            video.src = '';
            video.poster = '';
            
            // 移除所有source元素
            const sources = video.querySelectorAll('source');
            sources.forEach(source => {
                if (source.src && !source.dataset.originalSrc) {
                    source.dataset.originalSrc = source.src;
                }
                source.src = '';
            });
            
            // 设置视频样式
            if (config.usePlaceholder) {
                video.style.backgroundColor = 'transparent';
                video.style.backgroundImage = config.placeholderType === 'stripes' 
                    ? `linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee), linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee)` 
                    : `linear-gradient(to right, #eee 0%, #eee 100%)`;
                video.style.backgroundSize = config.placeholderType === 'stripes' ? '20px 20px' : '100% 100%';
                video.style.backgroundPosition = config.placeholderType === 'stripes' ? '0 0, 10px 10px' : '0 0';
                video.style.opacity = config.placeholderOpacity / 100;
            }
            
            video.dataset.videoBlocked = 'true';
        });
    }

    // 方法2: 重写Image构造函数
    if (config.blockImages) {
        const originalImage = window.Image;
        window.Image = function(width, height) {
            const img = new originalImage(width, height);
            img.src = '';
            return img;
        };
        window.Image.prototype = originalImage.prototype;
    }

    // 方法3: 拦截document.createElement
    const originalCreateElement = document.createElement;
    document.createElement = function(tagName) {
        const element = originalCreateElement.call(document, tagName);
        
        if (config.blockImages && tagName.toLowerCase() === 'img') {
            // 重写src属性的setter
            Object.defineProperty(element, 'src', {
                set: function() {
                    // 忽略设置src的操作
                },
                get: function() {
                    return '';
                }
            });
            // 同样处理srcset
            Object.defineProperty(element, 'srcset', {
                set: function() {
                    // 忽略设置srcset的操作
                },
                get: function() {
                    return '';
                }
            });
        }
        
        // 为所有元素重写setAttribute方法以拦截背景图片设置
        const originalSetAttribute = element.setAttribute;
        element.setAttribute = function(name, value) {
            // 拦截style属性中的背景图片
            if (config.blockBackgroundImages && name.toLowerCase() === 'style') {
                if (typeof value === 'string' && value.includes('background-image') && value.includes('url')) {
                    // 移除background-image相关内容
                    value = value.replace(/background-image\s*:\s*url\([^)]*\);?/gi, '');
                    value = value.replace(/background\s*:\s*[^;]*url\([^)]*\)[^;]*;?/gi, '');
                }
            }
            // 拦截background和background-image属性
            else if (config.blockBackgroundImages && (name.toLowerCase() === 'background' || name.toLowerCase() === 'background-image')) {
                if (typeof value === 'string' && value.includes('url')) {
                    // 忽略设置包含url的背景属性
                    return;
                }
            }
            // 拦截图片src属性
            else if (config.blockImages && (tagName.toLowerCase() === 'img' && (name.toLowerCase() === 'src' || name.toLowerCase() === 'srcset'))) {
                if (value && (config.blockBase64Images || !value.startsWith('data:image/'))) {
                    // 保存原始src
                    if (name.toLowerCase() === 'src' && !this.dataset.originalSrc) {
                        this.dataset.originalSrc = value;
                    }
                    // 不设置实际的src
                    return;
                }
            }
            return originalSetAttribute.call(this, name, value);
        };
        
        return element;
    };

    // 方法4: 尝试使用fetch拦截(如果浏览器支持)
    if (window.fetch) {
        const originalFetch = window.fetch;
        window.fetch = function(url, options) {
            // 规范化URL
            const urlStr = typeof url === 'string' ? url : String(url);
            
            try {
                // 使用URL对象获取路径部分,更精确地匹配文件扩展名
                const pathname = new URL(urlStr, location.href).pathname;
                
                // 检查是否为图片请求
                if (config.blockImages && /\.(png|jpe?g|gif|webp|svg|ico)$/i.test(pathname)) {
                    // 返回一个空响应
                    return Promise.resolve(new Response('', { status: 200 }));
                }
                // 检查是否为视频请求
                if (config.blockVideos && /\.(mp4|webm|ogg|avi|mov|mkv)$/i.test(pathname)) {
                    // 返回一个空响应
                    return Promise.resolve(new Response('', { status: 200 }));
                }
            } catch (e) {
                // URL解析失败时回退到简单检查
                if (config.blockImages && typeof url === 'string' && /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(url)) {
                    return Promise.resolve(new Response('', { status: 200 }));
                }
                if (config.blockVideos && typeof url === 'string' && /\.(mp4|webm|ogg|avi|mov|mkv)$/i.test(url)) {
                    return Promise.resolve(new Response('', { status: 200 }));
                }
            }
            return originalFetch(url, options);
        };
    }

    // 方法5: 拦截XMLHttpRequest
    const originalXHROpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url) {
        try {
            // 使用URL对象获取路径部分,更精确地匹配文件扩展名
            const pathname = new URL(String(url), location.href).pathname;
            
            // 检查是否为图片请求
            if (config.blockImages && /\.(png|jpe?g|gif|webp|svg|ico)$/i.test(pathname)) {
                // 不执行实际请求
                this._blocked = true;
            }
            // 检查是否为视频请求
            if (config.blockVideos && /\.(mp4|webm|ogg|avi|mov|mkv)$/i.test(pathname)) {
                // 不执行实际请求
                this._blocked = true;
            }
        } catch (e) {
            // URL解析失败时回退到简单检查
            if (config.blockImages && typeof url === 'string' && /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(url)) {
                this._blocked = true;
            }
            if (config.blockVideos && typeof url === 'string' && /\.(mp4|webm|ogg|avi|mov|mkv)$/i.test(url)) {
                this._blocked = true;
            }
        }
        return originalXHROpen.apply(this, arguments);
    };

    const originalXHRSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function() {
        if (this._blocked) {
            // 模拟完成但不加载内容
            setTimeout(() => {
                if (this.readyState < 4) {
                    this.readyState = 4;
                    this.status = 200;
                    if (this.onreadystatechange) this.onreadystatechange();
                    if (this.onload) this.onload();
                }
            }, 0);
            return;
        }
        return originalXHRSend.apply(this, arguments);
    };

    // 开始观察DOM变化
    observer.observe(document, {
        childList: true,
        subtree: true,
        attributes: true,  // 监听属性变化
        attributeFilter: ['style', 'background', 'background-image']  // 重点监听这些属性
    });
    
    // 增强MutationObserver回调,处理属性变化
    const originalObserverCallback = observer.observe.bind(observer);
    observer.observe = function(target, options) {
        // 确保options包含属性监听
        if (!options.attributes) {
            options.attributes = true;
        }
        if (!options.attributeFilter) {
            options.attributeFilter = ['style', 'background', 'background-image'];
        }
        return originalObserverCallback(target, options);
    };
    
    // 方法6: 拦截元素的style对象的backgroundImage属性设置
    if (config.blockBackgroundImages) {
        const originalStylePrototype = Object.getPrototypeOf(HTMLElement.prototype.style);
        Object.defineProperty(CSSStyleDeclaration.prototype, 'backgroundImage', {
            set: function(value) {
                // 忽略包含url的背景图片设置
                if (typeof value === 'string' && value.includes('url')) {
                    return;
                }
                // 对于不包含url的值,正常设置
                originalStylePrototype.setProperty.call(this, 'background-image', value);
            },
            get: function() {
                return originalStylePrototype.getPropertyValue.call(this, 'background-image');
            }
        });
        
        // 同样拦截background属性
        Object.defineProperty(CSSStyleDeclaration.prototype, 'background', {
            set: function(value) {
                // 忽略包含url的背景设置
                if (typeof value === 'string' && value.includes('url')) {
                    return;
                }
                originalStylePrototype.setProperty.call(this, 'background', value);
            },
            get: function() {
                return originalStylePrototype.getPropertyValue.call(this, 'background');
            }
        });
    }
    
    // 拦截setProperty方法,防止通过此方法设置背景图片
    const originalSetProperty = CSSStyleDeclaration.prototype.setProperty;
    CSSStyleDeclaration.prototype.setProperty = function(property, value) {
        // 拦截背景相关属性
        if (config.blockBackgroundImages) {
            const lowerProp = property.toLowerCase();
            if ((lowerProp === 'background-image' || lowerProp === 'background') && 
                typeof value === 'string' && value.includes('url')) {
                return;
            }
        }
        return originalSetProperty.apply(this, arguments);
    };
    
    // 方法7: 拦截CSS样式表操作,阻止通过CSS规则添加背景图片
    if (config.blockBackgroundImages) {
        // 拦截insertRule方法
        const originalInsertRule = CSSStyleSheet.prototype.insertRule;
        CSSStyleSheet.prototype.insertRule = function(rule, index) {
            // 检查规则中是否包含背景图片url
            if (rule && typeof rule === 'string' && 
                (rule.includes('background-image') || rule.includes('background')) && 
                rule.includes('url(')) {
                // 修改规则,移除背景图片相关内容
                rule = rule.replace(/background-image\s*:\s*url\([^)]*\);?/gi, '');
                rule = rule.replace(/background\s*:\s*[^;]*url\([^)]*\)[^;]*;?/gi, '');
            }
            return originalInsertRule.call(this, rule, index);
        };
        
        // 拦截addRule方法(IE兼容)
        if (CSSStyleSheet.prototype.addRule) {
            const originalAddRule = CSSStyleSheet.prototype.addRule;
            CSSStyleSheet.prototype.addRule = function(selector, style, index) {
                // 检查样式中是否包含背景图片url
                if (style && typeof style === 'string' && 
                    (style.includes('background-image') || style.includes('background')) && 
                    style.includes('url(')) {
                    // 修改样式,移除背景图片相关内容
                    style = style.replace(/background-image\s*:\s*url\([^)]*\);?/gi, '');
                    style = style.replace(/background\s*:\s*[^;]*url\([^)]*\)[^;]*;?/gi, '');
                }
                return originalAddRule.call(this, selector, style, index);
            };
        }
    }
    
    // 方法8: 拦截动态样式标签的创建和插入
    // 拦截appendChild方法
    const originalHeadAppendChild = document.head.appendChild;
    document.head.appendChild = function(child) {
        if (config.blockBackgroundImages) {
            processStyleElement(child);
        }
        return originalHeadAppendChild.call(this, child);
    };
    
    // 拦截insertBefore方法
    const originalHeadInsertBefore = document.head.insertBefore;
    document.head.insertBefore = function(newNode, referenceNode) {
        if (config.blockBackgroundImages) {
            processStyleElement(newNode);
        }
        return originalHeadInsertBefore.call(this, newNode, referenceNode);
    };
    
    // 增强:拦截document.createTextNode,防止通过文本节点注入样式
    const originalCreateTextNode = document.createTextNode;
    document.createTextNode = function(data) {
        const textNode = originalCreateTextNode.call(this, data);
        // 标记文本节点,以便后续检查是否为样式内容
        if (typeof data === 'string' && (data.includes('background-image') || data.includes('background')) && data.includes('url(')) {
            textNode._potentialStyleContent = true;
        }
        return textNode;
    };
    
    // 处理样式元素的函数
    function processStyleElement(element) {
        if (!config.blockBackgroundImages) return;
        
        const tagName = element.tagName ? element.tagName.toLowerCase() : '';
        
        // 检查是否为style标签
        if (tagName === 'style') {
            // 立即处理现有内容
            if (element.textContent) {
                element.textContent = removeBackgroundImages(element.textContent);
            }
            
            // 监听内容变化
            const styleObserver = new MutationObserver(function(mutations) {
                mutations.forEach(function(mutation) {
                    if (mutation.type === 'characterData' || mutation.type === 'childList') {
                        element.textContent = removeBackgroundImages(element.textContent);
                    }
                });
            });
            
            styleObserver.observe(element, { 
                characterData: true, 
                childList: true,
                subtree: true 
            });
        }
        // 检查是否为link标签(外部样式表)
        else if (tagName === 'link' && 
                 element.rel && element.rel.toLowerCase() === 'stylesheet') {
            // 记录外部样式表URL以便跟踪
            if (element.href) {
                if (!window._blockedStyleSheets) window._blockedStyleSheets = new Set();
                window._blockedStyleSheets.add(element.href);
            }
            
            // 立即尝试处理(可能尚未加载完成)
            setTimeout(() => {
                // 查找对应的样式表
                const styleSheet = Array.from(document.styleSheets).find(sheet => 
                    sheet.href === element.href
                );
                
                if (styleSheet) {
                    try {
                        const rules = Array.from(styleSheet.cssRules || []);
                        rules.forEach(removeBackgroundFromRule);
                    } catch {}
                } else {
                    // 延迟再尝试一次,确保样式表已加载
                    setTimeout(() => {
                        for (const sheet of document.styleSheets) {
                            try {
                                const rules = Array.from(sheet.cssRules || []);
                                rules.forEach(removeBackgroundFromRule);
                            } catch {}
                        }
                    }, 300);
                }
            }, 100);
        }
        // 增强:处理可能包含样式的iframe
        else if (tagName === 'iframe' && config.blockIframeImages) {
            try {
                // 尝试访问iframe内容(可能受到同源策略限制)
                const iframeDoc = element.contentDocument || element.contentWindow.document;
                if (iframeDoc) {
                    // 递归应用无图模式到iframe
                    setTimeout(() => {
                        if (config.blockImages) {
                            Array.from(iframeDoc.querySelectorAll('img')).forEach(img => {
                                if (!img.dataset.imageBlocked) {
                                    blockImage(img);
                                }
                            });
                        }
                        
                        if (config.blockBackgroundImages) {
                            processExistingStyleSheets(iframeDoc);
                        }
                    }, 100);
                }
            } catch (e) {
                if (config.debug) {
                    console.log('无法访问iframe内容(同源策略限制):', e.message);
                }
            }
        }
    }
    
    // 移除文本中的背景图片声明
function removeBackgroundImages(cssText) {
    if (!config.blockBackgroundImages || typeof cssText !== 'string') return cssText;
    
    // 增强的正则表达式,处理更复杂的背景图片格式
    // 1. 单独的background-image属性
    cssText = cssText.replace(/background-image\s*:\s*url\(\s*['"]?([^'")]+)['"]?\s*\)\s*;?/gi, '');
    
    // 2. 处理CSS变量中的背景图片
    cssText = cssText.replace(/(--[^:]+)\s*:\s*url\(\s*['"]?([^'")]+)['"]?\s*\)\s*;?/gi, function(match, varName) {
        return varName + ': none;'; // 保留变量但将其值设为none
    });
    
    // 3. 处理background简写属性中的url部分
    // 只移除url部分,保留其他背景属性
    cssText = cssText.replace(/(background\s*:\s*[^;]*?)url\(\s*['"]?([^'")]+)['"]?\s*\)([^;]*;?)/gi, function(match, prefix, url, suffix) {
        // 如果前后没有其他内容,则返回空
        if (!prefix.trim() && !suffix.trim()) return '';
        // 否则只返回前后部分(移除url部分)
        return prefix + suffix;
    });
    
    // 4. 处理其他可能的背景相关属性变体
    cssText = cssText.replace(/(background(?:-[^:]+)?\s*:\s*[^;]*?)url\(\s*['"]?([^'")]+)['"]?\s*\)([^;]*;?)/gi, function(match, prefix, url, suffix) {
        // 如果前后没有其他内容,则返回空
        if (!prefix.trim() && !suffix.trim()) return '';
        // 否则只返回前后部分(移除url部分)
        return prefix + suffix;
    });
    
    return cssText;
}
    

    
    // 处理单个CSS规则,移除背景图片
    function removeBackgroundFromRule(rule) {
        // 处理普通CSS规则
        if (rule.type === 1) { // CSSStyleRule
            // 检查并移除backgroundImage属性
            if (rule.style && rule.style.backgroundImage && rule.style.backgroundImage !== 'none') {
                rule.style.backgroundImage = 'none';
            }
            
            // 更精确地处理background简写属性
            if (rule.style && rule.style.background && rule.style.background.includes('url(')) {
                // 尝试保留其他背景属性,只移除图片URL
                let backgroundValue = rule.style.background;
                // 保存非URL部分的背景属性
                let preservedBackground = '';
                
                // 处理颜色值
                const colorMatch = backgroundValue.match(/(rgba?\([^)]+\)|#[0-9a-fA-F]{3,6}|[a-zA-Z]+)/);
                if (colorMatch) preservedBackground += colorMatch[0] + ' ';
                
                // 处理重复性
                const repeatMatch = backgroundValue.match(/(repeat|repeat-x|repeat-y|no-repeat)/);
                if (repeatMatch) preservedBackground += repeatMatch[0] + ' ';
                
                // 处理定位
                const positionMatch = backgroundValue.match(/(left|center|right|top|bottom|\d+(?:px|%|em|rem|vh|vw)?)\s+(left|center|right|top|bottom|\d+(?:px|%|em|rem|vh|vw)?)/);
                if (positionMatch) preservedBackground += positionMatch[0] + ' ';
                
                // 设置处理后的背景值
                rule.style.background = preservedBackground.trim() || 'none';
            }
            
            // 检查并移除可能包含URL的CSS变量
            if (rule.style) {
                for (let j = 0; j < rule.style.length; j++) {
                    const propName = rule.style[j];
                    if (propName.startsWith('--') && rule.style.getPropertyValue(propName).includes('url(')) {
                        rule.style.setProperty(propName, 'none');
                    }
                }
            }
        }
        // 处理@media规则等嵌套规则
        else if (rule.type === 4) { // CSSMediaRule
            try {
                const rules = Array.from(rule.cssRules || []);
                rules.forEach(removeBackgroundFromRule);
            } catch {}
        }
        // 处理其他可能包含规则的规则类型
        else if (rule.cssRules || rule.rules) {
            try {
                const rules = Array.from(rule.cssRules || rule.rules || []);
                rules.forEach(removeBackgroundFromRule);
            } catch {}
        }
    }
    
    // 方法9: 处理页面上已有的所有样式表 - 优化版本
    function processExistingStyleSheets(doc = document) {
        if (!config.blockBackgroundImages) return;
        
        // 批量处理所有样式表,减少try/catch次数,提升性能
        for (const sheet of doc.styleSheets) {
            try {
                const rules = Array.from(sheet.cssRules || []);
                rules.forEach(removeBackgroundFromRule);
            } catch {}
        }
        
        // 同时处理所有内联style标签
        try {
            doc.querySelectorAll('style').forEach(style => {
                if (style.textContent) {
                    style.textContent = removeBackgroundImages(style.textContent);
                }
            });
        } catch (e) {
            if (config.debug) {
                console.log('处理内联style标签时出错:', e.message);
            }
        }
        
        // 增强:添加全局样式覆盖,作为最后防线
        if (config.useGlobalStyleOverride) {
            addGlobalStyleOverride(doc);
        }
    }
    
    // 添加全局样式覆盖作为最后防线
    function addGlobalStyleOverride(doc = document) {
        // 检查是否已存在覆盖样式
        if (doc.getElementById('no-image-mode-override')) {
            return;
        }
        
        const styleElement = doc.createElement('style');
        styleElement.id = 'no-image-mode-override';
        styleElement.textContent = `
            /* 全局背景图片覆盖 */
            * {
                background-image: none !important;
            }
            
            /* 为已设置背景图片的元素保留其他背景属性 */
            [style*="background-image"] {
                background-image: none !important;
            }
            
            /* 处理CSS变量 */
            :root {
                --background-image: none !important;
                --bg-image: none !important;
            }
        `;
        
        try {
            doc.head.appendChild(styleElement);
        } catch (e) {
            if (config.debug) {
                console.log('无法添加全局样式覆盖:', e.message);
            }
        }
    }

    // 处理已经存在的图片(如果脚本在页面加载过程中注入)
    window.addEventListener('DOMContentLoaded', function() {
        // 1. 处理所有图片标签
        if (config.blockImages) {
            document.querySelectorAll('img').forEach(blockImage);
        }
        
        // 2. 处理所有元素的内联背景图片
        if (config.blockBackgroundImages) {
            document.querySelectorAll('*').forEach(function(element) {
                // 检查是否为排除的元素
                for (const selector of config.excludedSelectors) {
                    if (element.matches(selector) || element.closest(selector)) {
                        return;
                    }
                }
                
                // 清除内联样式中的背景图片
                if (element.style && element.style.backgroundImage && element.style.backgroundImage !== 'none') {
                    element.style.backgroundImage = 'none';
                }
                
                // 清除计算样式中的背景图片
                const computedStyle = window.getComputedStyle(element);
                if (computedStyle.backgroundImage !== 'none') {
                    element.style.backgroundImage = 'none';
                }
                
                // 检查所有背景相关属性
                const backgroundProperties = ['background', 'backgroundImage'];
                backgroundProperties.forEach(prop => {
                    if (element.style[prop] && element.style[prop].includes('url')) {
                        element.style[prop] = 'none';
                    }
                });
            });
        }
        
        // 3. 处理页面上所有已加载的样式表(延迟处理以提高性能)
        setTimeout(processExistingStyleSheets, 1500);
        
        // 4. 处理Base64编码图片
        blockBase64Images();
        
        // 5. 处理SVG中的图片填充
        blockSVGFillImages();
        
        // 6. 处理视频内容
        blockVideos();
    });
    
    // 当所有资源加载完成后再次检查(确保脚本动态添加的图片也被处理)
    window.addEventListener('load', function() {
        if (config.debug) {
            console.log('所有资源加载完成,开始执行最终检查...');
        }
        
        // 1. 再次处理所有图片标签(包括动态加载的图片)
        if (config.blockImages) {
            document.querySelectorAll('img:not([data-image-blocked])').forEach(blockImage);
        }
        
        // 2. 再次处理所有元素的内联背景图片
        if (config.blockBackgroundImages) {
            // 使用更高效的选择器来定位可能有背景图片的元素
            document.querySelectorAll('[style*="background-image"], [style*="background"], [style*="url("]').forEach(function(element) {
                // 检查是否为排除的元素
                for (const selector of config.excludedSelectors) {
                    if (element.matches(selector) || element.closest(selector)) {
                        return;
                    }
                }
                
                // 清除内联样式中的背景图片
                if (element.style && element.style.backgroundImage && element.style.backgroundImage !== 'none') {
                    element.style.backgroundImage = 'none';
                }
                
                // 处理background简写属性
                if (element.style.background && element.style.background.includes('url(')) {
                    element.style.background = element.style.background.replace(/url\([^)]+\)/gi, 'none');
                    // 如果替换后background属性无效,则清空
                    if (!element.style.background.trim()) {
                        element.style.background = '';
                    }
                }
            });
            
            // 再次处理所有样式表
            processExistingStyleSheets();
        }
        
        // 3. 再次处理Base64编码图片(包括脚本动态添加的)
        blockBase64Images();
        
        // 4. 再次处理SVG中的图片填充
        blockSVGFillImages();
        
        // 5. 再次处理视频内容
        blockVideos();
        
        // 6. 最后添加全局样式覆盖作为保险
        if (config.useGlobalStyleOverride) {
            addGlobalStyleOverride();
        }
        
        if (config.debug) {
            console.log('最终检查完成,所有图片和视频应已被阻止。');
        }
    });
    
    // 方法10: 监听DOM变化,处理新添加的内容
    const styleSheetObserver = new MutationObserver(function(mutations) {
        // 使用更精确的标志来避免不必要的全局处理
        let needsStyleUpdate = false;
        let needsImageUpdate = false;
        let needsVideoUpdate = false;
        let needsSVGUpdate = false;
        let newElementProcessed = false;
        
        // 直接处理新增节点,而不是等待定时器
        mutations.forEach(function(mutation) {
            // 处理新增节点
            mutation.addedNodes.forEach(function(node) {
                if (!node.tagName) return;
                
                const tagName = node.tagName.toLowerCase();
                const isElement = node.nodeType === 1;
                
                // 处理特定标签类型
                if (tagName === 'img' && config.blockImages && !node.dataset.imageBlocked) {
                    blockImage(node);
                    newElementProcessed = true;
                }
                else if (tagName === 'video' && config.blockVideos) {
                    blockVideo(node);
                    newElementProcessed = true;
                }
                else if (tagName === 'svg' && config.blockSVGFill) {
                    blockSVGFillInElement(node);
                    newElementProcessed = true;
                }
                else if (config.blockBackgroundImages && 
                         (tagName === 'style' || (tagName === 'link' && node.rel && node.rel.toLowerCase() === 'stylesheet'))) {
                    processStyleElement(node);
                    needsStyleUpdate = true;
                }
                // 处理可能包含内联样式的元素
                else if (isElement && config.blockBackgroundImages && 
                         node.hasAttribute('style') && 
                         (node.style.backgroundImage !== 'none' || node.style.background.includes('url('))) {
                    node.style.backgroundImage = 'none';
                    if (node.style.background.includes('url(')) {
                        node.style.background = '';
                    }
                    newElementProcessed = true;
                }
                
                // 处理包含子元素的节点
                if (isElement && node.hasChildNodes()) {
                    // 性能优化:根据需要选择性处理子节点
                    if (config.blockImages && node.querySelector('img:not([data-image-blocked])')) {
                        needsImageUpdate = true;
                    }
                    if (config.blockVideos && node.querySelector('video')) {
                        needsVideoUpdate = true;
                    }
                    if (config.blockSVGFill && node.querySelector('svg')) {
                        needsSVGUpdate = true;
                    }
                    if (config.blockBackgroundImages && 
                        (node.querySelector('style') || 
                         node.querySelector('[style*="background-image"], [style*="background"]'))) {
                        needsStyleUpdate = true;
                    }
                }
            });
            
            // 处理属性变化
            if (mutation.type === 'attributes' && mutation.target.nodeType === 1) {
                const target = mutation.target;
                const attrName = mutation.attributeName.toLowerCase();
                
                // 检查是否为背景相关属性变化
                if (config.blockBackgroundImages && 
                    (attrName === 'style' || attrName === 'background' || attrName === 'background-image')) {
                    // 直接处理该元素,而不是触发全局更新
                    if (target.style && (target.style.backgroundImage !== 'none' || target.style.background.includes('url('))) {
                        target.style.backgroundImage = 'none';
                        if (target.style.background.includes('url(')) {
                            target.style.background = '';
                        }
                    }
                }
                // 检查是否为图片src属性变化
                else if (config.blockImages && target.tagName && 
                         target.tagName.toLowerCase() === 'img' && 
                         (attrName === 'src' || attrName === 'srcset')) {
                    // 直接重新阻止该图片
                    if (!target.dataset.imageBlocked) {
                        blockImage(target);
                    }
                }
                // 检查SVG相关属性变化
                else if (config.blockSVGFill && target.tagName && 
                         (target.tagName.toLowerCase() === 'svg' || 
                          target.tagName.toLowerCase() === 'path' || 
                          target.tagName.toLowerCase() === 'image')) {
                    needsSVGUpdate = true;
                }
            }
        });
        
        // 仅在必要时执行批量更新,避免过度处理
        if (needsStyleUpdate || needsImageUpdate || needsVideoUpdate || needsSVGUpdate) {
            // 使用防抖,避免频繁更新
            if (window._styleUpdateTimer) {
                clearTimeout(window._styleUpdateTimer);
            }
            
            window._styleUpdateTimer = setTimeout(() => {
                // 根据需要处理不同类型的内容
                if (needsStyleUpdate && config.blockBackgroundImages) {
                    processExistingStyleSheets();
                }
                if (needsImageUpdate && config.blockImages) {
                    document.querySelectorAll('img:not([data-image-blocked])').forEach(blockImage);
                }
                if (needsVideoUpdate && config.blockVideos) {
                    document.querySelectorAll('video').forEach(blockVideo);
                }
                if (needsSVGUpdate && config.blockSVGFill) {
                    blockSVGFillImages();
                }
                if (config.blockBase64Images) {
                    blockBase64Images();
                }
            }, config.updateDebounceTime || 50);
        }
    });
    
    // 单独处理视频的函数
    function blockVideo(video) {
        if (!config.blockVideos) return;
        
        // 保存原始源
        if (!video.dataset.originalSrc) {
            video.dataset.originalSrc = video.src;
        }
        
        // 清空视频源
        video.pause();
        video.src = '';
        video.srcObject = null;
        
        // 隐藏视频
        video.style.visibility = 'hidden';
        video.style.height = '0';
        video.style.width = '0';
        video.style.overflow = 'hidden';
    }
    
    // 直接处理单个SVG元素的函数
    function blockSVGFillInElement(svg) {
        if (!config.blockSVGFill) return;
        
        // 处理SVG中的image元素
        svg.querySelectorAll('image').forEach(img => {
            if (img.href) {
                img.removeAttribute('href');
            }
            if (img.getAttribute('xlink:href')) {
                img.removeAttribute('xlink:href');
            }
        });
        
        // 处理fill属性中的URL
        svg.querySelectorAll('[fill*="url("]').forEach(elem => {
            elem.setAttribute('fill', 'none');
        });
        
        // 处理pattern中的image
        svg.querySelectorAll('pattern image').forEach(img => {
            if (img.href) {
                img.removeAttribute('href');
            }
            if (img.getAttribute('xlink:href')) {
                img.removeAttribute('xlink:href');
            }
        });
    }
    
    // 开始观察head区域的变化
    if (document.head) {
        styleSheetObserver.observe(document.head, {
            childList: true,
            subtree: true
        });
    }

    // 暴露全局配置接口(可选,用于调试或临时修改配置)
    window.noImageModeConfig = config;
    
    // 保存配置的函数(可以在控制台手动调用)
    window.saveNoImageModeConfig = function(newConfig) {
        try {
            Object.assign(config, newConfig);
            GM_setValue('noImageModeConfig', JSON.stringify(config));
            console.log('无图模式配置已保存:', config);
        } catch (e) {
            console.error('保存配置失败:', e.message);
        }
    };
    
    // 恢复被阻止图片的函数(用于临时查看图片)
    window.restoreImages = function() {
        const images = document.querySelectorAll('img[data-image-blocked="true"]');
        images.forEach(img => {
            if (img.dataset.originalSrc) {
                img.src = img.dataset.originalSrc;
                img.style.display = '';
                img.style.backgroundImage = 'none';
                img.style.backgroundColor = 'transparent';
                img.style.opacity = '1';
            }
        });
        console.log(`已恢复${images.length}张图片`);
    };
    
    // 阻止图片的函数(用于重新阻止图片)
    window.blockImages = function() {
        document.querySelectorAll('img').forEach(blockImage);
        console.log('已重新阻止所有图片');
    };
    
    console.log('无图模式已启用,图片和视频加载已被阻止。当前配置:', config);
})();