IThome Pro

优化ithome网页端浏览效果

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         IThome Pro
// @version      4.6
// @description  优化ithome网页端浏览效果
// @match        *://*.ithome.com/*
// @run-at       document-start
// @namespace    https://greasyfork.org/users/1354671
// ==/UserScript==

(function () {
  "use strict";

  // 启用评论框:true:启用 false:关闭
  const showCommentBox = false;

  // 定义样式-hideStyle:不透明度 0
  const hideStyle = document.createElement("style");
  hideStyle.innerHTML = `body { opacity: 0; }`;
  document.head.appendChild(hideStyle);

  // 跳转到 blog 页面,加载完成前隐藏原始页面
  if (
    window.location.href === "https://www.ithome.com" ||
    window.location.href === "https://www.ithome.com/"
  ) {
    document.head.appendChild(hideStyle);
    window.location.replace("https://www.ithome.com/blog/");
    return;
  }

  // blog 页面加载完成前隐藏原始页面
  if (window.location.href.startsWith("https://www.ithome.com/blog/")) {
    document.head.appendChild(hideStyle);
  }

  // 函数:保持页面激活,这样可以去除弹出的登录框
  function keepPageActive() {
    const event = new Event("mousemove", { bubbles: true, cancelable: true });

    // 设置定时器,每0.1秒触发一次事件
    const intervalId = setInterval(() => {
      document.dispatchEvent(event);
    }, 100); // 0.1秒(100毫秒)

    // 5秒后停止定时器
    setTimeout(() => {
      clearInterval(intervalId);
      console.log("Stopped keeping page active.");
    }, 5000); // 5秒(5000毫秒)
  }

  // [调用] 保持页面激活
  keepPageActive();

  // 函数:净化页面 利用 AdGuard 规则
  function hideElements() {
    const selectors = [
      ...(!showCommentBox ? ["#postcomment3"] : []),
      "#nav",
      "#top",
      "#tt",
      "#list > div.fr.fx:last-child",
      "#side_func",
      "#dt > div.fl.content:first-child > div.cv:first-child",
      "#dt > div.fr.fx:last-child",
      "#dt > div.fl.content:first-child > div.newsgrade:nth-child(6)",
      "#dt > div.fl.content:first-child > div.shareto:nth-child(7)",
      "#dt > div.fl.content:first-child > iframe.dajia:nth-child(10)",
      "#dt > div.fl.content:first-child > div.newsgrade:nth-child(8)",
      "#dt > div.fl.content:first-child > div.newserror:nth-child(7)",
      "#dt > div.fl.content:first-child > div.newsreward:nth-child(6)",
      "#dt > div.fl.content:first-child > div.shareto:nth-child(9)",
      "#rm-login-modal > div.modal.has-title.loaded",
      "#dt > div.fl.content:first-child > div.related_post:nth-child(8)",
      "#dt > div.fl.content:first-child > div.newserror:nth-child(5)",
      "#paragraph > p.ad-tips:last-child",
      "#fls",
      "#fi",
      "#lns",
      "#paragraph > div.tougao-user:nth-child(2)",
      "#login-guide-box",
      ".dajia",
      "#paragraph > div.tagging1:last-child",
      "#paragraph > p.ad-tips",
      '[id^="ad-id-"]',
      "div.-hongbao-container.bb:nth-child(6)",
    ];

    selectors.forEach((selector) => {
      document.querySelectorAll(selector).forEach((element) => {
        element.style.display = "none";
      });
    });
  }

  // 函数:图片处理 - 圆角、边框
  function processImage(image) {
    // 这部分匹配到的图片不处理
    if (image.closest("#post_comm")) return;
    if (image.classList.contains("titleLogo")) return;
    if (image.classList.contains("lazy") && image.classList.contains("emoji"))
      return;
    if (
      image.classList.contains("ruanmei-emoji") &&
      image.classList.contains("emoji")
    )
      return;
    if (image.id === "image-viewer" || image.classList.contains("zoomed"))
      return;
    if (image.classList.contains("comment-image")) return;

    // 首页图片
    if (image.closest("a.img")) {
      const anchor = image.closest("a.img");
      if (!anchor.classList.contains("processed")) {
        anchor.style.border = "3px solid #CCC";
        anchor.style.borderRadius = "12px";
        anchor.style.display = "inline-block";
        anchor.style.overflow = "hidden";
        anchor.classList.add("processed");
      }
      // 视频预览图
    } else if (image.closest(".ithome_super_player")) {
      const videoPlayer = image.closest(".ithome_super_player");
      if (!videoPlayer.parentNode.classList.contains("processed")) {
        const wrapper = document.createElement("div");
        wrapper.style.border = "3px solid #CCC";
        wrapper.style.borderRadius = "12px";
        wrapper.style.overflow = "hidden";
        wrapper.style.maxWidth = "100%";
        wrapper.style.display = "block";
        wrapper.style.margin = "0 auto";
        wrapper.classList.add("processed");
        videoPlayer.parentNode.insertBefore(wrapper, videoPlayer);
        wrapper.appendChild(videoPlayer);

        // 视频预览图根据父元素高度调整
        const img = videoPlayer.querySelector("img");
        if (img) {
          const imgWidth = img.getAttribute("w");
          const imgHeight = img.getAttribute("h");
          const parentHeight = wrapper.offsetHeight;

          if (imgWidth > wrapper.offsetWidth) {
            const aspectRatio = imgWidth / imgHeight;
            img.style.height = `${parentHeight}px`;
            img.style.width = `${parentHeight * aspectRatio}px`;
            img.style.objectFit = "cover";
          } else {
            img.style.width = `${imgWidth}px`;
            img.style.height = `${imgHeight}px`;
          }
        }
      }
    } else {
      // 超长图片宽度 450px
      if (image.height > 1000) {
        image.style.borderRadius = "12px";
        image.style.border = "3px solid #CCC";
        image.style.width = "400px";
        image.style.maxWidth = "400px";
        image.style.height = "auto";
        image.style.objectFit = "cover";
        image.style.overflow = "hidden";
        // 常规图片宽度 450px
      } else {
        image.style.borderRadius = "12px";
        image.style.border = "3px solid #CCC";
        image.style.maxWidth = "450px";
      }
    }
  }

  // [调用] 图片处理
  function setRoundedImages() {
    document.querySelectorAll("img").forEach((image) => processImage(image));
  }

  // 函数:头像处理
  function styleHeaderImage() {
    const headerImages = document.querySelectorAll(".list .entry .headerimage");

    headerImages.forEach((image) => {
      image.style.borderRadius = "12px";
      image.style.border = "3px solid #CCC";
    });
  }

  // 函数:多图连续排列时插入间隔
  function wrapImagesInP() {
    if (window.location.href.startsWith("https://www.ithome.com/blog/")) return;
    document.querySelectorAll("img").forEach((image) => {
      // 这部分匹配到的图片不处理
      if (image.closest("#post_comm")) return;
      if (image.closest(".ithome_super_player")) return;
      if (
        image.classList.contains("ruanmei-emoji") &&
        image.classList.contains("emoji")
      )
        return;
      if (image.classList.contains("ithome_super_player")) return;
      if (
        image.parentNode.tagName.toLowerCase() === "p" &&
        image.parentNode.children.length === 1
      )
        return;
      if (image.width < 25 || image.height < 20) return;

      const p = document.createElement("p");
      p.style.textAlign = "center";
      p.style.margin = "0";
      p.setAttribute("data-vmark", "f5e8");
      image.parentNode.insertBefore(p, image);
      p.appendChild(image);
    });
  }

  // 函数:视频处理 - 圆角、边框
  function processIframes() {
    const iframes = document.querySelectorAll(
      '.content .post_content iframe.ithome_video, .content .post_content iframe[src*="player.bilibili.com"]',
    );

    iframes.forEach((iframe) => {
      if (!iframe.classList.contains("processed")) {
        iframe.style.borderRadius = "12px";
        iframe.style.border = "3px solid #CCC";
        iframe.style.display = "block";
        iframe.style.margin = "0 auto";
        iframe.style.overflow = "hidden";
        iframe.classList.add("processed");
      }
    });
  }

  // 函数:页面样式圆角
  function setRounded() {
    const roundeds = document.querySelectorAll(
      ".comm_list ul.list li.entry ul.reply, .content .post_content blockquote, " +
        ".add_comm input#btnComment, .card, span.card",
    );
    roundeds.forEach((rounded) => (rounded.style.borderRadius = "12px"));

    document.querySelectorAll(".add_comm").forEach((addCommElement) => {
      addCommElement.style.borderRadius = "0px 0px 12px 12px";
    });

    document.querySelectorAll(".card, span.card").forEach((card) => {
      card.style.borderRadius = "12px";
      card.style.transform = "scale(0.8)";
    });
  }

  // 函数:移除首页信息流广告
  function removeAds() {
    document
      .querySelectorAll("div.bb.clearfix > div.fl > ul.bl > li")
      .forEach((element) => {
        if (element.querySelector("div.c > div.m:empty")) element.remove();
      });
  }

  // 函数:自动点击「加载更多」按钮
  function autoClickLoadMore() {
    const loadMoreButton = document.querySelector("a.more");

    if (loadMoreButton) {
      const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            loadMoreButton.click();
          }
        });
      });

      observer.observe(loadMoreButton);

      // 监听DOM变化
      const mutationObserver = new MutationObserver(() => {
        const newLoadMoreButton = document.querySelector("a.more");
        if (newLoadMoreButton && !observer.observe(newLoadMoreButton)) {
          observer.observe(newLoadMoreButton);
        }
      });

      mutationObserver.observe(document.body, {
        childList: true,
        subtree: true,
      });
    }
  }

  // 函数:评论加载
  function forceLoadComments() {
    const footer = document.querySelector("#post_comm");

    const spacer = document.createElement("div");
    spacer.style.height = "100vh";
    spacer.style.visibility = "hidden";
    document.body.appendChild(spacer);

    window.scrollTo(0, document.body.scrollHeight);

    spacer.remove();
    window.scrollTo(0, 0);
  }

  // 函数:首页卡片样式
  function initializePage() {
    function makeListItemsClickable() {
      const listItems = document.querySelectorAll(".bl > li");

      listItems.forEach((li) => {
        const wrapper = document.createElement("div");
        wrapper.classList.add("hover-wrapper");
        wrapper.style.position = "relative";
        wrapper.style.padding = "12px 16px";
        wrapper.style.borderRadius = "12px";
        wrapper.style.overflow = "hidden";
        wrapper.style.margin = "16px 0";

        li.parentNode.insertBefore(wrapper, li);
        wrapper.appendChild(li);

        const titleLink = li.querySelector("h2 a");

        if (titleLink) {
          const titleText = document.createTextNode(titleLink.textContent);
          titleLink.replaceWith(titleText);

          wrapper.style.cursor = "pointer";
          wrapper.addEventListener("click", () => {
            window.open(titleLink.href, titleLink.target || "_self");
          });

          wrapper.addEventListener("mouseover", () => {
            wrapper.style.boxShadow = "0px 6px 15px rgba(0, 0, 0, 0.2)";
            wrapper.style.backgroundColor = getBackgroundColor();
          });

          wrapper.addEventListener("mouseout", () => {
            wrapper.style.boxShadow = "none";
            wrapper.style.backgroundColor = "transparent";
          });
        }
      });
    }

    function setHome() {
      const divs = document.querySelectorAll("div.fl");
      divs.forEach((div) => {
        div.style.width = "870px";
      });
    }

    function removeMarginTop() {
      const hoverWrappers = document.querySelectorAll(".hover-wrapper");
      hoverWrappers.forEach((hoverWrapper) => {
        const listItems = hoverWrapper.querySelectorAll("li");
        listItems.forEach((item) => {
          item.style.marginTop = "0";
        });
      });
    }

    function setDivWidthTo590() {
      const divs = document.querySelectorAll("div.c");
      divs.forEach((div) => {
        div.style.width = "640px";
      });
    }

    function getBackgroundColor() {
      if (
        window.matchMedia &&
        window.matchMedia("(prefers-color-scheme: dark)").matches
      ) {
        return "#333333";
      } else {
        return "#f9f9f9";
      }
    }

    makeListItemsClickable();
    setHome();
    removeMarginTop();
    setDivWidthTo590();
  }

  // 函数:评论区图片放大
  function replaceImageWrapper() {
    const imageWrappers = document.querySelectorAll(
      ".post-img-list a.img-wrapper",
    );

    imageWrappers.forEach((wrapper) => {
      const img = wrapper.querySelector("img");
      if (img) {
        const parent = wrapper.parentElement;

        wrapper.classList.remove("img-wrapper");
        wrapper.classList.add("img-click");

        wrapper.removeAttribute("href");

        img.style.width = "30%";
        img.style.height = "auto";
        img.style.borderRadius = "12px";
        img.style.border = "3px solid #CCC";

        let isZoomed = false;

        img.addEventListener("click", () => {
          if (isZoomed) {
            img.style.width = "30%";
          } else {
            img.style.width = "100%";
          }
          img.style.height = "auto";
          isZoomed = !isZoomed;
        });
      }
    });
  }

  // 函数:观察DOM变化,处理新刷出的内容
  function observeDOM() {
    const observer = new MutationObserver((mutationsList) => {
      for (const mutation of mutationsList) {
        if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
          wrapImagesInP();
          setRounded();
          removeAds();
          hideElements();
          setRoundedImages();
          styleHeaderImage();
          initializePage();
          replaceImageWrapper();
        }
      }
    });

    observer.observe(document.body, { childList: true, subtree: true });
  }

  // 监听事件
  window.addEventListener("scroll", autoClickLoadMore);
  window.addEventListener("load", function () {
    hideElements();
    forceLoadComments();
    removeAds();
    wrapImagesInP();
    setRounded();
    processIframes();
    setRoundedImages();
    styleHeaderImage();
    initializePage();
    replaceImageWrapper();
    observeDOM();
    document.body.style.opacity = "1";

    // 处理图片懒加载
    document.querySelectorAll("img").forEach((img) => {
      if (img.hasAttribute("loading")) {
        img.removeAttribute("loading");
      }
      if (img.classList.contains("lazy")) {
        img.classList.remove("lazy");
      }
      if (img.dataset.src) {
        img.src = img.dataset.src;
      }
      if (img.dataset.original) {
        img.src = img.dataset.original;
      }
      img.loading = "eager";
    });
  });
})();