IThome Pro - IT之家高级优化版 2024

优化ithome网页端浏览效果

目前為 2024-10-05 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name IThome Pro - IT之家高级优化版 2024
  3. // @version 3.7
  4. // @description 优化ithome网页端浏览效果
  5. // @match *://*.ithome.com/*
  6. // @run-at document-start
  7. // @namespace https://gf.qytechs.cn/users/1354671
  8. // ==/UserScript==
  9.  
  10. (function() {
  11. 'use strict';
  12.  
  13. // Function to keep the page active by simulating clicks
  14. function keepPageActive() {
  15. const event = new MouseEvent('click', {
  16. view: window,
  17. bubbles: true,
  18. cancelable: true,
  19. clientX: 0, // 点击页面左上角,通常是空白区域
  20. clientY: 0
  21. });
  22. document.dispatchEvent(event);
  23. }
  24.  
  25. // Set an interval to keep the page active every 0.2 seconds
  26. const intervalId = setInterval(keepPageActive, 200);
  27.  
  28. // Stop the interval after 5 seconds
  29. setTimeout(() => {
  30. clearInterval(intervalId);
  31. }, 1000);
  32.  
  33. // 定义样式用于立即隐藏页面内容
  34. const hideStyle = document.createElement('style');
  35. hideStyle.innerHTML = `body { opacity: 0; }`;
  36. document.head.appendChild(hideStyle);
  37.  
  38. // 针对 https://www.ithome.com 页面执行逻辑
  39. if (window.location.href === 'https://www.ithome.com' || window.location.href === 'https://www.ithome.com/') {
  40. // 立即隐藏 主页 页面内容
  41. document.head.appendChild(hideStyle);
  42. // 跳转到 blog 页面
  43. window.location.replace('https://www.ithome.com/blog/');
  44. return;
  45. }
  46.  
  47. // 针对 https://www.ithome.com/blog/ 页面执行逻辑
  48. if (window.location.href.startsWith('https://www.ithome.com/blog/')) {
  49. // 立即隐藏 blog 页面内容
  50. document.head.appendChild(hideStyle);
  51. }
  52.  
  53. // Function to hide elements based on AdGuard rules
  54. function hideElements() {
  55. const selectors = [
  56. '#nav', '#top', '#tt', '#list > div.fr.fx:last-child', '#side_func',
  57. '#dt > div.fl.content:first-child > div.cv:first-child', '#dt > div.fr.fx:last-child',
  58. '#dt > div.fl.content:first-child > div.newsgrade:nth-child(6)',
  59. '#dt > div.fl.content:first-child > div.shareto:nth-child(7)',
  60. '#dt > div.fl.content:first-child > iframe.dajia:nth-child(10)',
  61. '#dt > div.fl.content:first-child > div.newsgrade:nth-child(8)',
  62. '#dt > div.fl.content:first-child > div.newserror:nth-child(7)',
  63. '#dt > div.fl.content:first-child > div.newsreward:nth-child(6)',
  64. '#dt > div.fl.content:first-child > div.shareto:nth-child(9)',
  65. '#rm-login-modal > div.modal.has-title.loaded',
  66. '#dt > div.fl.content:first-child > div.related_post:nth-child(8)',
  67. '#dt > div.fl.content:first-child > div.newserror:nth-child(5)',
  68. '#paragraph > p.ad-tips:last-child', '#postcomment3', '#fls', '#fi', '#lns',
  69. '#paragraph > div.tougao-user:nth-child(2)', '#login-guide-box', '.dajia',
  70. '#paragraph > div.tagging1:last-child',
  71. '#paragraph > p.ad-tips',
  72. '[id^="ad-id-"]'
  73. ];
  74.  
  75. selectors.forEach(selector => {
  76. document.querySelectorAll(selector).forEach(element => {
  77. element.style.display = 'none';
  78. });
  79. });
  80. }
  81.  
  82. // Function to process and set rounded images
  83. function processImage(image) {
  84. if (image.classList.contains('titleLogo')) return;
  85. if (image.classList.contains('lazy') && image.classList.contains('emoji')) return;
  86. if (image.classList.contains('ruanmei-emoji') && image.classList.contains('emoji')) return;
  87. if (image.id === 'image-viewer' || image.classList.contains('zoomed')) return;
  88. if (image.classList.contains('comment-image')) return; // 排除带有评论区特征的图片
  89. // 图片
  90. if (image.closest('a.img')) {
  91. const anchor = image.closest('a.img');
  92. if (!anchor.classList.contains('processed')) {
  93. anchor.style.border = '3px solid #CCC';
  94. anchor.style.borderRadius = '12px';
  95. anchor.style.display = 'inline-block';
  96. anchor.style.overflow = 'hidden';
  97. anchor.classList.add('processed');
  98. }
  99. // 视频
  100. } else if (image.closest('.ithome_super_player')) {
  101. const videoPlayer = image.closest('.ithome_super_player');
  102. if (!videoPlayer.parentNode.classList.contains('processed')) {
  103. const wrapper = document.createElement('div');
  104. wrapper.style.border = '3px solid #CCC';
  105. wrapper.style.borderRadius = '12px';
  106. wrapper.style.overflow = 'hidden';
  107. wrapper.style.maxWidth = '100%';
  108. wrapper.style.display = 'block';
  109. wrapper.style.margin = '0 auto';
  110. wrapper.classList.add('processed');
  111. videoPlayer.parentNode.insertBefore(wrapper, videoPlayer);
  112. wrapper.appendChild(videoPlayer);
  113.  
  114. // 设置预览图根据父元素高度调整
  115. const img = videoPlayer.querySelector('img');
  116. if (img) {
  117. const imgWidth = img.getAttribute('w');
  118. const imgHeight = img.getAttribute('h');
  119. const parentHeight = wrapper.offsetHeight;
  120.  
  121. if (imgWidth > wrapper.offsetWidth) {
  122. const aspectRatio = imgWidth / imgHeight;
  123. img.style.height = `${parentHeight}px`;
  124. img.style.width = `${parentHeight * aspectRatio}px`;
  125. img.style.objectFit = 'cover';
  126. } else {
  127. img.style.width = `${imgWidth}px`;
  128. img.style.height = `${imgHeight}px`;
  129. }
  130. }
  131. }
  132. // 头像修正
  133. } else {
  134. if (image.width >= 30) {
  135. image.style.borderRadius = '12px';
  136. image.style.border = '3px solid #CCC';
  137. }
  138. if (image.width >= 30 && image.height > 150) {
  139. image.style.borderRadius = '12px';
  140. image.style.border = '3px solid #CCC';
  141. image.style.maxWidth = '400px';
  142. image.style.height = 'auto';
  143. image.style.objectFit = 'cover';
  144. image.style.overflow = 'hidden';
  145. }
  146. }
  147. }
  148.  
  149. // Function to set rounded images on all img elements
  150. function setRoundedImages() {
  151. document.querySelectorAll('img').forEach(image => processImage(image));
  152. }
  153.  
  154. // Function to wrap images in <p> tags
  155. function wrapImagesInP() {
  156. if (window.location.href.startsWith('https://www.ithome.com/blog/')) return;
  157. document.querySelectorAll('img').forEach(image => {
  158. if (image.closest('.ithome_super_player')) return;
  159. if (image.classList.contains('ruanmei-emoji') && image.classList.contains('emoji')) return;
  160. if (image.classList.contains('ithome_super_player')) return;
  161. if (image.parentNode.tagName.toLowerCase() === 'p' && image.parentNode.children.length === 1) return;
  162. if (image.width < 25 || image.height < 20) return; // 排除编辑标识
  163. const p = document.createElement('p');
  164. p.style.textAlign = 'center';
  165. p.style.margin = '0';
  166. p.setAttribute('data-vmark', 'f5e8');
  167. image.parentNode.insertBefore(p, image);
  168. p.appendChild(image);
  169. });
  170. }
  171.  
  172. // Function to process specific iframes
  173. function processIframes() {
  174. const iframes = document.querySelectorAll('.content .post_content iframe.ithome_video, .content .post_content iframe[src*="player.bilibili.com"]');
  175.  
  176. iframes.forEach(iframe => {
  177. if (!iframe.classList.contains('processed')) {
  178. iframe.style.borderRadius = '12px';
  179. iframe.style.border = '3px solid #CCC';
  180. iframe.style.display = 'block';
  181. iframe.style.margin = '0 auto';
  182. iframe.style.overflow = 'hidden';
  183. iframe.classList.add('processed');
  184. }
  185. });
  186. }
  187.  
  188. // Function to set rounded corners for comments
  189. function setRounded() {
  190. const roundeds = document.querySelectorAll(
  191. '.comm_list ul.list li.entry ul.reply, .content .post_content blockquote, ' +
  192. '.add_comm input#btnComment, .card, span.card'
  193. );
  194. roundeds.forEach(rounded => rounded.style.borderRadius = '12px');
  195.  
  196. document.querySelectorAll('.add_comm').forEach(addCommElement => {
  197. addCommElement.style.borderRadius = '0px 0px 12px 12px';
  198. });
  199.  
  200. document.querySelectorAll('.card, span.card').forEach(card => {
  201. card.style.borderRadius = '12px';
  202. card.style.transform = 'scale(0.8)';
  203. });
  204. }
  205.  
  206. // Function to remove specific ads
  207. function removeAds() {
  208. document.querySelectorAll('div.bb.clearfix > div.fl > ul.bl > li').forEach(element => {
  209. if (element.querySelector('div.c > div.m:empty')) element.remove();
  210. });
  211. }
  212.  
  213. // Automatically click the "Load More" button
  214. function autoClickLoadMore() {
  215. const loadMoreButton = document.querySelector('a.more');
  216.  
  217. if (loadMoreButton) {
  218. const observer = new IntersectionObserver((entries) => {
  219. entries.forEach(entry => {
  220. if (entry.isIntersecting) {
  221. loadMoreButton.click();
  222. }
  223. });
  224. });
  225.  
  226. observer.observe(loadMoreButton);
  227.  
  228. // 监听DOM变化,重新观察按钮
  229. const mutationObserver = new MutationObserver(() => {
  230. const newLoadMoreButton = document.querySelector('a.more');
  231. if (newLoadMoreButton && !observer.observe(newLoadMoreButton)) {
  232. observer.observe(newLoadMoreButton);
  233. }
  234. });
  235.  
  236. mutationObserver.observe(document.body, { childList: true, subtree: true });
  237. }
  238. }
  239.  
  240. // Function to handle new nodes for comment images
  241. function handleNewNodes(nodes) {
  242. nodes.forEach((node) => {
  243. if (node.nodeType === Node.ELEMENT_NODE) {
  244. if (node.matches('.post-img-list.c-1')) {
  245. decodeAndDisplayImage(node);
  246. }
  247. // 递归处理子节点
  248. node.querySelectorAll('.post-img-list.c-1').forEach((childNode) => {
  249. decodeAndDisplayImage(childNode);
  250. });
  251. }
  252. });
  253. }
  254.  
  255. // Function to decode and display images in comments
  256. function decodeAndDisplayImages(node) {
  257. try {
  258. // 获取当前容器中所有的 img-placeholder
  259. const spanList = node.querySelectorAll('span.img-placeholder');
  260. spanList.forEach(span => {
  261. const dataS = span.getAttribute('data-s');
  262. if (dataS) {
  263. let decodedUrl;
  264. try {
  265. decodedUrl = atob(dataS); // 解码 Base64 字符串
  266. } catch (error) {
  267. console.error("图片 URL 解码失败:", error, dataS);
  268. return; // 解码失败时退出
  269. }
  270.  
  271. const img = document.createElement('img');
  272. img.src = decodedUrl;
  273. img.classList.add('comment-image');
  274. img.style.maxWidth = '200px';
  275. img.style.display = 'block';
  276. img.style.marginLeft = '0';
  277. img.style.border = '1px solid rgb(204, 204, 204)';
  278. img.style.borderRadius = '12px';
  279. img.style.cursor = 'pointer';
  280.  
  281. let isZoomed = false;
  282. img.addEventListener('click', function () {
  283. if (!isZoomed) {
  284. img.style.maxWidth = '100%';
  285. img.style.height = 'auto';
  286. img.style.cursor = 'zoom-out';
  287. isZoomed = true;
  288. } else {
  289. img.style.maxWidth = '200px';
  290. img.style.height = 'auto';
  291. img.style.cursor = 'pointer';
  292. isZoomed = false;
  293. }
  294. });
  295.  
  296. span.innerHTML = ''; // 清空 span 内容
  297. span.appendChild(img); // 添加 img 元素
  298. }
  299. });
  300. } catch (e) {
  301. console.error("处理图片时出错:", e, node);
  302. }
  303. }
  304.  
  305. // Observe DOM changes and apply styles/changes dynamically
  306. function observeDOM() {
  307. const observer = new MutationObserver(mutationsList => {
  308. for (const mutation of mutationsList) {
  309. if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
  310. setRoundedImages();
  311. wrapImagesInP();
  312. setRounded();
  313. removeAds();
  314. hideElements();
  315. mutation.addedNodes.forEach((node) => {
  316. if (node.nodeType === Node.ELEMENT_NODE) {
  317. // 检查是否是图片列表并进行处理
  318. if (node.matches('.post-img-list')) {
  319. decodeAndDisplayImages(node);
  320. }
  321. // 检查新加入的节点内部是否包含图片列表
  322. node.querySelectorAll('.post-img-list').forEach((childNode) => {
  323. decodeAndDisplayImages(childNode);
  324. });
  325. }
  326. });
  327. }
  328. }
  329. });
  330.  
  331. observer.observe(document.body, { childList: true, subtree: true });
  332. }
  333.  
  334. // Initial processing for existing comment images
  335. document.querySelectorAll('.post-img-list.c-1').forEach((node) => {
  336. decodeAndDisplayImage(node);
  337. });
  338.  
  339. document.querySelectorAll('.post-img-list').forEach((node) => {
  340. decodeAndDisplayImages(node);
  341. });
  342.  
  343. // Event listeners
  344. window.addEventListener('scroll', autoClickLoadMore);
  345. window.addEventListener('load', function() {
  346. hideElements();
  347. removeAds();
  348. wrapImagesInP();
  349. setRoundedImages();
  350. setRounded();
  351. processIframes();
  352. observeDOM();
  353. removeAds();
  354. document.body.style.opacity = '1';
  355.  
  356. // 处理图片懒加载
  357. document.querySelectorAll('img').forEach(img => {
  358. if (img.hasAttribute('loading')) {
  359. img.removeAttribute('loading');
  360. }
  361. if (img.classList.contains('lazy')) {
  362. img.classList.remove('lazy');
  363. }
  364. if (img.dataset.src) {
  365. img.src = img.dataset.src;
  366. }
  367. if (img.dataset.original) {
  368. img.src = img.dataset.original;
  369. }
  370. img.loading = 'eager';
  371. });
  372. });
  373.  
  374. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址