Via Css隐藏规则日志
// ==UserScript==
// @name Via Css隐藏规则日志
// @namespace https://viayoo.com/
// @version 2.3.2
// @license MIT
// @description 格式化CSS规则,检测哪些规则生效,并输出匹配日志。
// @author Copilot
// @run-at document-start
// @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
// ==/UserScript==
(function() {
'use strict';
// 获取CSS文件URL
function getCssFileUrl() {
const currentHost = window.location.hostname;
return `https://${currentHost}/via_inject_blocker.css`;
}
// 格式化CSS内容
function formatCss(rawCss) {
try {
return css_beautify(rawCss, {
indent_size: 2,
selector_separator_newline: true
});
} catch (error) {
console.error(`CSS格式化失败:${error.message}`);
return null;
}
}
// 拆分选择器,保护属性值中的逗号
function splitSelectors(selectorText) {
const selectors = [];
let currentSelector = '';
let inAttribute = false;
let quote = null;
let i = 0;
while (i < selectorText.length) {
const char = selectorText[i];
if (inAttribute) {
// 如果在属性值中,检查是否遇到结束引号
if (char === quote) {
inAttribute = false;
quote = null;
}
currentSelector += char;
} else if (char === '"' || char === "'") {
// 进入属性值
inAttribute = true;
quote = char;
currentSelector += char;
} else if (char === ',' && !inAttribute) {
// 遇到选择器分隔符,且不在属性值中
if (currentSelector.trim()) {
selectors.push(currentSelector.trim());
currentSelector = '';
}
} else {
currentSelector += char;
}
i++;
}
// 添加最后一个选择器
if (currentSelector.trim()) {
selectors.push(currentSelector.trim());
}
return selectors;
}
// 提取有效选择器
function extractValidSelectors(rule) {
if (!rule.selectorText) return [];
// 使用 splitSelectors 函数拆分选择器
const selectors = splitSelectors(rule.selectorText).map(selector => selector.trim());
return selectors.filter(selector => {
try {
document.querySelector(selector);
return true;
} catch {
return false;
}
});
}
// 检测生效的CSS规则
function checkActiveRules(sheet) {
const activeRules = [];
if (!sheet || !sheet.cssRules) return activeRules;
for (const rule of sheet.cssRules) {
if (rule.selectorText) {
const validSelectors = extractValidSelectors(rule);
validSelectors.forEach(selector => {
const elements = document.querySelectorAll(selector);
if (elements.length > 0) {
activeRules.push({
selector,
count: elements.length
});
}
});
}
}
return activeRules;
}
// 检查CSS文件
async function checkCssFile() {
const cssFileUrl = getCssFileUrl();
try {
const response = await fetch(cssFileUrl);
if (!response.ok) {
alert(`无法加载CSS文件: ${cssFileUrl} (状态码: ${response.status})`);
return;
}
const rawCss = await response.text();
if (!rawCss.trim()) {
alert("CSS文件为空!");
return;
}
// 格式化CSS
const formattedCss = formatCss(rawCss);
if (!formattedCss) {
alert("CSS格式化失败!");
return;
}
// 创建临时样式表并检测规则
const styleElement = document.createElement('style');
styleElement.textContent = formattedCss;
document.head.appendChild(styleElement);
const activeRules = checkActiveRules(styleElement.sheet);
document.head.removeChild(styleElement); // 移除临时样式表
if (activeRules.length > 0) {
let resultMessage = `检测完成!共有 ${activeRules.length} 条规则生效:\n\n`;
activeRules.forEach((rule, index) => {
resultMessage += `${index + 1}. 匹配规则: ##${rule.selector}\n`;
resultMessage += `匹配到的元素数: ${rule.count}\n\n`;
});
alert(resultMessage);
} else {
alert("没有发现生效的CSS规则!");
}
} catch (error) {
console.error("获取CSS文件失败:", error);
alert("获取CSS文件失败,请检查网络连接或CSS文件!");
}
}
// 确保按钮存在
function ensureButtonExists() {
const existingButton = document.querySelector("div[style*='CSS日志']");
if (!existingButton) {
console.log("悬浮按钮不存在,正在创建...");
createFloatingButtonForCssCheck();
} else {
console.log("悬浮按钮已存在");
}
}
// 创建悬浮按钮功能(附带位置记忆)
function createFloatingButtonForCssCheck() {
// 如果是iframe,不创建按钮
if (window.self !== window.top) {
console.warn("当前页面是iframe,按钮可能不可见");
return;
}
console.log("正在创建悬浮按钮...");
const button = document.createElement("div");
button.textContent = "CSS日志";
button.style.position = "fixed";
button.style.zIndex = "10000"; // 提高 z-index
button.style.width = "70px";
button.style.height = "35px";
button.style.backgroundColor = "#2d89ef";
button.style.color = "white";
button.style.borderRadius = "5px";
button.style.textAlign = "center";
button.style.lineHeight = "35px";
button.style.fontSize = "14px";
button.style.boxShadow = "0px 4px 6px rgba(0,0,0,0.1)";
button.style.cursor = "pointer";
button.style.opacity = "0.9";
button.style.transition = "opacity 0.3s, transform 0.3s";
// 读取按钮上次保存的位置(默认在右下角)
const savedLeft = GM_getValue("floatingButtonLeft", window.innerWidth - 100);
const savedTop = GM_getValue("floatingButtonTop", window.innerHeight - 100);
button.style.left = `${savedLeft}px`;
button.style.top = `${savedTop}px`;
document.body.appendChild(button);
console.log("悬浮按钮已创建");
// 触控移动功能
let startX, startY, startLeft, startTop;
button.addEventListener("touchstart", (e) => {
const touch = e.touches[0];
startX = touch.clientX;
startY = touch.clientY;
startLeft = parseInt(button.style.left, 10);
startTop = parseInt(button.style.top, 10);
});
button.addEventListener("touchmove", (e) => {
const touch = e.touches[0];
const deltaX = touch.clientX - startX;
const deltaY = touch.clientY - startY;
button.style.left = `${startLeft + deltaX}px`;
button.style.top = `${startTop + deltaY}px`;
});
button.addEventListener("touchend", () => {
// 保存按钮位置
GM_setValue("floatingButtonLeft", parseInt(button.style.left, 10));
GM_setValue("floatingButtonTop", parseInt(button.style.top, 10));
// 自动贴边隐藏
const rect = button.getBoundingClientRect();
if (rect.left + rect.width / 2 < window.innerWidth / 2) {
button.style.left = "0px"; // 靠左
GM_setValue("floatingButtonLeft", 0);
} else {
button.style.left = `${window.innerWidth - rect.width}px`; // 靠右
GM_setValue("floatingButtonLeft", window.innerWidth - rect.width);
}
});
// 点击事件:执行检查功能
button.addEventListener("click", () => {
if (typeof checkCssFile === "function") {
checkCssFile();
} else {
console.error("checkCssFile 函数未定义!");
}
});
}
// 初始化脚本
function initializeFloatingButtonScript() {
const isButtonEnabled = GM_getValue("floatingButtonEnabled", false);
// 添加菜单命令:用于切换悬浮按钮开关
GM_registerMenuCommand(isButtonEnabled ? "关闭悬浮按钮" : "开启悬浮按钮", () => {
GM_setValue("floatingButtonEnabled", !isButtonEnabled);
alert(`悬浮按钮已${isButtonEnabled ? "关闭" : "开启"}!`);
location.reload();
});
if (isButtonEnabled) {
// 确保在 DOM 加载完成后创建按钮
if (document.readyState === "complete" || document.readyState === "interactive") {
ensureButtonExists();
} else {
document.addEventListener("DOMContentLoaded", ensureButtonExists);
}
}
}
// 注册菜单命令
GM_registerMenuCommand("检测CSS隐藏规则", checkCssFile);
// 执行初始化
initializeFloatingButtonScript();
})();