您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
用于检验Via的Adblock规则中的Css隐藏规则是否有错误,支持自动运行、菜单操作、WebView版本检测及规则数量统计
当前为
- // ==UserScript==
- // @name Via Css 检验
- // @namespace https://viayoo.com/
- // @version 2.9
- // @license MIT
- // @description 用于检验Via的Adblock规则中的Css隐藏规则是否有错误,支持自动运行、菜单操作、WebView版本检测及规则数量统计
- // @author Copilot & Grok
- // @run-at document-end
- // @match *://*/*
- // @grant GM_registerMenuCommand
- // @grant GM_setValue
- // @grant GM_getValue
- // @require https://cdn.jsdelivr.net/npm/js-beautify@1.14.0/js/lib/beautify-css.js
- // @require https://cdn.jsdelivr.net/npm/css-tree@2.3.1/dist/csstree.min.js
- // ==/UserScript==
- (function() {
- 'use strict';
- function getCssFileUrl() {
- const currentHost = window.location.hostname;
- return `https://${currentHost}/via_inject_blocker.css`;
- }
- function formatCssWithJsBeautify(rawCss) {
- try {
- const formatted = css_beautify(rawCss, {
- indent_size: 2,
- selector_separator_newline: true
- });
- console.log('格式化后的CSS:', formatted);
- return formatted;
- } catch (error) {
- console.error(`CSS格式化失败:${error.message}`);
- return null;
- }
- }
- function getWebViewVersion() {
- const ua = navigator.userAgent;
- console.log('User-Agent:', ua);
- const patterns = [
- /Chrome\/([\d.]+)/i,
- /wv\).*?Version\/([\d.]+)/i,
- /Android.*?Version\/([\d.]+)/i
- ];
- for (let pattern of patterns) {
- const match = ua.match(pattern);
- if (match) {
- console.log('匹配到的版本:', match[1]);
- return match[1];
- }
- }
- return null;
- }
- function checkPseudoClassSupport(cssContent) {
- const pseudoClasses = [{
- name: ':hover',
- minVersion: 37
- },
- {
- name: ':focus',
- minVersion: 37
- },
- {
- name: ':active',
- minVersion: 37
- },
- {
- name: ':nth-child',
- minVersion: 37
- },
- {
- name: ':not',
- minVersion: 37
- },
- {
- name: ':where',
- minVersion: 88
- },
- {
- name: ':is',
- minVersion: 88
- },
- {
- name: ':has',
- minVersion: 105
- }
- ];
- const webviewVersion = getWebViewVersion();
- let unsupportedPseudo = [];
- if (!webviewVersion) {
- return "无法检测到WebView或浏览器内核版本";
- }
- const versionNum = parseFloat(webviewVersion);
- console.log('检测到的WebView版本:', versionNum);
- pseudoClasses.forEach(pseudo => {
- if (cssContent.includes(pseudo.name)) {
- if (versionNum < pseudo.minVersion) {
- unsupportedPseudo.push(`${pseudo.name} (需要版本 ${pseudo.minVersion}+)`);
- }
- }
- });
- return unsupportedPseudo.length > 0 ?
- `当前版本(${webviewVersion})不支持以下伪类:${unsupportedPseudo.join(', ')}` :
- `当前版本(${webviewVersion})支持所有使用的伪类`;
- }
- function countCssRules(formattedCss) {
- if (!formattedCss) return 0;
- try {
- const ast = csstree.parse(formattedCss);
- let count = 0;
- csstree.walk(ast, (node) => {
- if (node.type === 'Rule' && node.prelude && node.prelude.type === 'SelectorList') {
- const selectors = node.prelude.children.size;
- count += selectors;
- }
- });
- console.log('计算得到的规则总数:', count);
- return count;
- } catch (e) {
- console.error('CSS规则计数失败:', e);
- return 0;
- }
- }
- function getCssPerformance(totalCssRules) {
- if (totalCssRules <= 5000) {
- return '✅CSS规则数量正常,可以流畅运行';
- } else if (totalCssRules <= 7000) {
- return '❓CSS规则数量较多,可能会导致设备运行缓慢';
- } else if (totalCssRules < 9999) {
- return '⚠️CSS规则数量接近上限,可能明显影响设备性能';
- } else {
- return '🆘CSS规则数量过多,不建议订阅此规则';
- }
- }
- function truncateErrorLine(errorLine, maxLength = 150) {
- return errorLine.length > maxLength ? errorLine.substring(0, maxLength) + "..." : errorLine;
- }
- async function fetchAndFormatCss() {
- const url = getCssFileUrl();
- console.log('尝试获取CSS文件:', url);
- try {
- const response = await fetch(url, {
- cache: 'no-store'
- });
- if (!response.ok) throw new Error(`HTTP状态: ${response.status}`);
- const text = await response.text();
- console.log('原始CSS内容:', text);
- return text;
- } 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}`;
- }
- function validateCss(rawCss, formattedCss, isAutoRun = false) {
- if (!formattedCss) return;
- let hasError = false;
- const errors = [];
- const lines = formattedCss.split('\n');
- const totalCssRules = countCssRules(formattedCss);
- const cssPerformance = getCssPerformance(totalCssRules);
- const pseudoSupport = checkPseudoClassSupport(rawCss);
- try {
- csstree.parse(formattedCss, {
- onParseError(error) {
- hasError = true;
- const errorLine = lines[error.line - 1] || "无法提取错误行";
- const truncatedErrorLine = truncateErrorLine(errorLine);
- const translatedMessage = translateErrorMessage(error.message);
- errors.push(`
- CSS 解析错误:
- - 位置:第 ${error.line} 行
- - 错误信息:${translatedMessage}
- - 错误片段:${truncatedErrorLine}
- `.trim());
- }
- });
- const resultMessage = `
- CSS验证结果:
- - 规则总数:${totalCssRules}
- - 性能评价:${cssPerformance}
- - 伪类支持:${pseudoSupport}
- ${hasError ? '\n发现错误:\n' + errors.join('\n\n') : '\n未发现语法错误'}
- `.trim();
- if (isAutoRun && hasError) {
- alert(resultMessage);
- } else if (!isAutoRun) {
- alert(resultMessage);
- }
- } catch (error) {
- const translatedMessage = translateErrorMessage(error.message);
- alert(`CSS验证失败:${translatedMessage}`);
- }
- }
- async function autoRunCssValidation() {
- const rawCss = await fetchAndFormatCss();
- if (rawCss) {
- const formattedCss = formatCssWithJsBeautify(rawCss);
- if (formattedCss) {
- validateCss(rawCss, formattedCss, true);
- }
- }
- }
- function initializeScript() {
- const isAutoRunEnabled = GM_getValue("autoRun", true);
- GM_registerMenuCommand(isAutoRunEnabled ? "关闭自动运行" : "开启自动运行", () => {
- GM_setValue("autoRun", !isAutoRunEnabled);
- alert(`自动运行已${isAutoRunEnabled ? "关闭" : "开启"}!`);
- });
- GM_registerMenuCommand("验证CSS文件", async () => {
- const rawCss = await fetchAndFormatCss();
- if (rawCss) {
- const formattedCss = formatCssWithJsBeautify(rawCss);
- if (formattedCss) {
- validateCss(rawCss, formattedCss, false);
- }
- }
- });
- if (isAutoRunEnabled) {
- autoRunCssValidation();
- }
- }
- initializeScript();
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址