Zhihu enhancement

A more personalized Zhihu experience~

Installa questo script?
Script suggerito dall'autore

Potresti essere interessato/a anche a AutoPager

Installa questo script
  1. // ==UserScript==
  2. // @name Zhihu enhancement
  3. // @name:zh-CN 知乎增强
  4. // @name:zh-TW 知乎增強
  5. // @name:ru Улучшение Zhihu
  6. // @version 2.3.14
  7. // @author X.I.U
  8. // @description A more personalized Zhihu experience~
  9. // @description:zh-CN 屏蔽指定类别(视频、盐选、文章、想法、关注[赞同了XX/关注了XX]等等)、屏蔽用户、屏蔽关键词、默认收起回答、快捷收起回答/评论(左键两侧)、快捷回到顶部(右键两侧)、区分问题文章、移除高亮链接、净化搜索热门、净化标题消息、展开问题描述、显示问题作者、默认高清原图(无水印)、置顶显示时间、完整问题时间、直达问题按钮、默认站外直链...
  10. // @description:zh-TW 屏蔽指定類別(視頻、鹽選、文章、想法、關注[贊同了XX/關注了XX]等等)、屏蔽用戶、屏蔽關鍵詞、默認收起回答、快捷收起回答/評論、快捷回到頂部、區分問題文章、移除高亮鏈接、默認高清原圖(無水印)、默認站外直鏈...
  11. // @description:ru Более персонализированный опыт пользования сайтом Zhihu~
  12. // @match *://www.zhihu.com/*
  13. // @match *://zhuanlan.zhihu.com/*
  14. // @exclude https://www.zhihu.com/signin*
  15. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFo0lEQVR4nJWXT4hlVxHGf9/tJyYuzJtxIziQN8RBFDEtIWB0MW+Mi4CIk4UuAtqvAxPcqAkJRNxMshDUTc8s3TjdO3c9QbIKod+o4CIuZtRFDEi3EIgEM/02jpPIPZ+LqnPv6TeB4IHLPfeeP1X11VdV54i2vewtOhaITcQDdEgdthAdINAGNkgd0IEVbwR17rAmx1TniSVil6e0V0UKgJc8pWdfG5yvwqRhs1FQIyQ3trvcpxsVGd4xf/gelO24yV0usK1VB6APOMDMKSADBShIBWNwj1WwjClAzLEL0CMc86jj9cl/LgRs8ZjCJvexH5r/xAuJa260TatG6DosIee4lHO0ZnWDXH5bgYQ8uql122Iis2Xnj4JtRH675AIHMAQKuAsdrLV3dYXTwQ7Bir1jrzJ+Wyw698yVkLmgxgVg+PGjcPw8zD6JKcgFUcD94AoNa0eXkO600lVqXOPqPrPZNT6tjylYBRZfgp0n4GgFR7dDkEieeNys6ZPCBq4MCicXdFLWdIKBHtMFfC4JY8Hf/nxEyY0jmD+IM7Cgy77gxtto+jF4+NMj8+tY84YOLd8JnZJPpiDxI7shUigimJ2Gwxf5yLb9aryvffOj5+pXKbzJDxOVoIw7REkLhedno7+6CzffgdkpmE3z+5/Nrq7JJMfejc3bNj+TnT4tTyRtmLiAlARKliK09Uis2fsTPPcqvvwNdPlxuP4mbO+P4aQObz0cG958F77+mxMJh9kDcPh0IpCcUIerqycYuc8FGX7zczB/CI6O4cofAA9GjuRjUFhN2I0hmISlNFCUzCGMSkxqfFJw3XD6cXjuOt57A1YfpM/KSSEqY9zLo4w0psLsVnknyhkVYgNPMlRQh+qE63+GSsaBoK2VJcdTKTcKDLmhA/o1BDKFKzKl3aOJcoNBu3SHAAe4ahwwKgBkFRhdMMIc6Chzf+VphruT6urwZBh1aEQXjL/2fZidHoVP74/3xS8GP1IBLQ/hxuGonCLFxpZKjtTpDpRrSjYwYa2p4GcvoPm59ZFU5L54apvP4MZhY2XJMh1u+DB0Qk7ybaIR2EGHl34LV1/HGU5CsP8MbH4Gnvw1vPJX7G48pGw/OiLgyoEKf4PAYH0f6VtdIOAmlwCwugOrO0mDOHRodjrG/vGv9HvyQEprRwQjPB3rWg5oXBNR0A+Vf2wtJwDZaP5ZPL0fVv+B4zto5yJjKK6R0CUPMI7K6jUEsgpKGYqTwXpneGiExKnR4iuZ6d6Ggx/C7FNwdBuu/C6ROBmiUU/6PDuWhh9tEssQHxFQVlmP3wKfPY23Hotfe3+Eq8tYf/kJmE2jdK8pIPWJTDmJAFmq1We57iNnDQol9HWFDbr8rfg8eg+Wb8KV19DyrQjLa08hNal4/hD4l3D+LNr/HvhncPhC49+Ev5475DHfeUjjGrPt4jHY+upgvZOAPL0XRJ2fgwdPNS7IdvADuPgF7m15UDEDOhaXXKQT6RyAzTNw8DxMPxHWn/1p6ObMjc8+DjvfhVMvwOr9EcLjnwc6V38PL78Gq7vYG8PBxAqTzUbInJwoGtlbfA3tfCeEL/8G23sZEaAMIV99HW2egdW/m9Is/Mpf0O4bsPw7tY4os+OAbuUXHZKe8W3gVDLeEjr/uTgRHb0Hy7fyf0PUQd2YH4eZesrRmMBqDhF5gRFiIxSRQoGJxS0Kc8XNRSasHlqStOZ3Nf1aKVQzIKkMzeHTGZaRoEzWmyxIyw6zW6FRQ6c2NapC5pCjuAl5+Od7Tru41vxagEpTOeN0LAq7oe0lH0DeC6uVH0Lito03kbVUnmSrp+yE/967Y8dNfqEvdwD+L09a3BrgbqA/IZS4H4osLE3mHlDzYB30iUJ7XwwklrzPhXWk4ZIXdGxROM//g0ZbQrKXVza0EQcQiWNvcIuOXXbG6/n/AAwhLDO9HaqBAAAAAElFTkSuQmCC
  16. // @grant GM_xmlhttpRequest
  17. // @grant GM_registerMenuCommand
  18. // @grant GM_unregisterMenuCommand
  19. // @grant GM_openInTab
  20. // @grant GM_getValue
  21. // @grant GM_setValue
  22. // @grant GM_notification
  23. // @grant GM_info
  24. // @grant window.onurlchange
  25. // @sandbox JavaScript
  26. // @license GPL-3.0 License
  27. // @run-at document-end
  28. // @namespace https://greatest.deepsurf.us/scripts/4122051
  29. // @supportURL https://github.com/XIU2/UserScript
  30. // @homepageURL https://github.com/XIU2/UserScript
  31. // ==/UserScript==
  32.  
  33. 'use strict';
  34. var menu_ALL = [
  35. ['menu_defaultCollapsedAnswer', '默认收起回答', '默认收起回答', true],
  36. ['menu_collapsedAnswer', '一键收起回答/评论', '一键收起回答/评论', true],
  37. ['menu_collapsedNowAnswer', '快捷收起回答/评论 (点击两侧空白处)', '快捷收起回答/评论', true],
  38. ['menu_backToTop', '快捷回到顶部 (右键两侧空白处)', '快捷回到顶部', true],
  39. ['menu_blockUsers', '屏蔽指定用户', '屏蔽指定用户', true],
  40. ['menu_customBlockUsers', '自定义屏蔽用户', '自定义屏蔽用户', ['故事档案局', '盐选推荐', '盐选科普', '盐选成长计划', '知乎盐选会员', '知乎盐选创作者', '盐选心理', '盐选健康必修课', '盐选奇妙物语', '盐选生活馆', '盐选职场', '盐选文学甄选', '盐选作者小管家', '盐选博物馆', '盐选点金', '盐选测评室', '盐选科技前沿', '盐选会员精品']],
  41. ['menu_blockKeywords', '屏蔽指定关键词', '屏蔽指定关键词', true],
  42. ['menu_blockKeywordsComment', '屏蔽关键词 - 评论区', '屏蔽关键词 - 评论区', true],
  43. ['menu_customBlockKeywords', '自定义屏蔽关键词', '自定义屏蔽关键词', []],
  44. ['menu_blockType', '屏蔽指定类别 (视频/文章等)', '勾选 = 屏蔽该类别的信息流', ''],
  45. ['menu_blockTypeVideo', '视频 [首页、搜索页、问题页、关注页]', '视频(首页、搜索页、问题页、关注页)', true],
  46. ['menu_blockTypeArticle', '文章 [首页、搜索页、关注页]', '文章(首页、搜索页、关注页)', false],
  47. ['menu_blockTypePin', '想法 [首页、关注页]', '想法(首页、关注页)', false],
  48. ['menu_blockTypeFollowAgree', '赞同了XX [关注页]', '赞同了XX(关注页)', false],
  49. ['menu_blockTypeFollowQuestion', '关注了XX [关注页]', '关注了XX(关注页)', false],
  50. ['menu_blockTypeTopic', '话题 [搜索页]', '话题(搜索页)', false],
  51. ['menu_blockTypeSearch', '杂志文章、盐选专栏、相关搜索等 [搜索页]', '相关搜索、杂志、盐选等(搜索页)', false],
  52. ['menu_blockYanXuan', '盐选内容 [问题页]', '盐选内容(问题页)', false],
  53. ['menu_blockTypeLiveHot', '热榜文章、直播、广告等 [热榜]', '热榜文章、直播、广告等 [热榜]', true],
  54. ['menu_cleanHighlightLink', '移除高亮链接 (高亮的文字链接)', '移除高亮链接', true],
  55. ['menu_cleanSearch', '净化搜索热门 (默认搜索词及热门搜索)', '净化搜索热门', false],
  56. ['menu_cleanTitles', '净化标题消息 (标题中的私信/消息)', '净化标题提醒', false],
  57. ['menu_questionRichTextMore', '展开问题描述', '展开问题描述', false],
  58. ['menu_publishTop', '置顶显示时间', '置顶显示时间', true],
  59. ['menu_typeTips', '区分问题文章', '区分问题文章', true],
  60. ['menu_toQuestion', '直达问题按钮', '直达问题按钮', true]
  61. ], menu_ID = [];
  62. for (let i=0;i<menu_ALL.length;i++){ // 如果读取到的值为 null 就写入默认值
  63. if (GM_getValue(menu_ALL[i][0]) == null){GM_setValue(menu_ALL[i][0], menu_ALL[i][3])};
  64. }
  65. registerMenuCommand();
  66.  
  67. // 注册脚本菜单
  68. function registerMenuCommand() {
  69. if (menu_ID.length > menu_ALL.length){ // 如果菜单ID数组多于菜单数组,说明不是首次添加菜单,需要卸载所有脚本菜单
  70. for (let i=0;i<menu_ID.length;i++){
  71. GM_unregisterMenuCommand(menu_ID[i]);
  72. }
  73. }
  74. for (let i=0;i<menu_ALL.length;i++){ // 循环注册脚本菜单
  75. menu_ALL[i][3] = GM_getValue(menu_ALL[i][0]);
  76. if (menu_ALL[i][0] === 'menu_customBlockUsers') { // 只有 [屏蔽指定用户] 启用时,才注册菜单 [自定义屏蔽用户]
  77. if (menu_value('menu_blockUsers')) menu_ID[i] = GM_registerMenuCommand(`#️⃣ ${menu_ALL[i][1]}`, function(){customBlockUsers()});
  78. } else if (menu_ALL[i][0] === 'menu_customBlockKeywords') { // 只有 [屏蔽指定关键词] 启用时,才注册菜单 [自定义屏蔽关键词]
  79. if (menu_value('menu_blockKeywords')) menu_ID[i] = GM_registerMenuCommand(`#️⃣ ${menu_ALL[i][1]}`, function(){customBlockKeywords()});
  80. } else if (menu_ALL[i][0] === 'menu_blockKeywordsComment') { // 只有 [屏蔽指定关键词] 启用时,才注册菜单 [屏蔽关键词 - 评论区]
  81. if (menu_value('menu_blockKeywords')) menu_ID[i] = GM_registerMenuCommand(`${menu_ALL[i][3]?'✅':'❌'} ${menu_ALL[i][1]}`, function(){menu_switch(`${menu_ALL[i][3]}`,`${menu_ALL[i][0]}`,`${menu_ALL[i][2]}`)});
  82. } else if (menu_ALL[i][0] === 'menu_blockType') { // 屏蔽指定类别 使用单独的设置界面
  83. menu_ID[i] = GM_registerMenuCommand(`#️⃣ ${menu_ALL[i][1]}`, function(){menu_setting('checkbox', menu_ALL[i][1], menu_ALL[i][2], true, [menu_ALL[i+1], menu_ALL[i+2], menu_ALL[i+3], menu_ALL[i+4], menu_ALL[i+5], menu_ALL[i+6], menu_ALL[i+7], menu_ALL[i+8], menu_ALL[i+9]])});
  84. } else if (menu_ALL[i][0].indexOf('menu_blockType') == -1 && menu_ALL[i][0] != 'menu_blockYanXuan') { // 排除使用单独设置界面的 屏蔽指定类别 项
  85. menu_ID[i] = GM_registerMenuCommand(`${menu_ALL[i][3]?'✅':'❌'} ${menu_ALL[i][1]}`, function(){menu_switch(`${menu_ALL[i][3]}`,`${menu_ALL[i][0]}`,`${menu_ALL[i][2]}`)});
  86. }
  87. }
  88. menu_ID[menu_ID.length] = GM_registerMenuCommand('💬 反馈 & 建议', function () {window.GM_openInTab('https://github.com/XIU2/UserScript#xiu2userscript', {active: true,insert: true,setParent: true});window.GM_openInTab('https://greatest.deepsurf.us/zh-CN/scripts/419081/feedback', {active: true,insert: true,setParent: true});});
  89. }
  90.  
  91.  
  92. // 菜单开关
  93. function menu_switch(menu_status, Name, Tips) {
  94. if (menu_status == 'true'){
  95. GM_setValue(`${Name}`, false);
  96. GM_notification({text: `已关闭 [${Tips}] 功能\n(点击刷新网页后生效)`, timeout: 3500, onclick: function(){location.reload();}});
  97. }else{
  98. GM_setValue(`${Name}`, true);
  99. GM_notification({text: `已开启 [${Tips}] 功能\n(点击刷新网页后生效)`, timeout: 3500, onclick: function(){location.reload();}});
  100. }
  101. registerMenuCommand(); // 重新注册脚本菜单
  102. };
  103.  
  104.  
  105. // 返回菜单值
  106. function menu_value(menuName) {
  107. for (let menu of menu_ALL) {
  108. if (menu[0] == menuName) {
  109. return menu[3]
  110. }
  111. }
  112. }
  113.  
  114.  
  115. // 脚本设置
  116. function menu_setting(type, title, tips, line, menu) {
  117. let _br = '', _html = `<style class="zhihuE_SettingStyle">.zhihuE_SettingRoot {position: absolute;top: 50%;left: 50%;-webkit-transform: translate(-50%, -50%);-moz-transform: translate(-50%, -50%);-ms-transform: translate(-50%, -50%);-o-transform: translate(-50%, -50%);transform: translate(-50%, -50%);width: auto;min-width: 400px;max-width: 600px;height: auto;min-height: 150px;max-height: 400px;color: #535353;background-color: #fff;border-radius: 3px;}
  118. .zhihuE_SettingBackdrop_1 {position: fixed;top: 0;right: 0;bottom: 0;left: 0;z-index: 203;display: -webkit-box;display: -ms-flexbox;display: flex;-webkit-box-orient: vertical;-webkit-box-direction: normal;-ms-flex-direction: column;flex-direction: column;-webkit-box-pack: center;-ms-flex-pack: center;justify-content: center;overflow-x: hidden;overflow-y: auto;-webkit-transition: opacity .3s ease-out;transition: opacity .3s ease-out;}
  119. .zhihuE_SettingBackdrop_2 {position: absolute;top: 0;right: 0;bottom: 0;left: 0;z-index: 0;background-color: rgba(18,18,18,.65);-webkit-transition: background-color .3s ease-out;transition: background-color .3s ease-out;}
  120. .zhihuE_SettingRoot .zhihuE_SettingHeader {padding: 10px 20px;color: #fff;font-weight: bold;background-color: #3994ff;border-radius: 3px 3px 0 0;}
  121. .zhihuE_SettingRoot .zhihuE_SettingMain {padding: 10px 20px;border-radius: 0 0 3px 3px;}
  122. .zhihuE_SettingHeader span {float: right;cursor: pointer;}
  123. .zhihuE_SettingMain input {margin: 10px 6px 10px 0;cursor: pointer;vertical-align:middle}
  124. .zhihuE_SettingMain label {margin-right: 20px;user-select: none;cursor: pointer;vertical-align:middle}
  125. .zhihuE_SettingMain hr {border: 0.5px solid #f4f4f4;}
  126. [data-theme="dark"] .zhihuE_SettingRoot {color: #adbac7;background-color: #343A44;}
  127. [data-theme="dark"] .zhihuE_SettingHeader {color: #d0d0d0;background-color: #2D333B;}
  128. [data-theme="dark"] .zhihuE_SettingMain hr {border: 0.5px solid #2d333b;}</style>
  129. <div class="zhihuE_SettingBackdrop_1"><div class="zhihuE_SettingBackdrop_2"></div><div class="zhihuE_SettingRoot">
  130. <div class="zhihuE_SettingHeader">${title}<span class="zhihuE_SettingClose" title="点击关闭"><svg class="Zi Zi--Close Modal-closeIcon" fill="currentColor" viewBox="0 0 24 24" width="24" height="24"><path d="M13.486 12l5.208-5.207a1.048 1.048 0 0 0-.006-1.483 1.046 1.046 0 0 0-1.482-.005L12 10.514 6.793 5.305a1.048 1.048 0 0 0-1.483.005 1.046 1.046 0 0 0-.005 1.483L10.514 12l-5.208 5.207a1.048 1.048 0 0 0 .006 1.483 1.046 1.046 0 0 0 1.482.005L12 13.486l5.207 5.208a1.048 1.048 0 0 0 1.483-.006 1.046 1.046 0 0 0 .005-1.482L13.486 12z" fill-rule="evenodd"></path></svg></span></div>
  131. <div class="zhihuE_SettingMain"><p>${tips}</p><hr>`
  132. if (line) _br = '<br>'
  133. for (let i=0; i<menu.length; i++) {
  134. if (GM_getValue(menu[i][0])) {
  135. _html += `<label><input name="zhihuE_Setting" type="checkbox" value="${menu[i][0]}" checked="checked">${menu[i][1]}</label>${_br}`
  136. } else {
  137. _html += `<label><input name="zhihuE_Setting" type="checkbox" value="${menu[i][0]}">${menu[i][1]}</label>${_br}`
  138. }
  139. }
  140. _html += `</div></div></div>`
  141. document.body.insertAdjacentHTML('beforeend', _html); // 插入网页末尾
  142. setTimeout(function() { // 延迟 100 毫秒,避免太快
  143. // 关闭按钮 点击事件
  144. document.querySelector('.zhihuE_SettingClose').onclick = function(){this.parentElement.parentElement.parentElement.remove();document.querySelector('.zhihuE_SettingStyle').remove();}
  145. // 点击周围空白处 = 点击关闭按钮
  146. document.querySelector('.zhihuE_SettingBackdrop_2').onclick = function(event){if (event.target == this) {document.querySelector('.zhihuE_SettingClose').click();};}
  147. // 复选框 点击事件
  148. document.getElementsByName('zhihuE_Setting').forEach(function (checkBox) {
  149. checkBox.addEventListener('click', function(){if (this.checked) {GM_setValue(this.value, true);} else {GM_setValue(this.value, false);}});
  150. })
  151. }, 100)
  152. }
  153.  
  154.  
  155. // 添加收起回答观察器
  156. function getCollapsedAnswerObserver() {
  157. if (!window._collapsedAnswerObserver) {
  158. const observer = new MutationObserver(mutations => {
  159. for (const mutation of mutations) {
  160. if (mutation.target.hasAttribute('script-collapsed')) return
  161. // 短的回答
  162. if (mutation.target.classList.contains('RichContent')) {
  163. for (const addedNode of mutation.addedNodes) {
  164. if (addedNode.nodeType != Node.ELEMENT_NODE) continue
  165. if (addedNode.className != 'RichContent-inner') continue
  166. if (addedNode.offsetHeight < 400) break
  167. //console.log('111',addedNode, addedNode.classList, addedNode.classList.contains('RichContent-inner'), addedNode.offsetHeight, addedNode.textContent.length)
  168. const button = mutation.target.querySelector('.ContentItem-actions.Sticky [data-zop-retract-question]');
  169. if (button) {
  170. mutation.target.setAttribute('script-collapsed', '');
  171. button.click();
  172. return
  173. }
  174. }
  175. // 长的回答
  176. } else if (mutation.target.tagName === 'DIV' && !mutation.target.style.cssText && !mutation.target.className) {
  177. if (mutation.target.parentElement.hasAttribute('script-collapsed')) return
  178. //console.log('222',mutation.target, mutation.target.querySelector('.ContentItem-actions.Sticky [data-zop-retract-question]'))
  179. const button = mutation.target.querySelector('.ContentItem-actions.Sticky [data-zop-retract-question]');
  180. if (button) {
  181. mutation.target.parentElement.setAttribute('script-collapsed', '');
  182. button.click();
  183. return
  184. }
  185. }
  186. }
  187. })
  188.  
  189. observer.start = function() {
  190. if (!this._active) {
  191. this.observe(document, { childList: true, subtree: true });
  192. this._active = true;
  193. }
  194. }
  195. observer.end = function() {
  196. if (this._active) {
  197. this.disconnect();
  198. }
  199. }
  200.  
  201. window.addEventListener('urlchange', function() {
  202. observer[location.href.indexOf('/answer/') === -1 ? 'start' : 'end']();
  203. })
  204. window._collapsedAnswerObserver = observer;
  205. }
  206. return window._collapsedAnswerObserver
  207. }
  208.  
  209.  
  210. // 默认收起回答
  211. function defaultCollapsedAnswer() {
  212. if (!menu_value('menu_defaultCollapsedAnswer')) return
  213. const observer = getCollapsedAnswerObserver();
  214. if (location.href.indexOf('/answer/') === -1) {
  215. observer.start();
  216. }
  217. }
  218.  
  219.  
  220. // 一键收起回答+评论(全部)
  221. function collapsedAnswer() {
  222. if (!menu_value('menu_collapsedAnswer')) return
  223. //console.log('1111', document.querySelector('.CornerAnimayedFlex'))
  224. if (document.querySelector('.CornerAnimayedFlex') && !document.getElementById('collapsed-button')) {
  225. // 向网页中插入收起全部回答按钮+样式+绑定点击事件
  226. document.head.appendChild(document.createElement('style')).textContent = '.CornerButton{margin-bottom:8px !important;}.CornerButtons{bottom:45px !important;}';
  227. document.querySelector('.CornerAnimayedFlex').insertAdjacentHTML('afterBegin', '<button id="collapsed-button" data-tooltip="收起全部回答/评论" data-tooltip-position="left" data-tooltip-will-hide-on-click="false" aria-label="收起全部回答/评论" type="button" class="' + document.querySelector('.CornerAnimayedFlex>button').className + '"><svg class="ContentItem-arrowIcon is-active" aria-label="收起全部回答/评论" fill="currentColor" viewBox="0 0 24 24" width="24" height="24"><path d="M16.036 19.59a1 1 0 0 1-.997.995H9.032a.996.996 0 0 1-.997-.996v-7.005H5.03c-1.1 0-1.36-.633-.578-1.416L11.33 4.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.005z"></path></svg></button>');
  228. document.getElementById('collapsed-button').onclick = function () {
  229.  
  230. // 收起所有评论(悬浮的 [收起评论])
  231. document.querySelectorAll('.Comments-container').forEach(function (el) {
  232. let commentCollapseButton = getXpath('//button[text()="收起评论"]', el)
  233. if (commentCollapseButton) commentCollapseButton.click();
  234. });
  235. // 收起所有评论(固定的 [收起评论])
  236. document.querySelectorAll('.RichContent >.ContentItem-actions>button:first-of-type').forEach(function (el) {
  237. if (el.textContent.indexOf('收起评论') > -1) el.click()
  238. });
  239.  
  240. if (location.pathname === '/' || location.pathname === '/hot' || location.pathname === '/follow') {// 对于首页的关注、推荐、热榜
  241. document.querySelectorAll('.ContentItem-rightButton').forEach(function (el) {if (el.hasAttribute('data-zop-retract-question')) {el.click();};});
  242. } else {
  243. // 被 getCollapsedAnswerObserver 函数收起过的,固定 [收起] 按钮
  244. document.querySelectorAll('[script-collapsed]').forEach(function(scriptCollapsed) {scriptCollapsed.querySelectorAll('.ContentItem-actions [data-zop-retract-question], .ContentItem-actions.Sticky [data-zop-retract-question]').forEach(function(button) {button.click();});})
  245. // 被 getCollapsedAnswerObserver 函数收起过的,悬浮 [收起] 按钮(悬浮底部的横栏)
  246. document.querySelectorAll('.RichContent:not([script-collapsed]) .ContentItem-actions.Sticky [data-zop-retract-question]').forEach(function(button) {
  247. let el = button.parentElement;
  248. while (!el.classList.contains('RichContent')) {el = el.parentElement;}
  249. if (el) el.setAttribute('script-collapsed', '');
  250. button.click();
  251. })
  252.  
  253. const observer = getCollapsedAnswerObserver();
  254. observer.start();
  255.  
  256. if (!menu_value('menu_defaultCollapsedAnswer') && !observer._disconnectListener) {
  257. window.addEventListener('urlchange', function() {
  258. observer.end();
  259. window._collapsedAnswerObserver = null;
  260. })
  261. observer._disconnectListener = true;
  262. }
  263. }
  264. }
  265. }
  266. }
  267.  
  268.  
  269. // 收起当前回答、评论(监听点击事件,点击网页两侧空白处)
  270. function collapsedNowAnswer(selectors) {
  271. backToTop(selectors) // 快捷回到顶部
  272. if (!menu_value('menu_collapsedNowAnswer')) return
  273. document.querySelector(selectors).onclick = function(event){
  274. if (event.target == this) {
  275. // 下面这段主要是 [收起回答],顺便 [收起评论](如果展开了的话)
  276. let rightButton = document.querySelector('.ContentItem-actions.Sticky.RichContent-actions.is-fixed.is-bottom')
  277. if (rightButton) { // 悬浮在底部的 [收起回答](此时正在浏览回答内容 [中间区域])
  278. // 固定的 [收起评论](先看看是否展开评论)
  279. let commentCollapseButton = rightButton.querySelector('button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type')
  280. //console.log('111')
  281. if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) commentCollapseButton.click();
  282. // 再去收起回答
  283. rightButton = rightButton.querySelector('.ContentItem-rightButton[data-zop-retract-question]')
  284. //console.log('222')
  285. if (rightButton) rightButton.click();
  286.  
  287. } else { // 固定在回答底部的 [收起回答](此时正在浏览回答内容 [尾部区域])
  288.  
  289. // 悬浮的 [收起评论](此时正在浏览评论内容 [中间区域])
  290. //if (getXpath('//button[text()="收起评论"]',document.querySelector('.Comments-container'))) {getXpath('//button[text()="收起评论"]',document.querySelector('.Comments-container')).click();console.log('asfaf')}
  291.  
  292. let answerCollapseButton_ = false;
  293. for (let el of document.querySelectorAll('.ContentItem-rightButton[data-zop-retract-question]')) { // 遍历所有回答底部的 [收起] 按钮
  294. if (isElementInViewport(el)) { // 判断该 [收起] 按钮是否在可视区域内
  295. // 固定的 [收起评论](先看看是否展开评论,即存在 [收起评论] 按钮)
  296. let commentCollapseButton = el.parentNode.querySelector('button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type')
  297. // 如果展开了评论,就收起评论
  298. //console.log('333')
  299. //if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) commentCollapseButton.click();
  300. if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) {
  301. commentCollapseButton.click();
  302. if (!isElementInViewport(commentCollapseButton)) scrollTo(0,el.offsetTop+50)
  303. }
  304. //console.log('444')
  305. el.click() // 再去收起回答
  306. answerCollapseButton_ = true; // 如果找到并点击收起了,就没必要执行下面的代码了(可视区域中没有 [收起回答] 时)
  307. break
  308. }
  309. }
  310. // 针对完全看不到 [收起回答] 按钮时(如 [头部区域],以及部分明明很长却不显示悬浮横条的回答)
  311. if (!answerCollapseButton_) {
  312. for (let el of document.querySelectorAll('.List-item, .Card.AnswerCard, .Card.TopstoryItem')) { // 遍历所有回答主体元素
  313. if (isElementInViewport_(el)) { // 判断该回答是否在可视区域内
  314. // 固定的 [收起评论](先看看是否展开评论,即存在 [收起评论] 按钮)
  315. let commentCollapseButton = el.querySelector('button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type')
  316. // 如果展开了评论,就收起评论
  317. //console.log('555',commentCollapseButton)
  318. if (commentCollapseButton && commentCollapseButton.textContent.indexOf('收起评论') > -1) {
  319. commentCollapseButton.click();
  320. if (!isElementInViewport(commentCollapseButton)) scrollTo(0,el.offsetTop+50)
  321. }
  322. let answerCollapseButton__ = el.querySelector('.ContentItem-rightButton[data-zop-retract-question]');
  323. //console.log('666')
  324. if (answerCollapseButton__) answerCollapseButton__.click() // 再去收起回答
  325. break
  326. }
  327. }
  328. }
  329. }
  330.  
  331. // 下面这段只针对 [收起评论](如果展开了的话)
  332. let commentCollapseButton_ = false, commentCollapseButton__ = false;
  333. // 悬浮的 [收起评论](此时正在浏览评论内容 [中间区域])
  334. let commentCollapseButton = getXpath('//button[text()="收起评论"]',document.querySelector('.Comments-container'))
  335. if (commentCollapseButton) {
  336. //console.log('777', commentCollapseButton)
  337. commentCollapseButton.click();
  338. } else { // 固定的 [收起评论](此时正在浏览评论内容 [头部区域])
  339. let commentCollapseButton_1 = document.querySelectorAll('.ContentItem-actions > button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type, .ContentItem-action > button.Button.Button--plain.Button--withIcon.Button--withLabel:first-of-type')
  340. if (commentCollapseButton_1.length > 0) {
  341. for (let el of commentCollapseButton_1) {
  342. if (el.textContent.indexOf('收起评论') > -1) {
  343. if (isElementInViewport(el)) {
  344. //console.log('888')
  345. el.click()
  346. commentCollapseButton_ = true // 如果找到并点击了,就没必要执行下面的代码了(可视区域中没有 [收起评论] 时)
  347. break
  348. }
  349. }
  350. }
  351. }
  352. if (commentCollapseButton_ == false) { // 可视区域中没有 [收起评论] 时(此时正在浏览评论内容 [头部区域] + [尾部区域](不上不下的,既看不到固定的 [收起评论] 又看不到悬浮的 [收起评论])),需要判断可视区域中是否存在评论元素
  353. let commentCollapseButton_1 = document.querySelectorAll('.Comments-container')
  354. if (commentCollapseButton_1.length > 0) {
  355. for (let el of commentCollapseButton_1) {
  356. if (isElementInViewport(el)) {
  357. let parentElement = findParentElement(el, 'List-item') || findParentElement(el, 'Card '),
  358. commentCollapseButton = parentElement.querySelector('.ContentItem-actions > button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type')
  359. if (commentCollapseButton.textContent.indexOf('收起评论') > -1) {
  360. //console.log('999')
  361. commentCollapseButton.click()
  362. if (!isElementInViewport(commentCollapseButton)) {console.log(parentElement,parentElement.offsetTop,parentElement.offsetHeight);scrollTo(0,parentElement.offsetTop+parentElement.offsetHeight-50)}
  363. commentCollapseButton__ = true // 如果找到并点击了,就没必要执行下面的代码了(可视区域中没有 评论元素 时)
  364. break
  365. }
  366. }
  367. }
  368. }
  369. if (commentCollapseButton__ == false) { // 如果上面的都没找到,那么就尝试寻找评论末尾的 [评论回复框]
  370. let commentCollapseButton_2 = document.querySelectorAll('.Editable-content')
  371. if (commentCollapseButton_2.length > 0) {
  372. for (let el of commentCollapseButton_2) {
  373. if (isElementInViewport(el)) {
  374. let parentElement = findParentElement(el, 'List-item') || findParentElement(el, 'Card '),
  375. commentCollapseButton = parentElement.querySelector('.ContentItem-actions > button.Button.ContentItem-action.Button--plain.Button--withIcon.Button--withLabel:first-of-type')
  376. //console.log(commentCollapseButton)
  377. if (commentCollapseButton.textContent.indexOf('收起评论') > -1) {
  378. //console.log('101010')
  379. commentCollapseButton.click()
  380. if (!isElementInViewport(commentCollapseButton)) {console.log(parentElement,parentElement.offsetTop,parentElement.offsetHeight);scrollTo(0,parentElement.offsetTop+parentElement.offsetHeight-50)}
  381. break
  382. }
  383. }
  384. }
  385. }
  386. }
  387. }
  388. }
  389. }
  390. }
  391. }
  392.  
  393.  
  394. // 回到顶部(监听点击事件,鼠标右键点击网页两侧空白处)
  395. function backToTop(selectors) {
  396. if (!menu_value('menu_backToTop')) return
  397. document.querySelector(selectors).oncontextmenu = function(event){
  398. if (event.target == this) {
  399. event.preventDefault();
  400. window.scrollTo(0,0)
  401. }
  402. }
  403. }
  404.  
  405.  
  406. //获取元素是否在可视区域(完全可见)
  407. function isElementInViewport(el) {
  408. let rect = el.getBoundingClientRect();
  409. return (
  410. rect.top >= 0 &&
  411. rect.left >= 0 &&
  412. rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
  413. rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  414. );
  415. }
  416. //获取元素是否在可视区域(部分可见)
  417. function isElementInViewport_(el) {
  418. let rect = el.getBoundingClientRect();
  419. return (
  420. rect.top < (window.innerHeight || document.documentElement.clientHeight) &&
  421. rect.bottom > 0
  422. );
  423. }
  424.  
  425.  
  426. // 自定义屏蔽用户
  427. function customBlockUsers() {
  428. let nowBlockUsers = '';
  429. menu_value('menu_customBlockUsers').forEach(function(item){nowBlockUsers += '|' + item})
  430. //console.log(nowBlockUsers.replace('|',''))
  431. let newBlockUsers = prompt('编辑 [自定义屏蔽用户]\n(不同用户名之间使用 "|" 分隔,例如:用户A|用户B|用户C )', nowBlockUsers.replace('|',''));
  432. if (newBlockUsers === '') {
  433. GM_setValue('menu_customBlockUsers', []);
  434. registerMenuCommand(); // 重新注册脚本菜单
  435. } else if (newBlockUsers != null) {
  436. GM_setValue('menu_customBlockUsers', newBlockUsers.split('|'));
  437. registerMenuCommand(); // 重新注册脚本菜单
  438. }
  439. };
  440.  
  441.  
  442. // 屏蔽指定用户
  443. function blockUsers(type) {
  444. if (!menu_value('menu_blockUsers')) return
  445. if (!menu_value('menu_customBlockUsers') || menu_value('menu_customBlockUsers').length < 1) return
  446. switch(type) {
  447. case 'index':
  448. blockUsers_('.Card.TopstoryItem.TopstoryItem-isRecommend', 'Card TopstoryItem TopstoryItem-isRecommend');
  449. break;
  450. case 'question':
  451. blockUsers_question();
  452. break;
  453. case 'search':
  454. blockUsers_search();
  455. break;
  456. case 'topic':
  457. blockUsers_('.List-item.TopicFeedItem', 'List-item TopicFeedItem');
  458. break;
  459. case 'people':
  460. blockUsers_button_people(); // 添加屏蔽用户按钮(用户主页)
  461. break;
  462. }
  463. blockUsers_comment(); // 评论区
  464. blockUsers_button(); // 加入黑名单按钮(用户信息悬浮框中)
  465.  
  466. function blockUsers_(className1, className2) {
  467. // 前几条因为是直接加载的,而不是动态插入网页的,所以需要单独判断
  468. function blockKeywords_now() {
  469. document.querySelectorAll(className1).forEach(function(item1){
  470. let item = item1.querySelector('.ContentItem.AnswerItem, .ContentItem.ArticleItem'); // 用户名所在元素
  471. if (item) {
  472. for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单
  473. if (keyword != '' && item.dataset.zop.indexOf('authorName":"' + keyword + '",') > -1) { // 找到就删除该信息流
  474. console.log('已屏蔽:' + item.dataset.zop);
  475. item1.hidden = true;
  476. break;
  477. }
  478. }
  479. }
  480. })
  481. }
  482.  
  483. blockKeywords_now();
  484. window.addEventListener('urlchange', function(){
  485. setTimeout(blockKeywords_now, 1000); // 网页 URL 变化后再次执行
  486. })
  487.  
  488. // 这个是监听网页插入事件,用来判断后续网页动态插入的元素
  489. const callback = (mutationsList, observer) => {
  490. for (const mutation of mutationsList) {
  491. for (const target of mutation.addedNodes) {
  492. if (target.nodeType != 1) return
  493. if (target.className === className2) {
  494. let item = target.querySelector('.ContentItem.AnswerItem, .ContentItem.ArticleItem'); // 用户名所在元素
  495. if (item) {
  496. for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单
  497. if (keyword != '' && item.dataset.zop.indexOf('authorName":"' + keyword + '",') > -1) { // 找到就删除该信息流
  498. console.log('已屏蔽:' + item.dataset.zop);
  499. target.hidden = true;
  500. break;
  501. }
  502. }
  503. }
  504. }
  505. }
  506. }
  507. };
  508. const observer = new MutationObserver(callback);
  509. observer.observe(document, { childList: true, subtree: true });
  510. }
  511.  
  512.  
  513. function blockUsers_question() {
  514. const blockUsers_question_ = (mutationsList, observer) => {
  515. for (const mutation of mutationsList) {
  516. for (const target of mutation.addedNodes) {
  517. if (target.nodeType != 1) return
  518. if (target.className === 'List-item' || target.className === 'Card AnswerCard') {
  519. let item1 = target.querySelector('.ContentItem.AnswerItem');
  520. if (item1) {
  521. menu_value('menu_customBlockUsers').forEach(function(item2){ // 遍历用户黑名单
  522. if (item1.dataset.zop.indexOf('authorName":"' + item2 + '",') > -1) { // 找到就删除该回答
  523. console.log('已屏蔽:' + item1.dataset.zop)
  524. target.hidden = true;
  525. }
  526. })
  527. }
  528. }
  529. }
  530. }
  531. };
  532.  
  533. const blockUsers_question_answer_ = (mutationsList, observer) => {
  534. for (const mutation of mutationsList) {
  535. for (const target of mutation.addedNodes) {
  536. if (target.nodeType != 1) return
  537. target.querySelectorAll('.List-item, .Card.AnswerCard').forEach(function(item){
  538. let item1 = item.querySelector('.ContentItem.AnswerItem');
  539. if (item1) {
  540. menu_value('menu_customBlockUsers').forEach(function(item2){ // 遍历用户黑名单
  541. if (item1.dataset.zop.indexOf('authorName":"' + item2 + '",') > -1) { // 找到就删除该回答
  542. console.log('已屏蔽:' + item1.dataset.zop)
  543. item.hidden = true;
  544. }
  545. })
  546. }
  547. })
  548. }
  549. }
  550. };
  551.  
  552. if (location.pathname.indexOf('/answer/') > -1) { // 回答页(就是只有三个回答的页面)
  553. const observer = new MutationObserver(blockUsers_question_answer_);
  554. observer.observe(document, { childList: true, subtree: true });
  555. } else { // 问题页(可以显示所有回答的页面)
  556. const observer = new MutationObserver(blockUsers_question_);
  557. observer.observe(document, { childList: true, subtree: true });
  558. }
  559.  
  560. // 针对的是打开网页后直接加载的前面几个回答(上面哪些是针对动态加载的回答)
  561. document.querySelectorAll('.List-item, .Card.AnswerCard').forEach(function(item){
  562. let item1 = item.querySelector('.ContentItem.AnswerItem');
  563. if (item1) {
  564. menu_value('menu_customBlockUsers').forEach(function(item2){ // 遍历用户黑名单
  565. if (item1.dataset.zop.indexOf('authorName":"' + item2 + '",') > -1) { // 找到就删除该回答
  566. console.log('已屏蔽:' + item1.dataset.zop)
  567. item.hidden = true;
  568. }
  569. })
  570. }
  571. })
  572. }
  573.  
  574. function blockUsers_search() {
  575. function blockUsers_now() {
  576. if (location.search.indexOf('type=content') === -1) return // 目前只支持搜索页的 [综合]
  577. document.querySelectorAll('.Card.SearchResult-Card[data-za-detail-view-path-module="AnswerItem"], .Card.SearchResult-Card[data-za-detail-view-path-module="PostItem"]').forEach(function(item1){
  578. let item = item1.querySelector('.RichText.ztext.CopyrightRichText-richText b'); // 用户名所在元素
  579. if (item) {
  580. for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单
  581. if (keyword != '' && item.textContent === keyword) { // 找到就删除该信息流
  582. console.log('已屏蔽:' + item.textContent);
  583. item1.hidden = true;
  584. break;
  585. }
  586. }
  587. }
  588. })
  589. }
  590.  
  591. setTimeout(blockUsers_now, 2000);
  592. window.addEventListener('urlchange', function(){
  593. setTimeout(blockUsers_now, 1000); // 网页 URL 变化后再次执行
  594. })
  595.  
  596. const callback = (mutationsList, observer) => {
  597. if (location.search.indexOf('type=content') === -1) return // 目前只支持搜索页的 [综合]
  598. for (const mutation of mutationsList) {
  599. for (const target of mutation.addedNodes) {
  600. if (target.nodeType != 1) return
  601. let item = target.querySelector('.Card.SearchResult-Card[data-za-detail-view-path-module="AnswerItem"] .RichText.ztext.CopyrightRichText-richText b, .Card.SearchResult-Card[data-za-detail-view-path-module="PostItem"] .RichText.ztext.CopyrightRichText-richText b');
  602. if (item) {
  603. for (const keyword of menu_value('menu_customBlockUsers')) { // 遍历用户名黑名单
  604. if (keyword != '' && item.textContent === keyword) { // 找到就删除该信息流
  605. console.log('已屏蔽:' + item.textContent);
  606. target.hidden = true;
  607. break;
  608. }
  609. }
  610. }
  611. }
  612. }
  613. };
  614. const observer = new MutationObserver(callback);
  615. observer.observe(document, { childList: true, subtree: true });
  616. }
  617.  
  618. function blockUsers_comment() {
  619. const callback = (mutationsList, observer) => {
  620. for (const mutation of mutationsList) {
  621. for (const target of mutation.addedNodes) {
  622. if (target.nodeType != 1) return
  623. //console.log(target)
  624. if (target.tagName == 'DIV' && target.className.indexOf('css-') == 0 && target.dataset.id == undefined) {
  625. let item = target.querySelector('a[href^="https://www.zhihu.com/people/"]>img.Avatar[alt][loading]')
  626. if (item) {
  627. //console.log(item)
  628. menu_value('menu_customBlockUsers').forEach(function(item1){ // 遍历用户黑名单
  629. if (item.alt === item1) { // 找到就删除该搜索结果
  630. //console.log(item.alt,item1)
  631. item.parentElement.parentElement.parentElement.parentElement.style.display = "none";
  632. }
  633. })
  634.  
  635. // 添加屏蔽用户按钮(点赞、回复等按钮后面)
  636. /*if (item) {
  637. let footer = findParentElement(item, 'CommentItemV2-meta', true).parentElement.querySelector('.CommentItemV2-metaSibling > .CommentItemV2-footer'),
  638. userid = item.parentElement;
  639. if (userid && footer && !footer.lastElementChild.dataset.name) {
  640. userid = userid.href.split('/')[4];
  641. footer.insertAdjacentHTML('beforeend',`<button type="button" data-name="${item.alt}" data-userid="${userid}" class="Button CommentItemV2-hoverBtn Button--plain"><span style="display: inline-flex; align-items: center;">&#8203;<svg class="Zi Zi--Like" fill="currentColor" viewBox="0 0 24 24" width="16" height="16" style="transform: rotate(180deg); margin-right: 5px;"><path d="M18.376 5.624c-3.498-3.499-9.254-3.499-12.752 0-3.499 3.498-3.499 9.254 0 12.752 3.498 3.499 9.254 3.499 12.752 0 3.499-3.498 3.499-9.14 0-12.752zm-1.693 1.693c2.37 2.37 2.596 6.094.678 8.69l-9.367-9.48c2.708-1.919 6.32-1.58 8.69.79zm-9.48 9.48c-2.37-2.37-2.595-6.095-.676-8.69l9.48 9.48c-2.822 1.918-6.433 1.58-8.803-.79z" fill-rule="evenodd"></path></svg></span>屏蔽用户</button>`);
  642. footer.lastElementChild.onclick = function(){blockUsers_button_add(this.dataset.name, this.dataset.userid, false)}
  643. }
  644. }*/
  645. }
  646. }
  647. }
  648. }
  649. };
  650. const observer = new MutationObserver(callback);
  651. observer.observe(document, { childList: true, subtree: true });
  652. }
  653.  
  654.  
  655. // 添加屏蔽用户按钮(用户信息悬浮框中)
  656. function blockUsers_button() {
  657. const callback = (mutationsList, observer) => {
  658. for (const mutation of mutationsList) {
  659. for (const target of mutation.addedNodes) {
  660. if (target.nodeType != 1) return
  661. //console.log(target, target.className)
  662. if (target.tagName == 'DIV' && target.className && (target.className.indexOf('css-') == 0 || target.style == 'opacity: 1;')) {
  663. const item = target.querySelector('.MemberButtonGroup.ProfileButtonGroup.HoverCard-buttons'),
  664. item1 = target.querySelector('img.Avatar+div span.UserLink>a.UserLink-link[data-za-detail-view-element_name=User]');
  665. if (item1) {
  666. const name = item1.textContent, userid = item1.href.split('/')[4], users = menu_value('menu_customBlockUsers');
  667. for (let num = 0;num<users.length;num++) { // 判断是否已存在
  668. if (users[num] === name) { // 已存在
  669. target.querySelectorAll('.Button.Button--primary.Button--red').forEach(function(item){item.style.display = 'none';}) // 隐藏知乎自带的已屏蔽按钮
  670. item.insertAdjacentHTML('afterbegin', `<button type="button" data-name="${name}" data-userid="${userid}" class="Button FollowButton Button--primary Button--red"><span style="display: inline-flex; align-items: center;">​<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" class="Zi Zi--Ban" fill="currentColor"><path fill-rule="evenodd" d="M16.346 18.113a7.5 7.5 0 0 1-10.46-10.46l10.46 10.46Zm1.767-1.767L7.654 5.886a7.5 7.5 0 0 1 10.46 10.46ZM22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Z" clip-rule="evenodd"></path></svg></span> 已屏蔽</button>`);
  671. item.firstElementChild.onclick = function(){this.disabled = true;blockUsers_button_del(this.dataset.name, this.dataset.userid, false)}
  672. return
  673. }
  674. };
  675. if (item && !target.querySelector('button[data-name][data-userid]')) {
  676. item.insertAdjacentHTML('beforeend', `<button type="button" data-name="${name}" data-userid="${userid}" class="Button FollowButton Button--primary Button--red" style="width: 100%;margin: 7px 0 0 0;"><span style="display: inline-flex; align-items: center;">​<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" class="Zi Zi--Ban" fill="currentColor"><path fill-rule="evenodd" d="M16.346 18.113a7.5 7.5 0 0 1-10.46-10.46l10.46 10.46Zm1.767-1.767L7.654 5.886a7.5 7.5 0 0 1 10.46 10.46ZM22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Z" clip-rule="evenodd"></path></svg></span> 屏蔽用户</button>`);
  677. item.lastElementChild.onclick = function(){this.disabled = true;blockUsers_button_add(this.dataset.name, this.dataset.userid, false)}
  678. }
  679. }
  680. }
  681. }
  682. }
  683. };
  684. const observer = new MutationObserver(callback);
  685. observer.observe(document, { childList: true, subtree: true });
  686. }
  687.  
  688. // 添加屏蔽用户按钮(用户主页)
  689. function blockUsers_button_people() {
  690. let item = document.querySelector('.MemberButtonGroup.ProfileButtonGroup.ProfileHeader-buttons'), // 获取按钮元素位置
  691. name = document.querySelector('.ProfileHeader-name').firstChild.textContent, // 获取用户名
  692. users = menu_value('menu_customBlockUsers'), // 读取屏蔽列表
  693. userid = location.href.split('/')[4];
  694. for (let num = 0;num<users.length;num++) { // 判断是否已存在
  695. if (users[num] === name) { // 已存在
  696. document.querySelectorAll('.Button.Button--primary.Button--red').forEach(function(item){item.style.display = 'none';}) // 隐藏知乎自带的已屏蔽按钮
  697. item.insertAdjacentHTML('afterbegin', `<button type="button" data-name="${name}" data-userid="${userid}" class="Button FollowButton Button--primary Button--red" style="margin: 0 0 0 12px;"><span style="display: inline-flex; align-items: center;">​<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" class="Zi Zi--Ban" fill="currentColor"><path fill-rule="evenodd" d="M16.346 18.113a7.5 7.5 0 0 1-10.46-10.46l10.46 10.46Zm1.767-1.767L7.654 5.886a7.5 7.5 0 0 1 10.46 10.46ZM22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Z" clip-rule="evenodd"></path></svg></span> 已屏蔽</button>`);
  698. item.firstElementChild.onclick = function(){this.disabled = true;blockUsers_button_del(this.dataset.name, this.dataset.userid, true)}
  699. return
  700. }
  701. };
  702. if (item) {
  703. item.insertAdjacentHTML('beforeend', `<button type="button" data-name="${name}" data-userid="${userid}" class="Button FollowButton Button--primary Button--red" style="margin: 0 0 0 12px;"><span style="display: inline-flex; align-items: center;">​<svg width="1.2em" height="1.2em" viewBox="0 0 24 24" class="Zi Zi--Ban" fill="currentColor"><path fill-rule="evenodd" d="M16.346 18.113a7.5 7.5 0 0 1-10.46-10.46l10.46 10.46Zm1.767-1.767L7.654 5.886a7.5 7.5 0 0 1 10.46 10.46ZM22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Z" clip-rule="evenodd"></path></svg></span> 屏蔽用户</button>`);
  704. item.lastElementChild.onclick = function(){this.disabled = true;blockUsers_button_add(this.dataset.name, this.dataset.userid, true)}
  705. }
  706. }
  707.  
  708. // 屏蔽用户按钮绑定事件(添加)
  709. function blockUsers_button_add(name, userid, reload) {
  710. if (!name || !userid) return
  711. let users = menu_value('menu_customBlockUsers'), // 读取屏蔽列表
  712. index = users.indexOf(name);
  713. if (index === -1) {
  714. users.push(name); // 追加用户名
  715. GM_setValue('menu_customBlockUsers', users); // 写入屏蔽列表
  716. // 加入知乎自带的黑名单(和本脚本互补~
  717. GM_xmlhttpRequest({url: `https://www.zhihu.com/api/v4/members/${userid}/actions/block`,method: 'POST',timeout: 2000});
  718. // 是否刷新本页
  719. if (reload) {
  720. setTimeout(function(){location.reload()}, 200); // 刷新网页,延迟 200 毫秒,避免知乎反应慢~
  721. } else {
  722. GM_notification({text: `该用户已被屏蔽~\n刷新网页后生效~`, timeout: 3000});
  723. }
  724. } else {
  725. GM_notification({text: `该用户已经被屏蔽啦,无需重复屏蔽~`, timeout: 3000});
  726. }
  727. }
  728.  
  729.  
  730. // 屏蔽用户按钮绑定事件(删除)
  731. function blockUsers_button_del(name, userid, reload) {
  732. if (!name || !userid) return
  733. let users = menu_value('menu_customBlockUsers'), // 读取屏蔽列表
  734. index = users.indexOf(name);
  735. if (index > -1) {
  736. users.splice(index, 1); // 移除用户名
  737. GM_setValue('menu_customBlockUsers', users); // 写入屏蔽列表
  738. // 移除知乎自带的黑名单
  739. GM_xmlhttpRequest({url: `https://www.zhihu.com/api/v4/members/${userid}/actions/block`,method: 'DELETE',timeout: 2000});
  740. // 是否刷新本页
  741. if (reload) {
  742. setTimeout(function(){location.reload()}, 200); // 刷新网页,延迟 200 毫秒,避免知乎反应慢~
  743. } else {
  744. GM_notification({text: `该用户已取消屏蔽啦~\n刷新网页后生效~`, timeout: 3000});
  745. }
  746. } else {
  747. GM_notification({text: `没有在屏蔽列表中找到该用户...`, timeout: 3000});
  748. }
  749. }
  750. }
  751.  
  752.  
  753. // 自定义屏蔽关键词(标题)
  754. function customBlockKeywords() {
  755. let nowBlockKeywords = '';
  756. menu_value('menu_customBlockKeywords').forEach(function(item){nowBlockKeywords += '|' + item})
  757. let newBlockKeywords = prompt('编辑 [自定义屏蔽关键词]\n(不同关键词之间使用 "|" 分隔,例如:关键词A|关键词B|关键词C \n(关键词不区分大小写,支持表情如:[捂脸]|[飙泪笑]', nowBlockKeywords.replace('|',''));
  758. if (newBlockKeywords === '') {
  759. GM_setValue('menu_customBlockKeywords', []);
  760. registerMenuCommand(); // 重新注册脚本菜单
  761. } else if (newBlockKeywords != null) {
  762. GM_setValue('menu_customBlockKeywords', newBlockKeywords.split('|'));
  763. registerMenuCommand(); // 重新注册脚本菜单
  764. }
  765. };
  766.  
  767.  
  768. // 屏蔽指定关键词
  769. function blockKeywords(type) {
  770. if (!menu_value('menu_blockKeywords')) return
  771. if (!menu_value('menu_customBlockKeywords') || menu_value('menu_customBlockKeywords').length < 1) return
  772. switch(type) {
  773. case 'index':
  774. blockKeywords_('.Card.TopstoryItem.TopstoryItem-isRecommend', 'Card TopstoryItem TopstoryItem-isRecommend');
  775. break;
  776. case 'follow':
  777. blockKeywords_('.Card.TopstoryItem.TopstoryItem-isFollow', 'Card TopstoryItem TopstoryItem-isFollow');
  778. break;
  779. case 'topic':
  780. blockKeywords_('.List-item.TopicFeedItem', 'List-item TopicFeedItem');
  781. break;
  782. case 'people':
  783. blockKeywords_('.List-item', 'List-item');
  784. break;
  785. case 'collection':
  786. blockKeywords_('.Card.CollectionDetailPageItem', 'Card CollectionDetailPageItem');
  787. break;
  788. case 'search':
  789. blockKeywords_search();
  790. break;
  791. case 'comment':
  792. if (!menu_value('menu_blockKeywordsComment')) return // 如果 [屏蔽关键词 - 评论区] 未启用则跳过
  793. blockKeywords_comment();
  794. break;
  795. }
  796.  
  797.  
  798. function blockKeywords_(className1, className2) {
  799. // 前几条因为是直接加载的,而不是动态插入网页的,所以需要单独判断
  800. function blockKeywords_now() {
  801. if (location.pathname === '/hot') {
  802. document.querySelectorAll('.HotItem').forEach(function(item1){blockKeywords_1(item1, 'h2.HotItem-title');})
  803. } else {
  804. document.querySelectorAll(className1).forEach(function(item1){blockKeywords_1(item1, 'h2.ContentItem-title meta[itemprop="name"], meta[itemprop="headline"]');})
  805. }
  806. }
  807.  
  808. blockKeywords_now();
  809. window.addEventListener('urlchange', function(){
  810. setTimeout(blockKeywords_now, 1000); // 网页 URL 变化后再次执行
  811. })
  812.  
  813. // 这个是监听网页插入事件,用来判断后续网页动态插入的元素
  814. const callback = (mutationsList, observer) => {
  815. for (const mutation of mutationsList) {
  816. for (const target of mutation.addedNodes) {
  817. if (target.nodeType != 1) return
  818. if (target.className === className2) {blockKeywords_1(target, 'h2.ContentItem-title meta[itemprop="name"], meta[itemprop="headline"]');}
  819. }
  820. }
  821. };
  822. const observer = new MutationObserver(callback);
  823. observer.observe(document, { childList: true, subtree: true });
  824. }
  825.  
  826.  
  827. function blockKeywords_search() {
  828. function blockKeywords_now() {
  829. if (location.search.indexOf('type=content') === -1) return // 目前只支持搜索页的 [综合]
  830. document.querySelectorAll('.HotLanding-contentItem, .Card.SearchResult-Card[data-za-detail-view-path-module="AnswerItem"], .Card.SearchResult-Card[data-za-detail-view-path-module="PostItem"]').forEach(function(item1){blockKeywords_1(item1, 'a[data-za-detail-view-id]');})
  831. }
  832.  
  833. setTimeout(blockKeywords_now, 2000);
  834. window.addEventListener('urlchange', function(){
  835. setTimeout(blockKeywords_now, 1000); // 网页 URL 变化后再次执行
  836. })
  837.  
  838. const callback = (mutationsList, observer) => {
  839. if (location.search.indexOf('type=content') === -1) return // 目前只支持搜索页的 [综合]
  840. for (const mutation of mutationsList) {
  841. for (const target of mutation.addedNodes) {
  842. if (target.nodeType != 1) return
  843. //console.log(target)
  844. if (target.tagName === 'DIV' && target.className === '') {
  845. let tt = target.querySelector('div[class="Card SearchResult-Card"][data-za-detail-view-path-module="AnswerItem"], div[class="Card SearchResult-Card"][data-za-detail-view-path-module="PostItem"]')
  846. if (tt) {blockKeywords_1(target.childNodes[0], 'a[data-za-detail-view-id]');}
  847. }
  848. }
  849. }
  850. };
  851. const observer = new MutationObserver(callback);
  852. observer.observe(document, { childList: true, subtree: true });
  853. }
  854.  
  855.  
  856. function blockKeywords_comment() {
  857. function filterComment(comment) {
  858. let content = comment.querySelector('.CommentContent'); // 寻找评论文字所在元素
  859. let text = content.textContent.toLowerCase(); // 全部转为小写(用来不区分大小写)
  860. content.querySelectorAll('img.sticker[alt]').forEach((img)=>{text += img.alt}) // 将评论中的表情添加到待遍历的评论文字中
  861.  
  862. let keywords = menu_value('menu_customBlockKeywords');
  863. for (const keyword of keywords) { // 遍历关键词黑名单
  864. if (keyword != '' && text.indexOf(keyword.toLowerCase()) > -1) { // 找到就删除该评论
  865. console.log('已屏蔽评论:' + text);
  866. content.dataset.text = content.innerHTML
  867. content.onclick = (e)=>{if (e.target.dataset.text) {e.target.innerHTML = e.target.dataset.text;e.target.removeAttribute('data-text');}}
  868. content.textContent = '[该评论已屏蔽,可点击显示]';
  869. }
  870. }
  871. }
  872.  
  873. const callback = (mutationsList, observer) => {
  874. for (const mutation of mutationsList) {
  875. for (const target of mutation.addedNodes) {
  876. if (target.nodeType != 1) return
  877. //console.log(target);
  878. if (target.tagName == 'DIV' && target.className.indexOf('css-') == 0 && target.dataset.id == undefined) {
  879. let item = target.querySelector('a[href^="https://www.zhihu.com/people/"]>img.Avatar[alt][loading]')
  880. if (item) {
  881. //console.log(item)
  882. filterComment(item.parentElement.parentElement.parentElement.parentElement)
  883. }
  884. }
  885.  
  886. /*if (target.tagName == 'DIV' && target.dataset.id !== undefined) {
  887. console.log(target);
  888. for (const node of target.querySelectorAll('*')) {
  889. if (node.className === 'CommentItemV2-metaSibling') filterComment(node);
  890. }
  891. }*/
  892. }
  893. }
  894. };
  895. const observer = new MutationObserver(callback);
  896. observer.observe(document, { childList: true, subtree: true });
  897. }
  898.  
  899. function blockKeywords_1(item1, css) {
  900. let item = item1.querySelector(css); // 标题所在元素
  901. //console.log(item)
  902. if (item) {
  903. for (const keyword of menu_value('menu_customBlockKeywords')) { // 遍历关键词黑名单
  904. let text = item.content || item.textContent;
  905. //console.log(text,keyword)
  906. if (keyword != '' && text.toLowerCase().indexOf(keyword.toLowerCase()) > -1) { // 找到就删除该信息流
  907. console.log('已屏蔽:' + text);
  908. item1.hidden = true;
  909. item1.style.display = 'none';
  910. break;
  911. }
  912. }
  913. }
  914. }
  915. }
  916.  
  917.  
  918. // 屏蔽指定类别(视频/文章等)
  919. function blockType(type) {
  920. let name;
  921. // 一开始加载的信息流 + 添加标签样式
  922. if (type === 'search') { // 搜索页
  923. if (!menu_value('menu_blockTypeVideo') && !menu_value('menu_blockTypeArticle') && !menu_value('menu_blockTypePin') && !menu_value('menu_blockTypeTopic') && !menu_value('menu_blockTypeSearch')) return
  924. if (menu_value('menu_blockTypeSearch') && location.pathname === '/search') setTimeout(function(){document.querySelectorAll('.RelevantQuery').forEach((r)=>{r.parentElement.parentElement.hidden = true});}, 2000)
  925. name = 'h2.ContentItem-title a:not(.zhihu_e_toQuestion), a.KfeCollection-PcCollegeCard-link, h2.SearchTopicHeader-Title a'
  926. addSetInterval_(name);
  927. } else if (type === 'question') { // 问题页
  928. if (!menu_value('menu_blockTypeVideo')) return
  929. document.lastChild.appendChild(document.createElement('style')).textContent = `.VideoAnswerPlayer, .VideoAnswerPlayer video, .VideoAnswerPlayer-video, .VideoAnswerPlayer-iframe {display: none !important;}`;
  930. name = '.VideoAnswerPlayer'
  931. document.querySelectorAll(name).forEach(function(item){blockType_(item);})
  932. } else if (type === 'follow') { // 首页 - 关注
  933. if (!menu_value('menu_blockTypeFollowAgree') && !menu_value('menu_blockTypeFollowQuestion')) return
  934. if (menu_value('menu_blockTypeFollowAgree')) name = '.TopstoryItem-isFollow .FeedSource-byline' // 赞同了XX
  935. if (menu_value('menu_blockTypeFollowQuestion')) {if (name) {name += ',.ContentItem[data-za-detail-view-path-module=QuestionItem]:not(.AnswerItem):not(.PinItem)'} else {name = '.ContentItem[data-za-detail-view-path-module=QuestionItem]:not(.AnswerItem):not(.PinItem)'}} // 关注了XX
  936. if (!name) return
  937. document.querySelectorAll(name).forEach(function(item){blockType_(item);})
  938. } else { // 首页
  939. if (!menu_value('menu_blockTypeVideo') && !menu_value('menu_blockTypeArticle') && !menu_value('menu_blockTypePin')) return
  940. if (menu_value('menu_blockTypeVideo')) document.lastChild.appendChild(document.createElement('style')).textContent = `.Card .ZVideoItem-video, .VideoAnswerPlayer video, nav.TopstoryTabs > a[aria-controls="Topstory-zvideo"] {display: none !important;}`;
  941. name = 'h2.ContentItem-title a:not(.zhihu_e_toQuestion)'
  942. if (menu_value('menu_blockTypePin')) name = 'h2.ContentItem-title a:not(.zhihu_e_toQuestion), .ContentItem.PinItem'
  943. document.querySelectorAll(name).forEach(function(item){blockType_(item);})
  944. }
  945.  
  946. // 后续加载的信息流
  947. const observer = new MutationObserver(mutationsList => {
  948. for (const mutation of mutationsList) {
  949. for (const target of mutation.addedNodes) {
  950. if (target.nodeType != 1) return
  951. if (target.className === "Card SearchResult-Card" && target.dataset.zaDetailViewPathModule === undefined) {
  952. // 移除相关搜索
  953. if (menu_value('menu_blockTypeSearch') && location.pathname === '/search' && location.search.indexOf('type=content') > -1) target.hidden = true;
  954. } else {
  955. blockType_(target.querySelector(name));
  956. }
  957. }
  958. }
  959. });
  960. observer.observe(document, { childList: true, subtree: true });
  961.  
  962. window.addEventListener('urlchange', function(){
  963. addSetInterval_(name);
  964. // 移除相关搜索
  965. if (menu_value('menu_blockTypeSearch') && location.pathname === '/search' && location.search.indexOf('type=content') > -1) setTimeout(function(){document.querySelectorAll('.RelevantQuery').forEach((r)=>{r.parentElement.parentElement.hidden = true});}, 1500)
  966. })
  967.  
  968. function blockType_(titleA) {
  969. if (!titleA) return // 判断是否为真
  970. //console.log(titleA.href)
  971. if (location.pathname === '/search') { // 搜索页
  972. if (location.search.indexOf('type=content') === -1) return // 仅限搜索页的 [综合]
  973. if (titleA.href.indexOf('/zvideo/') > -1 || titleA.href.indexOf('video.zhihu.com') > -1) { // 如果是视频
  974. if (menu_value('menu_blockTypeVideo')) findParentElement(titleA, 'Card').remove();
  975. } else if (titleA.href.indexOf('zhuanlan.zhihu.com') > -1) { // 如果是文章
  976. if (menu_value('menu_blockTypeArticle')) findParentElement(titleA, 'Card SearchResult-Card').hidden = true;
  977. } else if (titleA.href.indexOf('/topic/') > -1) { // 如果是话题
  978. if (menu_value('menu_blockTypeTopic')) findParentElement(titleA, 'Card SearchResult-Card').hidden = true;
  979. } else if (titleA.href.indexOf('/market/') > -1) { // 如果是杂志文章等乱七八糟的
  980. if (menu_value('menu_blockTypeSearch')) findParentElement(titleA, 'Card SearchResult-Card').hidden = true;
  981. }
  982. } else if (location.pathname.indexOf('/question/') > -1) { // 问题页
  983. if (menu_value('menu_blockTypeVideo')) findParentElement(titleA, 'List-item').hidden = true;
  984. } else if (location.pathname.indexOf('/follow') > -1) { // 首页 - 关注
  985. if (type === 'follow') {
  986. if ((menu_value('menu_blockTypeFollowAgree') && titleA.className.indexOf('FeedSource-byline') != -1) || (menu_value('menu_blockTypeFollowQuestion') && titleA.dataset.zaDetailViewPathModule == 'QuestionItem')) findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isFollow').hidden = true; // 赞同了XX + 关注了XX
  987. }
  988. if (titleA.className == 'ContentItem PinItem' && menu_value('menu_blockTypePin')) findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isFollow').hidden = true; // 如果是想法
  989. } else { // 首页
  990. if (titleA.className == 'ContentItem PinItem') { // 如果是想法(针对无标题)
  991. if (menu_value('menu_blockTypePin')) findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isRecommend').hidden = true;
  992. /*} else if (titleA.href.indexOf('/pin/') > -1) { // 如果是想法
  993. if (menu_value('menu_blockTypePin')) findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isRecommend').hidden = true;*/
  994. } else if (titleA.href.indexOf('/zvideo/') > -1 || titleA.href.indexOf('video.zhihu.com') > -1) { // 如果是视频
  995. if (menu_value('menu_blockTypeVideo')) {findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isRecommend').hidden = true;}
  996. } else if (titleA.href.indexOf('/answer/') > -1) { // 如果是问题(视频回答)
  997. if (findParentElement(titleA, 'ContentItem AnswerItem').querySelector('.VideoAnswerPlayer')) {
  998. if (menu_value('menu_blockTypeVideo')) {findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isRecommend').hidden = true; findParentElement(titleA, 'ContentItem AnswerItem').remove();}
  999. }
  1000. } else if (titleA.href.indexOf('/education/video-course/') > -1) { // 如果是视频课程
  1001. if (menu_value('menu_blockTypeVideo')) {findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isRecommend').hidden = true;}
  1002. } else if (titleA.href.indexOf('zhuanlan.zhihu.com') > -1) { // 如果是文章
  1003. if (menu_value('menu_blockTypeArticle')) findParentElement(titleA, 'Card TopstoryItem TopstoryItem-isRecommend').hidden = true;
  1004. }
  1005. }
  1006. }
  1007.  
  1008. function addSetInterval_(A) {
  1009. let timer = setInterval(function(){
  1010. let aTag = document.querySelectorAll(A);
  1011. if (aTag.length > 0) {
  1012. clearInterval(timer);
  1013. aTag.forEach(function(item){blockType_(item);})
  1014. }
  1015. });
  1016. }
  1017. }
  1018.  
  1019.  
  1020. // 寻找父元素
  1021. function findParentElement(item, className, type = false) {
  1022. if (item.parentElement) {
  1023. //console.log(item.parentElement)
  1024. if (type) { // true = 完全一致,false = 包含即可
  1025. if (item.parentElement.className && item.parentElement.className === className) {
  1026. //console.log(item.parentElement.className)
  1027. return item.parentElement;
  1028. } else {
  1029. let temp = findParentElement(item.parentElement, className, true)
  1030. if (temp) return temp
  1031. }
  1032. } else {
  1033. if (item.parentElement.className && item.parentElement.className.indexOf(className) > -1) {
  1034. return item.parentElement;
  1035. } else {
  1036. let temp = findParentElement(item.parentElement, className)
  1037. if (temp) return temp
  1038. }
  1039. }
  1040. }
  1041. return
  1042. }
  1043.  
  1044.  
  1045. // 移除高亮链接
  1046. function cleanHighlightLink() {
  1047. if (!menu_value('menu_cleanHighlightLink')) return;
  1048. const callback = (mutationsList, observer) => {
  1049. for (const mutation of mutationsList) {
  1050. for (const target of mutation.addedNodes) {
  1051. if (target.nodeType != 1 || target.tagName != 'A') break
  1052. if (target.dataset.zaNotTrackLink && target.href.indexOf('https://zhida.zhihu.com/search?') > -1) {
  1053. target.parentElement.replaceWith(target.textContent);
  1054. }
  1055. }
  1056. }
  1057. };
  1058. const observer = new MutationObserver(callback);
  1059. observer.observe(document, { childList: true, subtree: true });
  1060.  
  1061. // 针对的是打开网页后直接加载的前面几个回答(上面哪些是针对动态加载的回答)
  1062. document.querySelectorAll('span > a[data-za-not-track-link][href^="https://zhida.zhihu.com/search?"]').forEach(e => e.parentElement.replaceWith(e.textContent))
  1063. }
  1064.  
  1065.  
  1066. // 屏蔽盐选内容
  1067. function blockYanXuan() {
  1068. if (!menu_value('menu_blockYanXuan')) return
  1069. const blockYanXuan_question = (mutationsList, observer) => {
  1070. for (const mutation of mutationsList) {
  1071. for (const target of mutation.addedNodes) {
  1072. if (target.nodeType != 1) return
  1073. if (target.className === 'List-item' || target.className === 'Card AnswerCard') {
  1074. if (target.querySelector('.KfeCollection-AnswerTopCard-Container, .KfeCollection-PurchaseBtn')) {
  1075. target.hidden = true;
  1076. }
  1077. }
  1078. }
  1079. }
  1080. };
  1081.  
  1082. const blockYanXuan_question_answer = (mutationsList, observer) => {
  1083. for (const mutation of mutationsList) {
  1084. for (const target of mutation.addedNodes) {
  1085. if (target.nodeType != 1) return
  1086. target.querySelectorAll('.List-item, .Card.AnswerCard').forEach(function(item){
  1087. if (item.querySelector('.KfeCollection-AnswerTopCard-Container, .KfeCollection-PurchaseBtn')) {
  1088. item.hidden = true;
  1089. }
  1090. })
  1091. }
  1092. }
  1093. };
  1094.  
  1095. if (location.pathname.indexOf('/answer/') > -1) { // 回答页(就是只有三个回答的页面)
  1096. const observer = new MutationObserver(blockYanXuan_question_answer);
  1097. observer.observe(document, { childList: true, subtree: true });
  1098. } else { // 问题页(可以显示所有回答的页面)
  1099. const observer = new MutationObserver(blockYanXuan_question);
  1100. observer.observe(document, { childList: true, subtree: true });
  1101. }
  1102.  
  1103. // 针对的是打开网页后直接加载的前面几个回答(上面哪些是针对动态加载的回答)
  1104. document.querySelectorAll('.List-item, .Card.AnswerCard').forEach(function(item){
  1105. if (item.querySelector('.KfeCollection-AnswerTopCard-Container, .KfeCollection-PurchaseBtn')) {
  1106. item.hidden = true;
  1107. }
  1108. })
  1109. }
  1110.  
  1111.  
  1112. // 区分问题文章
  1113. function addTypeTips() {
  1114. if (!menu_value('menu_typeTips')) return
  1115. let style = `font-weight: bold;font-size: 13px;padding: 1px 4px 0;border-radius: 2px;display: inline-block;vertical-align: top;margin: ${(location.pathname === '/search') ? '2' : '4'}px 4px 0 0;`
  1116. document.body.appendChild(document.createElement('style')).textContent = `/* 区分问题文章 */
  1117. .AnswerItem .ContentItem-title a:not(.zhihu_e_toQuestion)::before {content:'问题';color: #f68b83;background-color: #f68b8333;${style}}
  1118. /* 针对的是部分搜索词下搜索页开头的 "最新讨论" 之类的非常规元素 */
  1119. .HotLanding-contentItem .ContentItem[data-za-detail-view-path-module=Content] .ContentItem-title a:not(.zhihu_e_toQuestion)::before {content:'问题';color: #f68b83;background-color: #f68b8333;${style}}
  1120. .TopstoryQuestionAskItem .ContentItem-title a:not(.zhihu_e_toQuestion)::before {content:'问题';color: #ff5a4e;background-color: #ff5a4e33;${style}}
  1121. .ZVideoItem .ContentItem-title a::before, .ZvideoItem .ContentItem-title a::before {content:'视频';color: #00BCD4;background-color: #00BCD433;${style}}
  1122. .PinItem .ContentItem-title a::before {content:'想法';color: #4CAF50;background-color: #4CAF5033;${style}}
  1123. .ArticleItem .ContentItem-title a::before {content:'文章';color: #2196F3;background-color: #2196F333;${style}}`;
  1124. }
  1125.  
  1126.  
  1127. // 直达问题按钮
  1128. function addToQuestion() {
  1129. if (!menu_value('menu_toQuestion')) return
  1130.  
  1131. // 一开始加载的信息流 + 添加按钮样式
  1132. if (location.pathname === '/search') {
  1133. document.lastChild.appendChild(document.createElement('style')).textContent = `a.zhihu_e_toQuestion {font-size: 13px !important;font-weight: normal !important;padding: 1px 6px 0 !important;border-radius: 2px !important;display: inline-block !important;vertical-align: top !important;height: 20.67px !important;line-height: 20.67px !important;margin-top: 2px !important;}`;
  1134. addSetInterval_('h2.ContentItem-title a:not(.zhihu_e_tips)');
  1135. } else {
  1136. document.lastChild.appendChild(document.createElement('style')).textContent = `a.zhihu_e_toQuestion {font-size: 13px !important;font-weight: normal !important;padding: 1px 6px 0 !important;border-radius: 2px !important;display: inline-block !important;vertical-align: top !important;margin-top: 4px !important;}`;
  1137. document.querySelectorAll('h2.ContentItem-title a:not(.zhihu_e_tips)').forEach(function(item){addTypeTips_(item);})
  1138. }
  1139.  
  1140. // 后续加载的信息流
  1141. const observer = new MutationObserver(mutationsList => {
  1142. for (const mutation of mutationsList) {
  1143. for (const target of mutation.addedNodes) {
  1144. if (target.nodeType != 1) return
  1145. addTypeTips_(target.querySelector('h2.ContentItem-title a:not(.zhihu_e_tips)'));
  1146. }
  1147. }
  1148. });
  1149. observer.observe(document, { childList: true, subtree: true });
  1150.  
  1151. window.addEventListener('urlchange', function(){
  1152. addSetInterval_('h2.ContentItem-title a:not(.zhihu_e_tips)');
  1153. })
  1154.  
  1155. function addTypeTips_(titleA) {
  1156. if (!titleA) return // 判断是否为真
  1157. if (titleA.parentElement.querySelector('a.zhihu_e_toQuestion')) return // 判断是否已添加
  1158. if (titleA.textContent.indexOf('?') != -1) { // 把问题末尾英文问好 [?] 的替换为中文问好 [?],这样按钮与标题之间的间距就刚刚好~
  1159. titleA.innerHTML = titleA.innerHTML.replace('?', "?")
  1160. }
  1161. if (/answer\/\d+/.test(titleA.href)) { // 如果是指向回答的问题(而非指向纯问题的链接)
  1162. const titleA_meta = titleA.parentElement.parentElement.querySelector('meta[itemprop="url"]'); // 获取该问题页地址
  1163. if (!titleA_meta) return // 判断元素是否存在(针对的是部分搜索词下搜索页开头的 "最新讨论" 之类的非常规元素)
  1164. titleA.insertAdjacentHTML('afterend', `<a class="zhihu_e_toQuestion VoteButton" href="${titleA_meta.content}" target="_blank">直达问题</a>`);
  1165. }
  1166. }
  1167.  
  1168. function addSetInterval_(A) {
  1169. let timer = setInterval(function(){
  1170. let aTag = document.querySelectorAll(A);
  1171. if (aTag.length > 0) {
  1172. clearInterval(timer);
  1173. aTag.forEach(function(item){addTypeTips_(item);})
  1174. }
  1175. });
  1176. }
  1177. }
  1178.  
  1179.  
  1180. // 展开问题描述
  1181. function questionRichTextMore() {
  1182. if (!menu_value('menu_questionRichTextMore')) return
  1183. let button = document.querySelector('button.QuestionRichText-more');
  1184. if (button) button.click()
  1185. }
  1186.  
  1187.  
  1188. // 净化标题消息
  1189. function cleanTitles() {
  1190. if (!menu_value('menu_cleanTitles')) return
  1191.  
  1192. // 方案一
  1193. const elTitle = document.head.querySelector('title');
  1194. const original = elTitle.textContent;
  1195. const observer = new MutationObserver(function() {
  1196. if (elTitle.textContent != original) { // 避免重复执行
  1197. elTitle.textContent = original;
  1198. }
  1199. });
  1200. observer.observe(elTitle, { childList: true });
  1201.  
  1202. // 方案二
  1203. // if (Reflect.getOwnPropertyDescriptor(document, 'title')) {
  1204. // const elTitle = document.head.querySelector('title');
  1205. // const original = elTitle.textContent;
  1206. // const observer = new MutationObserver(function() {
  1207. // if (elTitle.textContent != original) { // 避免重复执行
  1208. // elTitle.textContent = original;
  1209. // }
  1210. // });
  1211. // observer.observe(elTitle, { childList: true });
  1212. // } else {
  1213. // const title = document.title;
  1214. // Reflect.defineProperty(document, 'title', {
  1215. // set: () => {},
  1216. // get: () => title,
  1217. // });
  1218. // }
  1219. }
  1220.  
  1221.  
  1222. // 净化搜索热门
  1223. function cleanSearch() {
  1224. if (!menu_value('menu_cleanSearch')) return
  1225.  
  1226. const el = document.querySelector('.SearchBar-input > input');
  1227. const observer = new MutationObserver((mutationsList, observer) => {
  1228. if (mutationsList[0].attributeName === 'placeholder' && mutationsList[0].target.placeholder != '') mutationsList[0].target.placeholder = '';
  1229. });
  1230. el.placeholder = '';
  1231. observer.observe(el, { attributes: true });
  1232. document.documentElement.appendChild(document.createElement('style')).textContent = '.AutoComplete-group > .SearchBar-label:not(.SearchBar-label--history), .AutoComplete-group > [id^="AutoComplete2-topSearch-"], .AutoComplete-group > [id^="AutoComplete3-topSearch-"] {display: none !important;}';
  1233. }
  1234.  
  1235.  
  1236. // 快捷关闭悬浮评论(监听点击事件,点击网页两侧空白处)
  1237. function closeFloatingComments() {
  1238. const closeFloatingCommentsModal = (mutationsList, observer) => {
  1239. for (const mutation of mutationsList) {
  1240. for (const target of mutation.addedNodes) {
  1241. if (target.nodeType != 1) return
  1242. let button = document.querySelector('button[aria-label="关闭"]');
  1243. if (button) {button.parentElement.parentElement.onclick = function(event){if (event.target.parentElement == this) {button.click();}}}
  1244. }
  1245. }
  1246. };
  1247. const observer = new MutationObserver(closeFloatingCommentsModal);
  1248. observer.observe(document, { childList: true, subtree: true });
  1249. }
  1250.  
  1251.  
  1252. // 监听 XMLHttpRequest 事件
  1253. /*function EventXMLHttpRequest() {
  1254. var _send = window.XMLHttpRequest.prototype.send
  1255. function sendReplacement(data) {
  1256. addTypeTips();
  1257. return _send.apply(this, arguments);
  1258. }
  1259. window.XMLHttpRequest.prototype.send = sendReplacement;
  1260. }*/
  1261.  
  1262.  
  1263. // 自定义 urlchange 事件(用来监听 URL 变化)
  1264. function addUrlChangeEvent() {
  1265. history.pushState = ( f => function pushState(){
  1266. var ret = f.apply(this, arguments);
  1267. window.dispatchEvent(new Event('pushstate'));
  1268. window.dispatchEvent(new Event('urlchange'));
  1269. return ret;
  1270. })(history.pushState);
  1271.  
  1272. history.replaceState = ( f => function replaceState(){
  1273. var ret = f.apply(this, arguments);
  1274. window.dispatchEvent(new Event('replacestate'));
  1275. window.dispatchEvent(new Event('urlchange'));
  1276. return ret;
  1277. })(history.replaceState);
  1278.  
  1279. window.addEventListener('popstate',()=>{
  1280. window.dispatchEvent(new Event('urlchange'))
  1281. });
  1282. }
  1283.  
  1284.  
  1285. function getXpath(xpath, contextNode, doc = document) {
  1286. contextNode = contextNode || doc;
  1287. try {
  1288. const result = doc.evaluate(xpath, contextNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
  1289. // 应该总是返回一个元素节点
  1290. return result.singleNodeValue && result.singleNodeValue.nodeType === 1 && result.singleNodeValue;
  1291. } catch (err) {
  1292. throw new Error(`无效 Xpath: ${xpath}`);
  1293. }
  1294. }
  1295.  
  1296.  
  1297. // 显示问题作者
  1298. function question_author() {
  1299. if (document.querySelector('.BrandQuestionSymbol, .QuestionAuthor')) return
  1300. let qJson = JSON.parse(document.querySelector('#js-initialData').textContent).initialState.entities.questions[/\d+/.exec(location.pathname)[0]].author,
  1301. html = `<div class="BrandQuestionSymbol"><a class="BrandQuestionSymbol-brandLink" href="/people/${qJson.urlToken}"><img role="presentation" src="${qJson.avatarUrl}" class="BrandQuestionSymbol-logo" alt=""><span class="BrandQuestionSymbol-name">${qJson.name}</span></a><div class="BrandQuestionSymbol-divider" style="margin-left: 5px;margin-right: 10px;"></div></div>`;
  1302. //html = `<div class="QuestionAuthor"><div class="AuthorInfo AuthorInfo--plain" itemprop="author" itemscope="" itemtype="http://schema.org/Person"><div class="AuthorInfo"><span class="UserLink AuthorInfo-avatarWrapper"><div class="Popover"><div id="Popover18-toggle" aria-haspopup="true" aria-expanded="false" aria-owns="Popover18-content"><a class="UserLink-link" data-za-detail-view-element_name="User" target="_blank" href="${qJson.urlToken}"><img class="Avatar AuthorInfo-avatar" width="24" height="24" src="${qJson.avatarUrl}"></a></div></div></span><div class="AuthorInfo-content"><div class="AuthorInfo-head"><span class="UserLink AuthorInfo-name"><div class="Popover"><div id="Popover19-toggle" aria-haspopup="true" aria-expanded="false" aria-owns="Popover19-content"><a class="UserLink-link" data-za-detail-view-element_name="User" target="_blank" href="${qJson.urlToken}">${qJson.name}</a></div></div></span></div></div></div></div></div>`
  1303. document.querySelector('.QuestionHeader-topics').insertAdjacentHTML('beforebegin', html);
  1304. //document.querySelector('.QuestionPage h1.QuestionHeader-title').insertAdjacentHTML('afterend', html);
  1305. }
  1306.  
  1307.  
  1308. // [完整显示时间 + 置顶显示时间] 功能修改自:https://greatest.deepsurf.us/scripts/402808(从 JQuery 改为原生 JavaScript,且精简、优化了代码)
  1309. // 完整显示时间 + 置顶显示时间
  1310. function topTime_(css, classs) {
  1311. document.querySelectorAll(css).forEach(function(_this) {
  1312. let t = _this.querySelector('.ContentItem-time'); if (!t) return
  1313. if (!(t.classList.contains('full')) && t.querySelector('span') && t.querySelector('span').textContent != null) {
  1314. // 完整显示时间
  1315. topTime_allTime(t)
  1316. // 发布时间置顶
  1317. topTime_publishTop(t, _this, classs)
  1318. }
  1319. });
  1320. }
  1321.  
  1322.  
  1323. // 完整显示时间 + 置顶显示时间 - 文章
  1324. function topTime_post() {
  1325. let t = document.querySelector('.ContentItem-time:not(.xiu-time)'); if (!t) return
  1326. // 完整显示时间
  1327. if (t.textContent.indexOf('编辑于') > -1 && !(t.classList.contains('xiu-time'))) {
  1328. let tt = t.textContent;
  1329. t.click();
  1330. t.textContent = (t.textContent + ' ,' + tt)
  1331. t.classList.add('xiu-time');
  1332. }
  1333.  
  1334. // 置顶显示时间
  1335. if (menu_value('menu_publishTop') && !(document.querySelector('.Post-Header > .ContentItem-time')) && !(document.querySelector('.ContentItem-meta > .ContentItem-time'))) {
  1336. let temp_time = t.cloneNode(true);
  1337. temp_time.style.padding = '0px';
  1338. document.querySelector('.Post-Header').insertAdjacentElement('beforeEnd', temp_time);
  1339. }
  1340. }
  1341.  
  1342.  
  1343. // 完整显示时间
  1344. function topTime_allTime(t) {
  1345. if (t.textContent.indexOf('发布于') > -1 && t.textContent.indexOf('编辑于') == -1) {
  1346. t.querySelector('span').textContent = (t.querySelector('span').dataset.tooltip);
  1347. t.classList.add('full');
  1348. } else if (t.textContent.indexOf('发布于') == -1 && t.textContent.indexOf('编辑于') > -1) {
  1349. t.querySelector('span').textContent = (t.querySelector('span').dataset.tooltip) + ' ,' + (t.querySelector('span').textContent);
  1350. t.classList.add('full');
  1351. }
  1352. }
  1353.  
  1354.  
  1355. // 置顶显示时间
  1356. function topTime_publishTop(t, _this, _class) {
  1357. if (!menu_value('menu_publishTop')) return
  1358. if (!t.parentNode.classList.contains(_class)) {
  1359. let temp_time = t.cloneNode(true);
  1360. temp_time.style.padding = '0px';
  1361. // 对于较短的回答,隐藏回答底部的时间
  1362. if (_this.offsetHeight < 600) t.style.display = 'none';
  1363. _this.querySelector('.' + _class).insertAdjacentElement('beforeEnd', temp_time);
  1364. }
  1365. }
  1366.  
  1367.  
  1368. // 问题创建时间
  1369. function question_time() {
  1370. if (!(document.querySelector('.QuestionPage .QuestionHeader-side .QuestionTime-xiu'))) {
  1371. document.querySelector('.QuestionPage .QuestionHeader-side').insertAdjacentHTML('beforeEnd', '<div class="QuestionTime-xiu" style="color: #9098ac; margin-top: 5px; font-size: 13px; font-style: italic;"><p>创建时间:' + getUTC8(new Date(document.querySelector('.QuestionPage > meta[itemprop=dateCreated]').content)) + '</p><p>最后编辑:' + getUTC8(new Date(document.querySelector('.QuestionPage > meta[itemprop=dateModified]').content)) + '</p></div>');
  1372. }
  1373. }
  1374.  
  1375.  
  1376. // UTC 标准时转 UTC+8 北京时间,修改自:https://greatest.deepsurf.us/zh-CN/scripts/402808(精简)
  1377. function getUTC8(t) {
  1378. return (t.getFullYear() + '-' + (((t.getMonth() + 1) < 10) ? ('0' + (t.getMonth() + 1)) : (t.getMonth() + 1)) + '-' + ((t.getDate() < 10) ? ('0' + t.getDate()) : t.getDate()) + '\xa0\xa0' + ((t.getHours() < 10) ? ('0' + t.getHours()) : t.getHours()) + ':' + ((t.getMinutes() < 10) ? ('0' + t.getMinutes()) : t.getMinutes()) + ':' + ((t.getSeconds() < 10) ? ('0' + t.getSeconds()) : t.getSeconds()));
  1379. }
  1380.  
  1381.  
  1382. // 默认高清原图(无水印)
  1383. function originalPic(){
  1384. document.querySelectorAll('img[data-original][data-original-token][data-lazy-status]:not([data-original-xiu]):not(.comment_sticker):not(.Avatar)').forEach(function(one){one.src = 'https://' + one.dataset.original.split('/')[2] + '/' + one.dataset.originalToken + '.webp'; one.dataset.originalXiu = 'true';});
  1385. }
  1386.  
  1387.  
  1388. // 默认站外直链,修改自:https://greatest.deepsurf.us/scripts/402808(从 JQuery 改为原生 JavaScript,且精简、优化了代码)
  1389. function directLink () {
  1390. document.querySelectorAll('a.external[href*="link.zhihu.com/?target="], a.LinkCard[href*="link.zhihu.com/?target="]:not(.MCNLinkCard):not(.ZVideoLinkCard):not(.ADLinkCardContainer)').forEach(function (_this) {_this.href = decodeURIComponent(_this.href.substring(_this.href.indexOf('link.zhihu.com/?target=') + 23));});
  1391. }
  1392.  
  1393.  
  1394. // 默认折叠邀请,修改自:https://greatest.deepsurf.us/scripts/402808(从 JQuery 改为原生 JavaScript,且精简、优化了代码)
  1395. function questionInvitation(){
  1396. let time = setInterval(function(){
  1397. let q = document.querySelector('.QuestionInvitation-content'); if (!q) return
  1398. clearInterval(time);
  1399. q.style.display = 'none';
  1400. document.querySelector('.QuestionInvitation-title').innerHTML = document.querySelector('.QuestionInvitation-title').innerText + '<span style="cursor: pointer; font-size: 14px; color: #919aae;"> 展开/折叠</span>'
  1401. // 点击事件(展开/折叠)
  1402. document.querySelector('.Topbar').onclick = function(){
  1403. let q = document.querySelector('.QuestionInvitation-content')
  1404. if (q.style.display == 'none') {
  1405. q.style.display = ''
  1406. } else {
  1407. q.style.display = 'none'
  1408. }
  1409. }
  1410. });
  1411. }
  1412.  
  1413. // 屏蔽热榜杂项
  1414. function blockHotOther() {
  1415. if (!menu_value('menu_blockTypeLiveHot')) return;
  1416.  
  1417. const isQuestionItem = (hotItem) => {
  1418. const linkItem = hotItem.querySelector('.HotItem-content a');
  1419. if (linkItem === null) return false;
  1420. return /\/question\/\d+/.test(linkItem.href);
  1421. }
  1422.  
  1423. const block = () => {
  1424. removeLiveItems();
  1425. fixItemRank();
  1426. };
  1427.  
  1428. // 移除非问题的内容
  1429. const removeLiveItems = () => {
  1430. const hotItems = document.querySelectorAll('.HotList-list .HotItem');
  1431. for (const item of hotItems) {
  1432. if (!isQuestionItem(item)) item.remove();
  1433. }
  1434. }
  1435.  
  1436. // 修复排行榜序号
  1437. const fixItemRank = () => {
  1438. const hotItems = document.querySelectorAll('.HotList-list .HotItem:not([hidden])');
  1439. hotItems.forEach((item, index) => {
  1440. const rank = item.querySelector('.HotItem-index .HotItem-rank');
  1441. if (rank !== null) rank.innerText = index + 1;
  1442. });
  1443. }
  1444.  
  1445. const blockLive_content = (mutationsList, observer) => {
  1446. for (const mutation of mutationsList) {
  1447. for (const target of mutation.addedNodes) {
  1448. if (target.classList.contains('.HotItem')) {
  1449. block();
  1450. }
  1451. }
  1452. }
  1453. }
  1454.  
  1455. const observer = new MutationObserver(blockLive_content);
  1456. observer.observe(document, { childList: true, subtree: true });
  1457.  
  1458. // 初始移除
  1459. block();
  1460. }
  1461.  
  1462.  
  1463. (function() {
  1464. if (window.onurlchange === undefined) {addUrlChangeEvent();} // Tampermonkey v4.11 版本添加的 onurlchange 事件 grant,可以监控 pjax 等网页的 URL 变化
  1465. window.addEventListener('urlchange', function(){ // 针对的是从单个回答页跳转到完整回答页时
  1466. if (location.pathname.indexOf('question') > -1 && location.pathname.indexOf('waiting') === -1 && location.pathname.indexOf('/answer/') === -1) { // 回答页 //
  1467. setTimeout(function(){
  1468. collapsedNowAnswer('.QuestionPage'); // 收起当前回答 + 快捷返回顶部
  1469. collapsedNowAnswer('.Question-main'); // 收起当前回答 + 快捷返回顶部
  1470. questionRichTextMore(); // 展开问题描述
  1471. blockUsers('question'); // 屏蔽指定用户
  1472. blockYanXuan(); // 屏蔽盐选内容
  1473. }, 300);
  1474. } else if (location.pathname == '/') { // 推荐
  1475. setTimeout(()=>{
  1476. blockUsers('index'); // 屏蔽指定用户
  1477. blockKeywords('index'); // 屏蔽指定关键词
  1478. blockType(); // 屏蔽指定类别(视频/文章等)
  1479. }, 500);
  1480. } else if (location.pathname == '/hot') { // 热榜
  1481. setTimeout(()=>{
  1482. blockKeywords('index'); // 屏蔽指定关键词
  1483. blockHotOther(); // 移除热播杂项
  1484. }, 500);
  1485. } else if (location.pathname == '/follow') { // 关注
  1486. setTimeout(()=>{
  1487. blockKeywords('follow'); // 屏蔽指定关键词
  1488. blockType(); // 屏蔽指定类别(视频/文章等)
  1489. blockType('follow'); // 屏蔽指定类别(赞同了XX/关注了XX等)
  1490. }, 500);
  1491. }
  1492. })
  1493.  
  1494. cleanTitles(); // 净化标题消息,不能延迟执行
  1495. // Violentmonkey 比 Tampermonkey 加载更早,会导致一些元素还没加载,因此需要延迟一会儿
  1496. // Tampermonkey 4.18.0 版本可能需要延迟一会执行
  1497. if (GM_info.scriptHandler === 'Violentmonkey' || (GM_info.scriptHandler === 'Tampermonkey' && parseFloat(GM_info.version.slice(0,4)) >= 4.18)) {
  1498. setTimeout(start, 300);
  1499. } else {
  1500. start();
  1501. }
  1502.  
  1503. function start(){
  1504. cleanHighlightLink(); // 移除高亮链接
  1505. originalPic();directLink(); // 先立即执行一次
  1506. setInterval(originalPic,500); // 默认高清原图(无水印)
  1507. setInterval(directLink, 500); // 默认站外直链
  1508. if (location.hostname != 'zhuanlan.zhihu.com') {
  1509. if (location.pathname.indexOf('/column/') === -1) cleanSearch(); //净化搜索热门
  1510. collapsedAnswer(); // 一键收起回答
  1511. }
  1512. closeFloatingComments(); // 快捷关闭悬浮评论(监听点击事件,点击网页两侧空白处)
  1513. blockKeywords('comment'); // 屏蔽指定关键词(评论)
  1514.  
  1515.  
  1516. if (location.pathname.indexOf('question') > -1 && location.href.indexOf('/log') == -1) { // 回答页 //
  1517. if (location.pathname.indexOf('waiting') == -1) {
  1518. collapsedNowAnswer('.QuestionPage'); // 收起当前回答 + 快捷返回顶部
  1519. collapsedNowAnswer('.Question-main'); // 收起当前回答 + 快捷返回顶部
  1520. questionRichTextMore(); // 展开问题描述
  1521. blockUsers('question'); // 屏蔽指定用户
  1522. blockYanXuan(); // 屏蔽盐选内容
  1523. blockType('question'); // 屏蔽指定类别(视频/文章等)
  1524. defaultCollapsedAnswer(); // 默认收起回答
  1525. }
  1526. setInterval(function(){topTime_('.ContentItem.AnswerItem', 'ContentItem-meta')}, 300); // 置顶显示时间
  1527. setTimeout(function(){question_time(); question_author()}, 100); //问题创建时间 + 显示问题作者
  1528. questionInvitation(); // 默认折叠邀请
  1529.  
  1530. } else if (location.pathname === '/search') { // 搜索结果页 //
  1531. collapsedNowAnswer('main div'); // 收起当前回答 + 快捷返回顶部
  1532. collapsedNowAnswer('.Search-container'); // 收起当前回答 + 快捷返回顶部
  1533. setInterval(function(){topTime_('.ContentItem.AnswerItem, .ContentItem.ArticleItem', 'SearchItem-meta')}, 300); // 置顶显示时间
  1534. addTypeTips(); // 区分问题文章
  1535. addToQuestion(); // 直达问题按钮
  1536. blockUsers('search'); // 屏蔽指定用户
  1537. blockKeywords('search'); // 屏蔽指定关键词
  1538. blockType('search'); // 屏蔽指定类别(视频/文章等)
  1539.  
  1540.  
  1541. } else if (location.pathname.indexOf('/topic/') > -1) { // 话题页 //
  1542. if (location.pathname.indexOf('/hot') > -1 || location.href.indexOf('/top-answers') > -1) { // 仅限 [讨论] [精华]
  1543. collapsedNowAnswer('main.App-main'); // 收起当前回答 + 快捷返回顶部
  1544. setInterval(function(){topTime_('.ContentItem.AnswerItem, .ContentItem.ArticleItem', 'ContentItem-meta')}, 300); // 置顶显示时间
  1545. addTypeTips(); // 区分问题文章
  1546. addToQuestion(); // 直达问题按钮
  1547. blockUsers('topic'); // 屏蔽指定用户
  1548. blockKeywords('topic'); // 屏蔽指定关键词
  1549. }
  1550.  
  1551. } else if (location.hostname === 'zhuanlan.zhihu.com'){ // 文章 //
  1552. backToTop('.Post-content'); // 快捷返回顶部
  1553. backToTop('.Post-Row-Content'); // 快捷返回顶部
  1554. setTimeout(topTime_post, 300); // 置顶显示时间
  1555. blockUsers(); // 屏蔽指定用户
  1556.  
  1557.  
  1558. } else if (location.pathname.indexOf('/column/') > -1) { // 专栏 //
  1559. setTimeout(function(){
  1560. collapsedAnswer(); // 一键收起回答
  1561. collapsedNowAnswer('main div'); // 收起当前回答 + 快捷返回顶部
  1562. setInterval(function(){topTime_('.ContentItem.AnswerItem, .ContentItem.ArticleItem', 'ContentItem-meta')}, 300); // 置顶显示时间
  1563. blockUsers(); // 屏蔽指定用户
  1564. }, 300);
  1565.  
  1566.  
  1567. } else if (location.pathname.indexOf('/people/') > -1 || location.href.indexOf('org') > -1) { // 用户主页 //
  1568. if (location.pathname.split('/').length === 3) addTypeTips();addToQuestion(); // 区分问题文章、直达问题按钮
  1569. collapsedNowAnswer('main div'); // 收起当前回答 + 快捷返回顶部
  1570. collapsedNowAnswer('.Profile-main'); // 收起当前回答 + 快捷返回顶部
  1571. setInterval(function(){topTime_('.ContentItem.AnswerItem, .ContentItem.ArticleItem', 'ContentItem-meta')}, 300); // 置顶显示时间
  1572. blockUsers('people'); // 屏蔽指定用户
  1573. blockKeywords('people'); // 屏蔽指定关键词
  1574.  
  1575.  
  1576. } else if (location.pathname.indexOf('/collection/') > -1) { // 收藏夹 //
  1577. addTypeTips(); // 区分问题文章
  1578. addToQuestion(); // 直达问题按钮
  1579. collapsedNowAnswer('main'); // 收起当前回答 + 快捷返回顶部
  1580. collapsedNowAnswer('.CollectionsDetailPage'); // 收起当前回答 + 快捷返回顶部
  1581. setInterval(function(){topTime_('.ContentItem.AnswerItem, .ContentItem.ArticleItem', 'ContentItem-meta')}, 300); // 置顶显示时间
  1582. blockKeywords('collection'); // 屏蔽指定关键词
  1583.  
  1584. } else if (location.pathname.indexOf('/pin/') > -1) { // 想法 //
  1585. backToTop('main[role=main]'); // 快捷返回顶部
  1586. setInterval(function(){topTime_('.ContentItem.PinItem', 'ContentItem-meta')}, 300); // 置顶显示时间
  1587.  
  1588. } else { // 首页 //
  1589. // 解决屏蔽类别后,因为首页信息流太少而没有滚动条导致无法加载更多内容的问题
  1590. document.lastElementChild.appendChild(document.createElement('style')).textContent = '.Topstory-container {min-height: 1500px;}';
  1591. if (menu_value('menu_blockTypeVideo')) document.lastChild.appendChild(document.createElement('style')).textContent = `.Card .ZVideoItem-video, nav.TopstoryTabs > a[aria-controls="Topstory-zvideo"] {display: none !important;}`;
  1592.  
  1593. collapsedNowAnswer('main div'); // 收起当前回答 + 快捷返回顶部
  1594. collapsedNowAnswer('.Topstory-container'); // 收起当前回答 + 快捷返回顶部
  1595. setInterval(function(){topTime_('.TopstoryItem', 'ContentItem-meta')}, 300); // 置顶显示时间
  1596. addTypeTips(); // 区分问题文章
  1597. addToQuestion(); // 直达问题按钮
  1598. if (location.pathname == '/') { // 推荐
  1599. blockUsers('index'); // 屏蔽指定用户
  1600. blockKeywords('index'); // 屏蔽指定关键词
  1601. blockType(); // 屏蔽指定类别(视频/文章等)
  1602. } else if (location.pathname == '/hot') { // 热榜
  1603. blockKeywords('index'); // 屏蔽指定关键词
  1604. blockHotOther(); // 屏蔽热榜杂项
  1605. } else if (location.pathname == '/follow') { // 关注
  1606. blockKeywords('follow'); // 屏蔽指定关键词
  1607. blockType(); // 屏蔽指定类别(视频/文章等)
  1608. blockType('follow'); // 屏蔽指定类别(赞同了XX/关注了XX等)
  1609. } else {
  1610. blockUsers();
  1611. }
  1612. }
  1613. }
  1614. })();