您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Replace specific favicon with a old one on cnblogs.
// ==UserScript== // @name Get Old Cnblogs Favicon Back // @namespace http://tampermonkey.net/ // @version 1.1.0 // @description Replace specific favicon with a old one on cnblogs. // @author aspen138 // @icon https://assets.cnblogs.com/favicon_v3_preview.ico?v=1 // @match *://*.cnblogs.com/* // @grant none // @run-at document-start // @license MIT // ==/UserScript== (function () { 'use strict'; // Favicon URLs const FAVICON_URL_V3 = 'https://assets.cnblogs.com/favicon_v3_preview.ico?v=1'; const FAVICON_URL_COMMON = 'https://common.cnblogs.com/favicon.svg'; const FAVICON_URL_V3P2 = 'https://assets.cnblogs.com/favicon_v3_2.ico'; const FAVICON_URL_DEFAULT = FAVICON_URL_V3; // Default favicon to use // Link mappings for different icon types const linkMap = { "icon": FAVICON_URL_DEFAULT, "shortcut icon": FAVICON_URL_DEFAULT, "apple-touch-icon": FAVICON_URL_COMMON, // Use SVG for Apple touch icon }; // Meta tag mappings const metaMap = { "application-name": "博客园", "apple-mobile-web-app-title": "博客园" }; function main() { waitForElement("body").then(() => { console.log("CNBlogs favicon enhancer: Body loaded, initializing..."); }); waitForElement("head").then(() => { console.log("CNBlogs favicon enhancer: Head loaded, applying changes..."); monitorHead(); monitorTitle(); }); } // Utility function to wait for elements to load async function waitForElement(selector) { const el = document.querySelector(selector); if (el) return el; return new Promise((resolve) => { const fn = () => { const el2 = document.querySelector(selector); if (el2) { return resolve(el2); } requestAnimationFrame(fn); }; requestAnimationFrame(fn); }); } // Monitor and update favicon and related elements function monitorHead() { const sync = () => { // Update favicon links Object.entries(linkMap).forEach(([rel, targetValue]) => { let link = document.querySelector(`link[rel="${rel}"]`); // If link doesn't exist, create it if (!link) { link = document.createElement("link"); link.rel = rel; document.head.appendChild(link); } // Update href if different if (link.getAttribute("href") !== targetValue) { link.setAttribute("href", targetValue); console.log(`CNBlogs favicon enhancer: Updated ${rel} to ${targetValue}`); } }); // Update meta tags Object.entries(metaMap).forEach(([name, targetValue]) => { let meta = document.querySelector(`meta[name="${name}"]`); // If meta doesn't exist, create it if (!meta) { meta = document.createElement("meta"); meta.name = name; document.head.appendChild(meta); } // Update content if different if (meta.getAttribute("content") !== targetValue) { meta.setAttribute("content", targetValue); console.log(`CNBlogs favicon enhancer: Updated meta ${name} to ${targetValue}`); } }); // Handle notification-based favicon switching (if applicable) handleNotificationFavicon(); }; // Initial sync sync(); // Monitor for changes const mutationObserverOptions = { subtree: true, characterData: true, childList: true, attributes: true }; // Re-sync when page visibility changes window.addEventListener("visibilitychange", sync); // Monitor head for changes new MutationObserver(sync).observe(document.head, mutationObserverOptions); console.log("CNBlogs favicon enhancer: Monitoring started"); } // Handle notification-based favicon switching function handleNotificationFavicon() { // Check for notification indicators (adjust selector based on CNBlogs structure) const hasNotification = document.querySelector('[class*="notification"], [class*="unread"], .msg-count, [data-count]:not([data-count="0"])'); if (hasNotification) { // Use a different favicon when there are notifications const notificationFavicon = FAVICON_URL_V3P2; const faviconLink = document.querySelector('link[rel="icon"], link[rel="shortcut icon"]'); if (faviconLink && faviconLink.getAttribute("href") !== notificationFavicon) { faviconLink.setAttribute("href", notificationFavicon); console.log("CNBlogs favicon enhancer: Switched to notification favicon"); } } } // Monitor and enhance page title async function monitorTitle() { const titleEl = await waitForElement("head > title"); const sync = () => { const currentTitle = document.title; // Enhance title with CNBlogs branding if needed let newTitle = currentTitle; // Add notification count to title if present const notificationElement = document.querySelector('[class*="notification"], .msg-count'); if (notificationElement) { const count = notificationElement.textContent.trim(); if (count && count !== '0' && !currentTitle.startsWith(`(${count})`)) { newTitle = `(${count}) ${currentTitle}`; } } // Ensure "博客园" branding is present if (!newTitle.includes("博客园") && !newTitle.includes("CNBlogs")) { if (newTitle.includes(" - ")) { newTitle = newTitle.replace(" - ", " - 博客园 - "); } else { newTitle = `${newTitle} - 博客园`; } } if (newTitle !== document.title) { document.title = newTitle; console.log(`CNBlogs favicon enhancer: Title updated to "${newTitle}"`); } }; // Initial sync sync(); // Monitor for changes window.addEventListener("visibilitychange", sync); new MutationObserver(sync).observe(titleEl, { subtree: true, characterData: true, childList: true }); // Also monitor for dynamic content changes that might affect notifications new MutationObserver(sync).observe(document.body, { subtree: true, childList: true, attributes: true, attributeFilter: ['class', 'data-count'] }); console.log("CNBlogs favicon enhancer: Title monitoring started"); } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', main); } else { main(); } console.log("CNBlogs favicon enhancer: Script loaded and initialized"); })();