Replace specific favicon with a old one on cnblogs.
As of
// ==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");
})();