Via Css 检验

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

目前為 2025-03-09 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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();

})();