Via Css 检验

用于检验Via的Adblock规则中的Css隐藏规则是否有错误的规则,支持自动运行和菜单操作。

当前为 2025-03-09 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Via Css 检验
// @namespace    https://viayoo.com/
// @version      2.6
// @license      MIT
// @description  用于检验Via的Adblock规则中的Css隐藏规则是否有错误的规则,支持自动运行和菜单操作。
// @author       Copilot
// @run-at       document-end
// @match        *://*/*
// @grant        GM_registerMenuCommand
// @require      https://cdn.jsdelivr.net/npm/[email protected]/js/lib/beautify-css.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/csstree.min.js
// ==/UserScript==

(function() {
    'use strict';

    // 获取CSS文件URL
    function getCssFileUrl() {
        const currentHost = window.location.hostname;
        return `https://${currentHost}/via_inject_blocker.css`;
    }

    // 使用 js-beautify 格式化CSS内容
    function formatCssWithJsBeautify(rawCss) {
        try {
            return css_beautify(rawCss, {
                indent_size: 2,
                selector_separator_newline: true
            });
        } catch (error) {
            console.error(`CSS格式化失败:${error.message}`);
            return null;
        }
    }

    // 截断错误行以限制字符数
    function truncateErrorLine(errorLine, maxLength = 150) {
        if (errorLine.length > maxLength) {
            return errorLine.substring(0, maxLength) + "..."; // 添加省略号表示截断
        }
        return errorLine;
    }

    // 读取并格式化CSS内容
    async function fetchAndFormatCss() {
        const url = getCssFileUrl();
        try {
            const response = await fetch(url);
            if (!response.ok) {
                throw new Error(`无法获取CSS文件:${response.statusText}`);
            }
            const rawCss = await response.text();
            return formatCssWithJsBeautify(rawCss);
        } catch (error) {
            console.error(`无法获取或格式化CSS文件:${error.message}`);
            return null;
        }
    }

    // 翻译错误信息为中文
    function translateErrorMessage(englishMessage) {
        const translations = {
            "Identifier is expected": "需要标识符",
            "Unexpected end of input": "输入意外结束",
            "Selector is expected": "需要选择器",
            "Invalid character": "无效字符",
            "Unexpected token": "意外的标记",
            '"]" is expected': '需要 "]"',
            '"{" is expected': '需要 "{"',
            'Unclosed block': '未闭合的块',
            'Unclosed string': '未闭合的字符串',
            'Property is expected': '需要属性名',
            'Value is expected': '需要属性值',
            "Percent sign is expected": "需要百分号 (%)",
            'Attribute selector (=, ~=, ^=, $=, *=, |=) is expected': '需要属性选择器运算符(=、~=、^=、$=、*=、|=)',
            'Semicolon is expected': '需要分号 ";"',
            'Number is expected': '需要数字',
            'Colon is expected': '需要冒号 ":"'
        };
        return translations[englishMessage] || `${englishMessage}`;
    }

    // 验证格式化后的CSS内容
    function validateCss(formattedCss, isAutoRun = false) {
        if (!formattedCss) return;

        let hasError = false;
        const errors = [];
        const lines = formattedCss.split('\n'); // 将格式化的CSS按行分割

        try {
            csstree.parse(formattedCss, {
                onParseError(error) {
                    hasError = true;

                    // 获取并截断错误的具体片段
                    const errorLine = lines[error.line - 1] || "无法提取错误行";
                    const truncatedErrorLine = truncateErrorLine(errorLine);

                    // 翻译错误信息
                    const translatedMessage = translateErrorMessage(error.message);

                    const errorMessage = `
CSS 解析错误:
- 位置:第 ${error.line} 行
- 错误信息:${translatedMessage}
- 错误片段:${truncatedErrorLine}
                    `.trim();
                    errors.push(errorMessage);
                }
            });

            if (hasError) {
                if (isAutoRun) {
                    alert(errors.join('\n\n'));
                }
            } else if (!isAutoRun) {
                alert("CSS验证通过:未发现错误。");
            }
        } catch (error) {
            const translatedMessage = translateErrorMessage(error.message);
            if (isAutoRun) {
                console.error(`自动运行时CSS验证失败:${translatedMessage}`);
            } else {
                alert(`CSS验证失败:${translatedMessage}`);
            }
        }
    }

    // 自动运行逻辑
    async function autoRunCssValidation() {
        const formattedCss = await fetchAndFormatCss();
        if (formattedCss) {
            validateCss(formattedCss, true); // 自动运行时传递 true
        }
    }

    // 注册菜单
    GM_registerMenuCommand("验证CSS文件", async () => {
        const formattedCss = await fetchAndFormatCss();
        if (formattedCss) {
            validateCss(formattedCss, false); // 手动运行时传递 false
        }
    });

    // 触发自动运行
    autoRunCssValidation();

})();