Get Old Cnblogs Favicon Back

Replace specific favicon with a old one on cnblogs.

Versión del día 30/8/2025. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==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");

})();