CSDN优化

支持手机端和PC端,屏蔽广告,优化浏览体验,自动跳转拦截的URL

当前为 2024-06-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name CSDN优化
  3. // @namespace https://github.com/WhiteSevs/TamperMonkeyScript
  4. // @version 2024.6.6.9
  5. // @author WhiteSevs
  6. // @description 支持手机端和PC端,屏蔽广告,优化浏览体验,自动跳转拦截的URL
  7. // @license GPL-3.0-only
  8. // @icon https://www.csdn.net/favicon.ico
  9. // @supportURL https://github.com/WhiteSevs/TamperMonkeyScript/issues
  10. // @match *://*.csdn.net/*
  11. // @require https://update.gf.qytechs.cn/scripts/494167/1376186/CoverUMD.js
  12. // @require https://update.gf.qytechs.cn/scripts/456485/1384984/pops.js
  13. // @require https://cdn.jsdelivr.net/npm/qmsg@1.1.0/dist/index.umd.js
  14. // @require https://cdn.jsdelivr.net/npm/@whitesev/utils@1.3.9/dist/index.umd.js
  15. // @require https://cdn.jsdelivr.net/npm/@whitesev/domutils@1.1.1/dist/index.umd.js
  16. // @grant GM_addStyle
  17. // @grant GM_cookie
  18. // @grant GM_deleteValue
  19. // @grant GM_getValue
  20. // @grant GM_info
  21. // @grant GM_registerMenuCommand
  22. // @grant GM_setValue
  23. // @grant GM_unregisterMenuCommand
  24. // @grant GM_xmlhttpRequest
  25. // @grant unsafeWindow
  26. // @run-at document-start
  27. // ==/UserScript==
  28.  
  29. (function (Qmsg, DOMUtils, Utils) {
  30. 'use strict';
  31.  
  32. var _a;
  33. var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)();
  34. var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  35. var _GM_info = /* @__PURE__ */ (() => typeof GM_info != "undefined" ? GM_info : void 0)();
  36. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  37. var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  38. var _GM_unregisterMenuCommand = /* @__PURE__ */ (() => typeof GM_unregisterMenuCommand != "undefined" ? GM_unregisterMenuCommand : void 0)();
  39. var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  40. var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
  41. var _monkeyWindow = /* @__PURE__ */ (() => window)();
  42. const _SCRIPT_NAME_ = "CSDN优化";
  43. const utils = Utils.noConflict();
  44. const domutils = DOMUtils.noConflict();
  45. const pops = _monkeyWindow.pops || _unsafeWindow.pops;
  46. const log = new utils.Log(
  47. _GM_info,
  48. _unsafeWindow.console || _monkeyWindow.console
  49. );
  50. const SCRIPT_NAME = ((_a = _GM_info == null ? void 0 : _GM_info.script) == null ? void 0 : _a.name) || _SCRIPT_NAME_;
  51. const DEBUG = false;
  52. log.config({
  53. debug: DEBUG,
  54. logMaxCount: 2e4,
  55. autoClearConsole: true,
  56. tag: true
  57. });
  58. Qmsg.config({
  59. position: "bottom",
  60. html: true,
  61. maxNums: 5,
  62. autoClose: true,
  63. showClose: false,
  64. showReverse: true
  65. });
  66. const GM_Menu = new utils.GM_Menu({
  67. GM_getValue: _GM_getValue,
  68. GM_setValue: _GM_setValue,
  69. GM_registerMenuCommand: _GM_registerMenuCommand,
  70. GM_unregisterMenuCommand: _GM_unregisterMenuCommand
  71. });
  72. const httpx = new utils.Httpx(_GM_xmlhttpRequest);
  73. httpx.config({
  74. logDetails: DEBUG,
  75. onabort() {
  76. Qmsg.warning("请求取消");
  77. },
  78. ontimeout() {
  79. Qmsg.error("请求超时");
  80. },
  81. onerror(response) {
  82. Qmsg.error("请求异常");
  83. log.error(["httpx-onerror 请求异常", response]);
  84. }
  85. });
  86. ({
  87. Object: {
  88. defineProperty: _unsafeWindow.Object.defineProperty
  89. },
  90. Function: {
  91. apply: _unsafeWindow.Function.prototype.apply,
  92. call: _unsafeWindow.Function.prototype.call
  93. },
  94. Element: {
  95. appendChild: _unsafeWindow.Element.prototype.appendChild
  96. },
  97. setTimeout: _unsafeWindow.setTimeout
  98. });
  99. const addStyle = utils.addStyle;
  100. const KEY = "GM_Panel";
  101. const ATTRIBUTE_KEY = "data-key";
  102. const ATTRIBUTE_DEFAULT_VALUE = "data-default-value";
  103. const CSDNRouter = {
  104. /**
  105. * 判断是否是华为云联盟
  106. * + huaweicloud.csdn.net
  107. */
  108. isHuaWeiCloudBlog() {
  109. return Boolean(/huaweicloud.csdn.net/i.test(window.location.origin));
  110. },
  111. /**
  112. * 判断是否是博客
  113. * + blog.csdn.net
  114. */
  115. isBlog() {
  116. return Boolean(/blog.csdn.net/i.test(window.location.origin));
  117. },
  118. /**
  119. * 判断是否是文库
  120. * + wenku.csdn.net
  121. */
  122. isWenKu() {
  123. return Boolean(/wenku.csdn.net/i.test(window.location.origin));
  124. },
  125. /**
  126. * 判断是否是链接
  127. * + link.csdn.net
  128. */
  129. isLink() {
  130. return window.location.hostname === "link.csdn.net";
  131. },
  132. /**
  133. * 判断是否是搜索
  134. * + so.csdn.net
  135. */
  136. isSo() {
  137. return window.location.hostname === "so.csdn.net";
  138. },
  139. /**
  140. * 判断是否是C知道
  141. * + so.csdn.net/know
  142. * + /chat
  143. * + /so/ai
  144. */
  145. isSoCKnow() {
  146. return this.isSo() && (window.location.pathname.startsWith("/chat") || window.location.pathname.startsWith("/so/ai"));
  147. },
  148. /**
  149. * 判断是否是资源页面
  150. * + download.csdn.net
  151. */
  152. isDownload() {
  153. return window.location.hostname === "download.csdn.net";
  154. }
  155. };
  156. const UISlider = function(text, key, defaultValue, min, max, changeCallBack, getToolTipContent, description) {
  157. let result = {
  158. text,
  159. type: "slider",
  160. description,
  161. attributes: {},
  162. getValue() {
  163. return PopsPanel.getValue(key, defaultValue);
  164. },
  165. getToolTipContent(value) {
  166. if (typeof getToolTipContent === "function") {
  167. return getToolTipContent(value);
  168. } else {
  169. return `${value}`;
  170. }
  171. },
  172. callback(event, value) {
  173. if (typeof changeCallBack === "function") {
  174. if (changeCallBack(event, value)) {
  175. return;
  176. }
  177. }
  178. PopsPanel.setValue(key, value);
  179. },
  180. min,
  181. max
  182. };
  183. if (result.attributes) {
  184. result.attributes[ATTRIBUTE_KEY] = key;
  185. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = defaultValue;
  186. }
  187. return result;
  188. };
  189. const UISwitch = function(text, key, defaultValue, clickCallBack, description) {
  190. let result = {
  191. text,
  192. type: "switch",
  193. description,
  194. attributes: {},
  195. getValue() {
  196. return Boolean(PopsPanel.getValue(key, defaultValue));
  197. },
  198. callback(event, value) {
  199. log.success(`${value ? "开启" : "关闭"} ${text}`);
  200. if (typeof clickCallBack === "function") {
  201. if (clickCallBack(event, value)) {
  202. return;
  203. }
  204. }
  205. PopsPanel.setValue(key, Boolean(value));
  206. },
  207. afterAddToUListCallBack: void 0
  208. };
  209. if (result.attributes) {
  210. result.attributes[ATTRIBUTE_KEY] = key;
  211. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = Boolean(defaultValue);
  212. }
  213. return result;
  214. };
  215. const SettingUIBlog = {
  216. id: "panel-blog",
  217. title: "博客",
  218. isDefault() {
  219. return CSDNRouter.isBlog();
  220. },
  221. forms: [
  222. {
  223. text: "屏蔽",
  224. type: "forms",
  225. forms: [
  226. UISwitch("【屏蔽】登录(不可用)弹窗", "csdn-blog-shieldLoginDialog", true),
  227. UISwitch(
  228. "【屏蔽】左侧博客信息",
  229. "csdn-blog-shieldLeftBlogContainerAside",
  230. false
  231. ),
  232. UISwitch(
  233. "【屏蔽】右侧目录信息",
  234. "csdn-blog-shieldRightDirectoryInformation",
  235. false
  236. ),
  237. UISwitch("【屏蔽】顶部工具栏", "csdn-blog-shieldTopToolbar", false),
  238. UISwitch(
  239. "【屏蔽】底部的悬浮工具栏",
  240. "csdn-blog-shieldBottomFloatingToolbar",
  241. false
  242. )
  243. ]
  244. },
  245. {
  246. text: "右侧悬浮工具栏",
  247. type: "forms",
  248. forms: [
  249. UISwitch(
  250. "启用",
  251. "csdn-blog-rightToolbarEnable",
  252. true,
  253. void 0,
  254. "创作中心,隐藏/显示侧栏,新手引导,客服、举报..."
  255. ),
  256. UISwitch(
  257. "【添加按钮】前往评论",
  258. "csdn-blog-addGotoRecommandButton",
  259. true,
  260. void 0,
  261. "在悬浮工具栏最后面添加"
  262. ),
  263. UISlider(
  264. "right偏移",
  265. "csdn-blog-rightToolbarRightOffset",
  266. 90,
  267. 0,
  268. document.documentElement.clientWidth,
  269. (event, value) => {
  270. let csdnSideToolbar = document.querySelector(
  271. ".csdn-side-toolbar"
  272. );
  273. domutils.css(csdnSideToolbar, {
  274. right: value + "px"
  275. });
  276. },
  277. (value) => {
  278. return `当前:${value}px,默认:90px`;
  279. }
  280. ),
  281. UISlider(
  282. "top偏移",
  283. "csdn-blog-rightToolbarTopOffset",
  284. 140,
  285. 0,
  286. document.documentElement.clientHeight,
  287. (event, value) => {
  288. let csdnSideToolbar = document.querySelector(
  289. ".csdn-side-toolbar"
  290. );
  291. domutils.css(csdnSideToolbar, {
  292. top: value + "px"
  293. });
  294. },
  295. (value) => {
  296. return `当前:${value}px,默认:90px`;
  297. }
  298. ),
  299. UISwitch(
  300. "【屏蔽】创作中心",
  301. "csdn-blog-rightToolbarCreativeCenter",
  302. false
  303. ),
  304. UISwitch(
  305. "【屏蔽】显示/隐藏侧栏",
  306. "csdn-blog-rightToolbarShowOrSidebar",
  307. false
  308. ),
  309. UISwitch(
  310. "【屏蔽】新手引导",
  311. "csdn-blog-rightToolbarBeginnerGuidance",
  312. false
  313. ),
  314. UISwitch(
  315. "【屏蔽】客服",
  316. "csdn-blog-rightToolbarCustomerService",
  317. false
  318. ),
  319. UISwitch("【屏蔽】举报", "csdn-blog-rightToolbarReport", false),
  320. UISwitch("【屏蔽】返回顶部", "csdn-blog-rightToolbarBackToTop", false)
  321. ]
  322. },
  323. {
  324. text: "内容",
  325. type: "forms",
  326. forms: [
  327. UISwitch(
  328. "【屏蔽】底部xx技能树",
  329. "csdn-blog-shieldBottomSkillTree",
  330. false
  331. ),
  332. UISwitch(
  333. "【屏蔽】选中文字悬浮栏",
  334. "csdn-blog-shieldArticleSearchTip",
  335. false,
  336. void 0,
  337. "选中文字弹出的,例如:搜索、评论、笔记"
  338. ),
  339. UISwitch(
  340. "点击代码块自动展开",
  341. "csdn-blog-clickPreCodeAutomatically",
  342. true,
  343. void 0,
  344. "当鼠标点击代码块区域时,将自动展开内容"
  345. ),
  346. UISwitch(
  347. "自动展开代码块",
  348. "csdn-blog-autoExpandCodeContent",
  349. true,
  350. void 0,
  351. "懒人操作,免手动点击展开"
  352. ),
  353. UISwitch(
  354. "自动展开内容",
  355. "csdn-blog-autoExpandContent",
  356. true,
  357. void 0,
  358. "懒人操作,免手动点击展开"
  359. ),
  360. UISwitch(
  361. "全文居中",
  362. "csdn-blog-articleCenter",
  363. true,
  364. function(event, enable) {
  365. if (enable) {
  366. alert(
  367. "为了更好的呈现效果,请开启功能:【屏蔽】左侧博客信息、【屏蔽】右侧目录信息"
  368. );
  369. }
  370. },
  371. "自动屏蔽左侧和右侧的信息,且将文章居中"
  372. ),
  373. UISwitch("允许选择内容", "csdn-blog-allowSelectContent", true, void 0)
  374. ]
  375. },
  376. {
  377. text: "评论",
  378. type: "forms",
  379. forms: [
  380. UISwitch("屏蔽", "csdn-blog-blockComment", false, void 0, "屏蔽评论"),
  381. UISwitch("优化评论的位置", "csdn-blog-restoreComments", true)
  382. ]
  383. },
  384. {
  385. text: "底部文章",
  386. type: "forms",
  387. forms: [
  388. UISwitch(
  389. "屏蔽",
  390. "csdn-blog-shieldBottomRecommendArticle",
  391. false,
  392. void 0,
  393. "屏蔽底部文章"
  394. ),
  395. UISwitch(
  396. "标识CSDN下载",
  397. "csdn-blog-identityCSDNDownload",
  398. true,
  399. void 0,
  400. "使用红框标识"
  401. ),
  402. UISwitch(
  403. "移除资源下载的文章",
  404. "csdn-blog-removeResourceDownloadArticle",
  405. false,
  406. void 0,
  407. "移除download.csdn.net、www.iteye.com、edu.csdn.net的文章链接"
  408. )
  409. ]
  410. },
  411. {
  412. text: "劫持/拦截",
  413. type: "forms",
  414. forms: [
  415. UISwitch(
  416. "拦截-复制的小尾巴",
  417. "csdn-blog-removeClipboardHijacking",
  418. true
  419. ),
  420. UISwitch(
  421. "劫持-禁止复制",
  422. "csdn-blog-unBlockCopy",
  423. true,
  424. void 0,
  425. "允许点击复制按钮进行复制"
  426. )
  427. ]
  428. }
  429. ]
  430. };
  431. const SettingUILink = {
  432. id: "panel-link",
  433. title: "链接",
  434. isDefault() {
  435. return CSDNRouter.isLink();
  436. },
  437. forms: [
  438. {
  439. text: "功能",
  440. type: "forms",
  441. forms: [
  442. UISwitch(
  443. "重定向链接",
  444. "csdn-link-jumpRedirect",
  445. true,
  446. void 0,
  447. "自动跳转至被拦截的Url链接"
  448. )
  449. ]
  450. }
  451. ]
  452. };
  453. const SettingUIHuaWeiCloud = {
  454. id: "panel-hua-wei-cloud",
  455. title: "华为云开发者联盟",
  456. isDefault() {
  457. return CSDNRouter.isHuaWeiCloudBlog();
  458. },
  459. forms: [
  460. {
  461. text: "功能",
  462. type: "forms",
  463. forms: [
  464. UISwitch(
  465. "自动展开全文",
  466. "csdn-hua-wei-cloud-autoExpandContent",
  467. true
  468. )
  469. ]
  470. },
  471. {
  472. text: "屏蔽",
  473. type: "forms",
  474. forms: [
  475. UISwitch(
  476. "【屏蔽】云开发者任务挑战活动",
  477. "csdn-hua-wei-cloud-shieldCloudDeveloperTaskChallengeEvent",
  478. true
  479. ),
  480. UISwitch(
  481. "【屏蔽】左侧悬浮按钮",
  482. "csdn-hua-wei-cloud-shieldLeftFloatingButton",
  483. false,
  484. function(event, enable) {
  485. if (enable) {
  486. alert(
  487. "开启后将屏蔽【当前阅读量】、【点赞按钮】、【评论按钮】、【分享按钮】"
  488. );
  489. }
  490. }
  491. ),
  492. UISwitch(
  493. "【屏蔽】右侧栏",
  494. "csdn-hua-wei-cloud-blockRightColumn",
  495. false,
  496. function(event, enable) {
  497. if (enable) {
  498. alert(
  499. "开启后将屏蔽【相关产品】-【活动日历】-【运营活动】-【热门标签】"
  500. );
  501. }
  502. }
  503. ),
  504. UISwitch(
  505. "【屏蔽】底部推荐内容",
  506. "csdn-hua-wei-cloud-blockRecommendedContentAtTheBottom",
  507. false
  508. ),
  509. UISwitch(
  510. "【屏蔽】底部更多推荐",
  511. "csdn-hua-wei-cloud-shieldTheBottomForMoreRecommendations",
  512. false
  513. )
  514. ]
  515. }
  516. ]
  517. };
  518. const SettingUIWenKu = {
  519. id: "panel-wenku",
  520. title: "资源",
  521. isDefault() {
  522. return CSDNRouter.isLink();
  523. },
  524. forms: [
  525. {
  526. text: "屏蔽",
  527. type: "forms",
  528. forms: [
  529. UISwitch(
  530. "【屏蔽】资源推荐",
  531. "csdn-wenku-shieldResourceRecommend",
  532. false
  533. ),
  534. UISwitch(
  535. "【屏蔽】右侧用户信息",
  536. "csdn-wenku-shieldRightUserInfo",
  537. false
  538. ),
  539. UISwitch(
  540. "【屏蔽】右侧悬浮工具栏",
  541. "csdn-wenku-shieldRightToolBar",
  542. false
  543. )
  544. ]
  545. }
  546. ]
  547. };
  548. const SettingUISo = {
  549. id: "panel-so",
  550. title: "搜索",
  551. isDefault() {
  552. return CSDNRouter.isSo();
  553. },
  554. forms: [
  555. {
  556. text: "C知道-功能",
  557. type: "forms",
  558. forms: [
  559. UISwitch(
  560. "去除水印",
  561. "csdn-so-cknow-removeMaskCover",
  562. true
  563. )
  564. ]
  565. }
  566. ]
  567. };
  568. const MSettingUIBlog = {
  569. id: "m-panel-blog",
  570. title: "博客",
  571. isDefault() {
  572. return CSDNRouter.isBlog();
  573. },
  574. forms: [
  575. {
  576. text: "屏蔽",
  577. type: "forms",
  578. forms: [
  579. UISwitch(
  580. "【屏蔽】广告",
  581. "m-csdn-blog-removeAds",
  582. true,
  583. void 0,
  584. "包括:登录(不可用)弹窗、打开APP、ios版本提示等"
  585. ),
  586. UISwitch(
  587. "【屏蔽】顶部Toolbar",
  588. "m-csdn-blog-shieldTopToolbar",
  589. false
  590. )
  591. ]
  592. },
  593. {
  594. text: "内容",
  595. type: "forms",
  596. forms: [
  597. UISwitch(
  598. "允许选中文字",
  599. "m-csdn-blog-allowSelectText",
  600. true,
  601. void 0,
  602. "设置user-select: text;"
  603. ),
  604. UISwitch(
  605. "自动展开",
  606. "m-csdn-blog-autoExpandContent",
  607. true,
  608. void 0,
  609. "包括内容、代码块"
  610. ),
  611. UISwitch(
  612. "不限制代码块的最大高度",
  613. "m-csdn-blog-notLimitCodePreMaxHeight",
  614. false,
  615. void 0,
  616. "让代码块的高度直接被撑开"
  617. )
  618. ]
  619. },
  620. {
  621. text: "评论",
  622. type: "forms",
  623. forms: [
  624. UISwitch(
  625. "屏蔽",
  626. "m-csdn-blog-blockComment",
  627. false,
  628. void 0,
  629. "屏蔽评论区"
  630. ),
  631. UISwitch(
  632. "不限制评论区的最大高度",
  633. "m-csdn-blog-notLimitCommentMaxHeight",
  634. true,
  635. void 0,
  636. "让评论区高度直接被撑开"
  637. )
  638. ]
  639. },
  640. {
  641. text: "底部文章",
  642. type: "forms",
  643. forms: [
  644. UISwitch(
  645. "屏蔽",
  646. "m-csdn-blog-blockBottomArticle",
  647. false,
  648. void 0,
  649. "屏蔽底部文章"
  650. ),
  651. UISwitch(
  652. "移除资源下载的文章",
  653. "m-csdn-blog-removeResourceArticle",
  654. false,
  655. void 0,
  656. "移除download.csdn.net、www.iteye.com、edu.csdn.net的文章链接"
  657. ),
  658. UISwitch(
  659. "重构",
  660. "m-csdn-blog-refactoringRecommendation",
  661. true,
  662. void 0,
  663. "样式统一化"
  664. ),
  665. UISwitch(
  666. "新标签页打开",
  667. "m-csdn-blog-openNewTab",
  668. true,
  669. void 0,
  670. "点击文章,新标签页打开"
  671. )
  672. ]
  673. },
  674. {
  675. text: "劫持/拦截",
  676. type: "forms",
  677. forms: [
  678. UISwitch(
  679. "劫持-禁止复制",
  680. "m-csdn-blog-unBlockCopy",
  681. true,
  682. void 0,
  683. "允许点击复制按钮进行复制"
  684. )
  685. ]
  686. }
  687. ]
  688. };
  689. const MSettingUILink = {
  690. id: "m-panel-link",
  691. title: "链接",
  692. isDefault() {
  693. return CSDNRouter.isLink();
  694. },
  695. forms: [
  696. {
  697. text: "功能",
  698. type: "forms",
  699. forms: [
  700. UISwitch(
  701. "重定向链接",
  702. "m-csdn-link-jumpRedirect",
  703. true,
  704. void 0,
  705. "自动跳转至被拦截的Url链接"
  706. )
  707. ]
  708. }
  709. ]
  710. };
  711. const MSettingUISo = {
  712. id: "panel-so",
  713. title: "搜索",
  714. isDefault() {
  715. return CSDNRouter.isSo();
  716. },
  717. forms: [
  718. {
  719. text: "C知道-功能",
  720. type: "forms",
  721. forms: [
  722. UISwitch(
  723. "去除水印",
  724. "m-csdn-so-cknow-removeMaskCover",
  725. true
  726. )
  727. ]
  728. }
  729. ]
  730. };
  731. const MSettingUIWenKu = {
  732. id: "m-panel-wenku",
  733. title: "文库",
  734. isDefault() {
  735. return CSDNRouter.isWenKu();
  736. },
  737. forms: [
  738. {
  739. text: "屏蔽",
  740. type: "forms",
  741. forms: [
  742. UISwitch(
  743. "【屏蔽】底部工具栏",
  744. "m-csdn-wenku-shieldBottomToolbar",
  745. false
  746. )
  747. ]
  748. }
  749. ]
  750. };
  751. const MSettingUIHuaWeiCloud = {
  752. id: "m-panel-hua-wei-cloud",
  753. title: "华为云开发者联盟",
  754. isDefault() {
  755. return CSDNRouter.isHuaWeiCloudBlog();
  756. },
  757. forms: [
  758. {
  759. text: "功能",
  760. type: "forms",
  761. forms: [
  762. UISwitch(
  763. "自动展开全文",
  764. "m-csdn-hua-wei-cloud-autoExpandContent",
  765. true
  766. )
  767. ]
  768. }
  769. ]
  770. };
  771. const MSettingUIDownload = {
  772. id: "m-panel-download",
  773. title: "资源",
  774. isDefault() {
  775. return CSDNRouter.isDownload();
  776. },
  777. forms: [
  778. {
  779. text: "屏蔽",
  780. type: "forms",
  781. forms: [
  782. UISwitch(
  783. "【屏蔽】广告",
  784. "m-csdn-download-removeAds",
  785. true,
  786. void 0,
  787. "包括:登录(不可用)弹窗、会员降价等"
  788. )
  789. ]
  790. }
  791. ]
  792. };
  793. const PopsPanel = {
  794. /** 数据 */
  795. $data: {
  796. /**
  797. * 菜单项的默认值
  798. */
  799. data: new utils.Dictionary(),
  800. /**
  801. * 成功只执行了一次的项
  802. */
  803. oneSuccessExecMenu: new utils.Dictionary(),
  804. /**
  805. * 成功只执行了一次的项
  806. */
  807. onceExec: new utils.Dictionary(),
  808. /** 脚本名,一般用在设置的标题上 */
  809. scriptName: SCRIPT_NAME,
  810. /** 菜单项的总值在本地数据配置的键名 */
  811. key: KEY,
  812. /** 菜单项在attributes上配置的菜单键 */
  813. attributeKeyName: ATTRIBUTE_KEY,
  814. /** 菜单项在attributes上配置的菜单默认值 */
  815. attributeDefaultValueName: ATTRIBUTE_DEFAULT_VALUE
  816. },
  817. /** 监听器 */
  818. $listener: {
  819. /**
  820. * 值改变的监听器
  821. */
  822. listenData: new utils.Dictionary()
  823. },
  824. init() {
  825. this.initPanelDefaultValue();
  826. this.initExtensionsMenu();
  827. },
  828. initExtensionsMenu() {
  829. if (_unsafeWindow.top !== _unsafeWindow.self) {
  830. return;
  831. }
  832. GM_Menu.add([
  833. {
  834. key: "show_pops_panel_setting",
  835. text: "⚙ PC端设置",
  836. autoReload: false,
  837. isStoreValue: false,
  838. showText(text) {
  839. return text;
  840. },
  841. callback: () => {
  842. this.showPanel();
  843. }
  844. },
  845. {
  846. key: "m_show_pops_panel_setting",
  847. text: "⚙ 移动端端设置",
  848. autoReload: false,
  849. isStoreValue: false,
  850. showText(text) {
  851. return text;
  852. },
  853. callback: () => {
  854. this.showMPanel();
  855. }
  856. },
  857. {
  858. key: "gotoCSDNCKnow",
  859. text: "⚙ 前往C知道",
  860. isStoreValue: false,
  861. autoReload: false,
  862. showText(text) {
  863. return text;
  864. },
  865. callback() {
  866. window.open("https://so.csdn.net/chat", "_blank");
  867. }
  868. }
  869. ]);
  870. },
  871. /** 初始化本地设置默认的值 */
  872. initPanelDefaultValue() {
  873. let that = this;
  874. function initDefaultValue(config) {
  875. if (!config["attributes"]) {
  876. return;
  877. }
  878. let key = config.attributes[ATTRIBUTE_KEY];
  879. let defaultValue = config["attributes"][ATTRIBUTE_DEFAULT_VALUE];
  880. if (key == null) {
  881. log.warn(["请先配置键", config]);
  882. return;
  883. }
  884. if (that.$data.data.has(key)) {
  885. log.warn("请检查该key(已存在): " + key);
  886. }
  887. that.$data.data.set(key, defaultValue);
  888. }
  889. let contentConfigList = this.getPanelContentConfig().concat(
  890. this.getMPanelContentConfig()
  891. );
  892. for (let index = 0; index < contentConfigList.length; index++) {
  893. let leftContentConfigItem = contentConfigList[index];
  894. if (!leftContentConfigItem.forms) {
  895. continue;
  896. }
  897. let rightContentConfigList = leftContentConfigItem.forms;
  898. for (let formItemIndex = 0; formItemIndex < rightContentConfigList.length; formItemIndex++) {
  899. let rightContentConfigItem = rightContentConfigList[formItemIndex];
  900. if (rightContentConfigItem.forms) {
  901. let childFormConfigList = rightContentConfigItem.forms;
  902. for (let formChildConfigIndex = 0; formChildConfigIndex < childFormConfigList.length; formChildConfigIndex++) {
  903. initDefaultValue(childFormConfigList[formChildConfigIndex]);
  904. }
  905. } else {
  906. initDefaultValue(rightContentConfigItem);
  907. }
  908. }
  909. }
  910. },
  911. /**
  912. * 设置值
  913. * @param key 键
  914. * @param value 值
  915. */
  916. setValue(key, value) {
  917. let locaData = _GM_getValue(KEY, {});
  918. let oldValue = locaData[key];
  919. locaData[key] = value;
  920. _GM_setValue(KEY, locaData);
  921. if (this.$listener.listenData.has(key)) {
  922. this.$listener.listenData.get(key).callback(key, oldValue, value);
  923. }
  924. },
  925. /**
  926. * 判断该键是否存在
  927. * @param key 键
  928. */
  929. hasKey(key) {
  930. let locaData = _GM_getValue(KEY, {});
  931. return key in locaData;
  932. },
  933. /**
  934. * 获取值
  935. * @param key 键
  936. * @param defaultValue 默认值
  937. */
  938. getValue(key, defaultValue) {
  939. let locaData = _GM_getValue(KEY, {});
  940. let localValue = locaData[key];
  941. if (localValue == null) {
  942. if (this.$data.data.has(key)) {
  943. return this.$data.data.get(key);
  944. }
  945. return defaultValue;
  946. }
  947. return localValue;
  948. },
  949. /**
  950. * 删除值
  951. * @param key 键
  952. */
  953. deleteValue(key) {
  954. let locaData = _GM_getValue(KEY, {});
  955. let oldValue = locaData[key];
  956. Reflect.deleteProperty(locaData, key);
  957. _GM_setValue(KEY, locaData);
  958. if (this.$listener.listenData.has(key)) {
  959. this.$listener.listenData.get(key).callback(key, oldValue, void 0);
  960. }
  961. },
  962. /**
  963. * 监听调用setValue、deleteValue
  964. * @param key 需要监听的键
  965. * @param callback
  966. */
  967. addValueChangeListener(key, callback) {
  968. let listenerId = Math.random();
  969. this.$listener.listenData.set(key, {
  970. id: listenerId,
  971. key,
  972. callback
  973. });
  974. return listenerId;
  975. },
  976. /**
  977. * 移除监听
  978. * @param listenerId 监听的id
  979. */
  980. removeValueChangeListener(listenerId) {
  981. let deleteKey = null;
  982. for (const [key, value] of this.$listener.listenData.entries()) {
  983. if (value.id === listenerId) {
  984. deleteKey = key;
  985. break;
  986. }
  987. }
  988. if (typeof deleteKey === "string") {
  989. this.$listener.listenData.delete(deleteKey);
  990. } else {
  991. console.warn("没有找到对应的监听器");
  992. }
  993. },
  994. /**
  995. * 自动判断菜单是否启用,然后执行回调
  996. * @param key
  997. * @param callback 回调
  998. */
  999. execMenu(key, callback) {
  1000. if (typeof key !== "string") {
  1001. throw new TypeError("key 必须是字符串");
  1002. }
  1003. if (!this.$data.data.has(key)) {
  1004. log.warn(`${key} 键不存在`);
  1005. return;
  1006. }
  1007. let value = PopsPanel.getValue(key);
  1008. if (value) {
  1009. callback(value);
  1010. }
  1011. },
  1012. /**
  1013. * 自动判断菜单是否启用,然后执行回调,只会执行一次
  1014. * @param key
  1015. * @param callback 回调
  1016. */
  1017. execMenuOnce(key, callback) {
  1018. if (typeof key !== "string") {
  1019. throw new TypeError("key 必须是字符串");
  1020. }
  1021. if (!this.$data.data.has(key)) {
  1022. log.warn(`${key} 键不存在`);
  1023. return;
  1024. }
  1025. let value = PopsPanel.getValue(key);
  1026. if (value) {
  1027. if (this.$data.oneSuccessExecMenu.has(key)) {
  1028. return;
  1029. }
  1030. callback(value);
  1031. this.$data.oneSuccessExecMenu.set(key, 1);
  1032. }
  1033. },
  1034. /**
  1035. * 根据key执行一次
  1036. * @param key
  1037. */
  1038. onceExec(key, callback) {
  1039. if (typeof key !== "string") {
  1040. throw new TypeError("key 必须是字符串");
  1041. }
  1042. if (this.$data.onceExec.has(key)) {
  1043. return;
  1044. }
  1045. callback();
  1046. this.$data.onceExec.set(key, 1);
  1047. },
  1048. /**
  1049. * 显示设置面板
  1050. */
  1051. showPanel() {
  1052. pops.panel({
  1053. title: {
  1054. text: `${SCRIPT_NAME}-PC端设置`,
  1055. position: "center",
  1056. html: false,
  1057. style: ""
  1058. },
  1059. content: this.getPanelContentConfig(),
  1060. mask: {
  1061. enable: true,
  1062. clickEvent: {
  1063. toClose: true,
  1064. toHide: false
  1065. }
  1066. },
  1067. isMobile: this.isMobile(),
  1068. width: this.getWidth(),
  1069. height: this.getHeight(),
  1070. drag: true,
  1071. only: true
  1072. });
  1073. },
  1074. /**
  1075. * 显示设置面板
  1076. */
  1077. showMPanel() {
  1078. pops.panel({
  1079. title: {
  1080. text: `${SCRIPT_NAME}-移动端设置`,
  1081. position: "center",
  1082. html: false,
  1083. style: ""
  1084. },
  1085. content: this.getMPanelContentConfig(),
  1086. mask: {
  1087. enable: true,
  1088. clickEvent: {
  1089. toClose: true,
  1090. toHide: false
  1091. }
  1092. },
  1093. isMobile: this.isMobile(),
  1094. width: this.getWidth(),
  1095. height: this.getHeight(),
  1096. drag: true,
  1097. only: true
  1098. });
  1099. },
  1100. isMobile() {
  1101. return window.outerWidth < 550;
  1102. },
  1103. /**
  1104. * 获取设置面板的宽度
  1105. */
  1106. getWidth() {
  1107. if (window.outerWidth < 800) {
  1108. return "92dvw";
  1109. } else {
  1110. return "800px";
  1111. }
  1112. },
  1113. /**
  1114. * 获取设置面板的高度
  1115. */
  1116. getHeight() {
  1117. if (window.outerHeight > 450) {
  1118. return "80dvh";
  1119. } else {
  1120. return "450px";
  1121. }
  1122. },
  1123. /**
  1124. * 获取配置内容
  1125. */
  1126. getPanelContentConfig() {
  1127. let configList = [
  1128. SettingUIBlog,
  1129. SettingUILink,
  1130. SettingUIHuaWeiCloud,
  1131. SettingUIWenKu,
  1132. SettingUISo
  1133. ];
  1134. return configList;
  1135. },
  1136. /**
  1137. * 获取配置内容
  1138. */
  1139. getMPanelContentConfig() {
  1140. let configList = [
  1141. MSettingUIBlog,
  1142. MSettingUILink,
  1143. MSettingUIHuaWeiCloud,
  1144. MSettingUIWenKu,
  1145. MSettingUISo,
  1146. MSettingUIDownload
  1147. ];
  1148. return configList;
  1149. }
  1150. };
  1151. const ShieldCSS$4 = "/* 底部免费抽xxx奖品广告 */\r\ndiv.siderbar-box,\r\n/* 华为开发者联盟加入社区 */\r\ndiv.user-desc.user-desc-fix {\r\n display: none !important;\r\n}\r\n";
  1152. const CSDNHuaWeiCloud = {
  1153. init() {
  1154. addStyle(ShieldCSS$4);
  1155. PopsPanel.execMenu(
  1156. "csdn-hua-wei-cloud-shieldCloudDeveloperTaskChallengeEvent",
  1157. () => {
  1158. this.shieldCloudDeveloperTaskChallengeEvent();
  1159. }
  1160. );
  1161. PopsPanel.execMenu("csdn-hua-wei-cloud-autoExpandContent", () => {
  1162. this.autoExpandContent();
  1163. });
  1164. PopsPanel.execMenu("csdn-hua-wei-cloud-shieldLeftFloatingButton", () => {
  1165. this.shieldLeftFloatingButton();
  1166. });
  1167. PopsPanel.execMenu("csdn-hua-wei-cloud-blockRightColumn", () => {
  1168. this.blockRightColumn();
  1169. });
  1170. PopsPanel.execMenu(
  1171. "csdn-hua-wei-cloud-blockRecommendedContentAtTheBottom",
  1172. () => {
  1173. this.blockRecommendedContentAtTheBottom();
  1174. }
  1175. );
  1176. PopsPanel.execMenu(
  1177. "csdn-hua-wei-cloud-shieldTheBottomForMoreRecommendations",
  1178. () => {
  1179. this.shieldTheBottomForMoreRecommendations();
  1180. }
  1181. );
  1182. },
  1183. /**
  1184. * 自动展开内容
  1185. */
  1186. autoExpandContent() {
  1187. log.info("自动展开全文");
  1188. addStyle(`
  1189. /* 自动展开全文 */
  1190. .main-content .user-article{
  1191. height: auto !important;
  1192. overflow: auto !important;
  1193. }
  1194. /* 点击阅读全文 */
  1195. div.article-show-more {
  1196. display: none !important;
  1197. }
  1198. `);
  1199. },
  1200. /**
  1201. * 屏蔽云开发者任务挑战活动
  1202. */
  1203. shieldCloudDeveloperTaskChallengeEvent() {
  1204. let GM_cookie = new utils.GM_Cookie();
  1205. GM_cookie.set({ name: "show_join_group_index", value: 1 });
  1206. log.info("设置Cookie 屏蔽云开发者任务挑战活动");
  1207. },
  1208. /**
  1209. * 屏蔽左侧悬浮按钮
  1210. */
  1211. shieldLeftFloatingButton() {
  1212. log.info("屏蔽左侧悬浮按钮,包括当前阅读量、点赞按钮、评论按钮、分享按钮");
  1213. addStyle(`
  1214. div.toolbar-wrapper.article-interact-bar{
  1215. display: none !important;
  1216. }`);
  1217. },
  1218. /**
  1219. * 屏蔽右侧栏
  1220. */
  1221. blockRightColumn() {
  1222. log.info("屏蔽右侧栏,包括相关产品-活动日历-运营活动-热门标签");
  1223. addStyle(`
  1224. div.page-home-right.dp-aside-right{
  1225. display: none !important;
  1226. }
  1227. `);
  1228. },
  1229. /**
  1230. * 屏蔽底部推荐内容
  1231. */
  1232. blockRecommendedContentAtTheBottom() {
  1233. log.info("屏蔽底部推荐内容");
  1234. addStyle(`
  1235. div.recommend-card-box{
  1236. display: none !important;
  1237. }`);
  1238. },
  1239. /**
  1240. * 屏蔽底部更多推荐
  1241. */
  1242. shieldTheBottomForMoreRecommendations() {
  1243. log.info("屏蔽底部更多推荐");
  1244. addStyle(`
  1245. div.more-article{
  1246. display: none !important;
  1247. }`);
  1248. }
  1249. };
  1250. const BlogShieldCSS = ".ecommend-item-box.recommend-recommend-box,\r\n.login-mark,\r\n.opt-box.text-center,\r\n.leftPop,\r\n#csdn-shop-window,\r\n.toolbar-advert,\r\n.hide-article-box,\r\n.user-desc.user-desc-fix,\r\n.recommend-card-box,\r\n.more-article,\r\n.article-show-more,\r\n#csdn-toolbar-profile-nologin,\r\n.guide-rr-first,\r\n#recommend-item-box-tow,\r\n/* 发文章得原力分图片提示 */\r\ndiv.csdn-toolbar-creative-mp,\r\n/* 阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。 */\r\n#toolBarBox div.write-guide-buttom-box,\r\n/* 觉得还不错? 一键收藏 */\r\nul.toolbox-list div.tool-active-list,\r\n/* 右边按钮组的最上面的创作话题 */\r\ndiv.csdn-side-toolbar .activity-swiper-box,\r\n.sidetool-writeguide-box .tip-box,\r\n/* 右下角的登录(不可用)提示 */\r\n.passport-login-tip-container {\r\n display: none !important;\r\n}\r\n\r\n\r\n";
  1251. const BlogCSS = "/*.blog_container_aside,\r\n#nav {\r\n margin-left: -45px;\r\n}\r\n.recommend-right.align-items-stretch.clearfix,\r\n.dl_right_fixed {\r\n margin-left: 45px;\r\n}*/\r\n";
  1252. const BlogArticleCenterCSS = '#mainBox main {\r\n width: inherit !important;\r\n}\r\n/* 当文章向下滚动时,触发左侧信息悬浮 */\r\naside.blog_container_aside[style*="position: fixed;"] {\r\n display: none !important;\r\n}\r\n\r\n@media (min-width: 1320px) and (max-width: 1380px) {\r\n .nodata .container {\r\n width: 900px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 900px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 490px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 500px;\r\n }\r\n}\r\n\r\n@media screen and (max-width: 1320px) {\r\n .nodata .container {\r\n width: 760px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 760px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 490px !important;\r\n }\r\n\r\n .nodata .container main .toolbox-list .tool-reward {\r\n display: none;\r\n }\r\n\r\n .nodata\r\n .container\r\n main\r\n .more-toolbox-new\r\n .toolbox-left\r\n .profile-box\r\n .profile-name {\r\n max-width: 128px;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 420px;\r\n }\r\n}\r\n\r\n@media screen and (min-width: 1380px) {\r\n .nodata .container {\r\n width: 1010px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 1010px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 490px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 560px;\r\n }\r\n}\r\n\r\n@media (min-width: 1550px) and (max-width: 1700px) {\r\n .nodata .container {\r\n width: 820px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 820px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 690px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 500px;\r\n }\r\n}\r\n\r\n@media screen and (min-width: 1700px) {\r\n .nodata .container {\r\n width: 1010px !important;\r\n }\r\n\r\n .nodata .container main {\r\n width: 1010px;\r\n }\r\n\r\n .nodata .container main #pcCommentBox pre > ol.hljs-ln {\r\n width: 690px !important;\r\n }\r\n\r\n .nodata .container main .articleConDownSource {\r\n width: 560px;\r\n }\r\n}\r\n';
  1253. const CSDNBlogRightToolBar = {
  1254. init() {
  1255. if (!PopsPanel.getValue("csdn-blog-rightToolbarEnable")) {
  1256. this.shieldRightToolbar();
  1257. }
  1258. PopsPanel.execMenuOnce("csdn-blog-rightToolbarCreativeCenter", () => {
  1259. this.shieldCreativeCenter();
  1260. });
  1261. PopsPanel.execMenuOnce("csdn-blog-rightToolbarShowOrSidebar", () => {
  1262. this.shieldShowOrSidebar();
  1263. });
  1264. PopsPanel.execMenuOnce("csdn-blog-rightToolbarBeginnerGuidance", () => {
  1265. this.shieldBeginnerGuidance();
  1266. });
  1267. PopsPanel.execMenuOnce("csdn-blog-rightToolbarCustomerService", () => {
  1268. this.shieldCustomerService();
  1269. });
  1270. PopsPanel.execMenuOnce("csdn-blog-rightToolbarReport", () => {
  1271. this.shieldReport();
  1272. });
  1273. PopsPanel.execMenuOnce("csdn-blog-rightToolbarBackToTop", () => {
  1274. this.shieldBackToTop();
  1275. });
  1276. this.initRightToolbarOffset();
  1277. domutils.ready(() => {
  1278. PopsPanel.execMenu("csdn-blog-addGotoRecommandButton", () => {
  1279. this.addGotoRecommandButton();
  1280. });
  1281. });
  1282. },
  1283. /**
  1284. * 屏蔽右侧工具栏
  1285. */
  1286. shieldRightToolbar() {
  1287. log.info("屏蔽右侧工具栏");
  1288. addStyle(`div.csdn-side-toolbar{display: none !important;}`);
  1289. },
  1290. /**
  1291. * 【添加】前往评论按钮,在返回顶部的下面
  1292. */
  1293. addGotoRecommandButton() {
  1294. log.info("【添加】前往评论按钮,在返回顶部的上面");
  1295. let gotoRecommandNode = document.createElement("a");
  1296. gotoRecommandNode.className = "option-box";
  1297. gotoRecommandNode.setAttribute("data-type", "gorecommand");
  1298. gotoRecommandNode.innerHTML = `<span class="show-txt" style="display:flex;opacity:100;">前往<br>评论</span>`;
  1299. gotoRecommandNode.addEventListener("click", function() {
  1300. let toolbarBoxElement = document.querySelector(
  1301. "#toolBarBox"
  1302. );
  1303. if (!toolbarBoxElement.getClientRects().length) {
  1304. log.error("评论区处于隐藏状态");
  1305. return;
  1306. }
  1307. log.info("滚动到评论");
  1308. let toolbarBoxOffsetTop = toolbarBoxElement.getBoundingClientRect().top + window.scrollY;
  1309. let csdnToolBarElement = document.querySelector(
  1310. "#csdn-toolbar"
  1311. );
  1312. let csdnToolBarStyles = window.getComputedStyle(csdnToolBarElement);
  1313. let csdnToolBarHeight = csdnToolBarElement.clientHeight - parseFloat(csdnToolBarStyles.paddingTop) - parseFloat(csdnToolBarStyles.paddingBottom);
  1314. window.scrollTo({
  1315. top: toolbarBoxOffsetTop - csdnToolBarHeight - 8,
  1316. left: 0,
  1317. behavior: "smooth"
  1318. });
  1319. });
  1320. utils.waitNode(".csdn-side-toolbar").then(() => {
  1321. let targetElement = document.querySelector(
  1322. ".csdn-side-toolbar a:nth-last-child(2)"
  1323. );
  1324. targetElement.parentElement.insertBefore(
  1325. gotoRecommandNode,
  1326. targetElement.nextSibling
  1327. );
  1328. });
  1329. },
  1330. /**
  1331. * 初始化右侧工具栏的偏移(top、right)
  1332. */
  1333. initRightToolbarOffset() {
  1334. log.info("初始化右侧工具栏的偏移(top、right)");
  1335. addStyle(`
  1336. .csdn-side-toolbar{
  1337. left: unset !important;
  1338. }
  1339. `);
  1340. utils.waitNode(".csdn-side-toolbar").then(($sideToolbar) => {
  1341. domutils.css($sideToolbar, {
  1342. top: parseInt(PopsPanel.getValue("csdn-blog-rightToolbarTopOffset")) + "px",
  1343. right: parseInt(PopsPanel.getValue("csdn-blog-rightToolbarRightOffset")) + "px"
  1344. });
  1345. });
  1346. },
  1347. /**
  1348. * 【屏蔽】创作中心
  1349. */
  1350. shieldCreativeCenter() {
  1351. log.info("【屏蔽】创作中心");
  1352. addStyle(
  1353. ".csdn-side-toolbar .sidetool-writeguide-box{display:none !important}"
  1354. );
  1355. },
  1356. /**
  1357. * 【屏蔽】显示/隐藏侧栏
  1358. */
  1359. shieldShowOrSidebar() {
  1360. log.info("【屏蔽】显示/隐藏侧栏");
  1361. addStyle(".csdn-side-toolbar a.sidecolumn{display:none !important}");
  1362. },
  1363. /**
  1364. * 【屏蔽】新手引导
  1365. */
  1366. shieldBeginnerGuidance() {
  1367. log.info("【屏蔽】新手引导");
  1368. addStyle(
  1369. '.csdn-side-toolbar a.option-box[data-type="guide"]{display:none !important}'
  1370. );
  1371. },
  1372. /**
  1373. * 【屏蔽】客服
  1374. */
  1375. shieldCustomerService() {
  1376. log.info("【屏蔽】客服");
  1377. addStyle(
  1378. '.csdn-side-toolbar a.option-box[data-type="cs"]{display:none !important}'
  1379. );
  1380. },
  1381. /**
  1382. * 【屏蔽】举报
  1383. */
  1384. shieldReport() {
  1385. log.info("【屏蔽】举报");
  1386. addStyle(
  1387. '.csdn-side-toolbar a.option-box[data-type="report"]{display:none !important}'
  1388. );
  1389. },
  1390. /**
  1391. * 【屏蔽】返回顶部
  1392. */
  1393. shieldBackToTop() {
  1394. log.info("【屏蔽】返回顶部");
  1395. addStyle(
  1396. '.csdn-side-toolbar a.option-box[data-type="gotop"]{display:none !important}'
  1397. );
  1398. }
  1399. };
  1400. const CSDNBlog = {
  1401. init() {
  1402. this.addCSS();
  1403. CSDNBlogRightToolBar.init();
  1404. PopsPanel.execMenu("csdn-blog-articleCenter", () => {
  1405. this.articleCenter();
  1406. });
  1407. PopsPanel.execMenu("csdn-blog-shieldLoginDialog", () => {
  1408. this.shieldLoginDialog();
  1409. });
  1410. PopsPanel.execMenu("csdn-blog-autoExpandContent", () => {
  1411. this.autoExpandContent();
  1412. });
  1413. PopsPanel.execMenu("csdn-blog-autoExpandCodeContent", () => {
  1414. this.autoExpandCodeContent();
  1415. });
  1416. PopsPanel.execMenu("csdn-blog-blockComment", () => {
  1417. this.blockComment();
  1418. });
  1419. PopsPanel.execMenu("csdn-blog-shieldBottomRecommendArticle", () => {
  1420. this.shieldBottomRecommendArticle();
  1421. });
  1422. PopsPanel.execMenu("csdn-blog-shieldBottomSkillTree", () => {
  1423. this.shieldBottomSkillTree();
  1424. });
  1425. PopsPanel.execMenu("csdn-blog-shieldBottomFloatingToolbar", () => {
  1426. this.shieldBottomFloatingToolbar();
  1427. });
  1428. PopsPanel.execMenu("csdn-blog-shieldLeftBlogContainerAside", () => {
  1429. this.shieldLeftBlogContainerAside();
  1430. });
  1431. PopsPanel.execMenu("csdn-blog-shieldRightDirectoryInformation", () => {
  1432. this.shieldRightDirectoryInformation();
  1433. });
  1434. PopsPanel.execMenu("csdn-blog-shieldTopToolbar", () => {
  1435. this.shieldTopToolbar();
  1436. });
  1437. PopsPanel.execMenu("csdn-blog-shieldArticleSearchTip", () => {
  1438. this.shieldArticleSearchTip();
  1439. });
  1440. PopsPanel.execMenu("csdn-blog-allowSelectContent", () => {
  1441. this.allowSelectContent();
  1442. });
  1443. domutils.ready(() => {
  1444. PopsPanel.execMenu("csdn-blog-removeClipboardHijacking", () => {
  1445. this.removeClipboardHijacking();
  1446. });
  1447. PopsPanel.execMenuOnce("csdn-blog-unBlockCopy", () => {
  1448. this.unBlockCopy();
  1449. });
  1450. PopsPanel.execMenu("csdn-blog-identityCSDNDownload", () => {
  1451. this.identityCSDNDownload();
  1452. });
  1453. PopsPanel.execMenuOnce("csdn-blog-clickPreCodeAutomatically", () => {
  1454. this.clickPreCodeAutomatically();
  1455. });
  1456. PopsPanel.execMenu("csdn-blog-restoreComments", () => {
  1457. this.restoreComments();
  1458. });
  1459. });
  1460. },
  1461. /**
  1462. * 添加屏蔽CSS和功能CSS
  1463. */
  1464. addCSS() {
  1465. log.info("添加屏蔽CSS和功能CSS");
  1466. addStyle(BlogShieldCSS);
  1467. addStyle(BlogCSS);
  1468. },
  1469. /**
  1470. * 去除剪贴板劫持
  1471. */
  1472. removeClipboardHijacking() {
  1473. var _a2;
  1474. log.info("去除剪贴板劫持");
  1475. (_a2 = document.querySelector(".article-copyright")) == null ? void 0 : _a2.remove();
  1476. if (_unsafeWindow.articleType) {
  1477. _unsafeWindow.articleType = 0;
  1478. }
  1479. if (_unsafeWindow.csdn && _unsafeWindow.csdn.copyright && _unsafeWindow.csdn.copyright.textData) {
  1480. _unsafeWindow.csdn.copyright.textData = "";
  1481. }
  1482. if (_unsafeWindow.csdn && _unsafeWindow.csdn.copyright && _unsafeWindow.csdn.copyright.htmlData) {
  1483. _unsafeWindow.csdn.copyright.htmlData = "";
  1484. }
  1485. },
  1486. /**
  1487. * 取消禁止复制
  1488. */
  1489. unBlockCopy() {
  1490. log.info("取消禁止复制");
  1491. domutils.on(
  1492. document,
  1493. "click",
  1494. function(event) {
  1495. let $click = event.target;
  1496. let $parent = $click.parentElement;
  1497. if (!$click.classList.contains("hljs-button")) {
  1498. return;
  1499. }
  1500. utils.preventEvent(event);
  1501. let copyText = ($parent.innerText || $parent.textContent || "").toString();
  1502. log.info(
  1503. "点击复制按钮复制内容:" + (copyText.length > 8 ? copyText.substring(0, 8) + "..." : copyText)
  1504. );
  1505. utils.setClip(copyText);
  1506. $click.setAttribute("data-title", "复制成功");
  1507. },
  1508. {
  1509. capture: true
  1510. }
  1511. );
  1512. let changeDataTitle = new utils.LockFunction(function(event) {
  1513. let $mouse = event.target;
  1514. if ($mouse.localName !== "pre") {
  1515. return;
  1516. }
  1517. let $hljsBtn = $mouse.querySelector(".hljs-button");
  1518. if ($hljsBtn) {
  1519. $hljsBtn.setAttribute("data-title", "复制");
  1520. }
  1521. });
  1522. domutils.on(
  1523. document,
  1524. ["mouseenter", "mouseleave"],
  1525. function(event) {
  1526. changeDataTitle.run(event);
  1527. },
  1528. {
  1529. capture: true
  1530. }
  1531. );
  1532. utils.waitNode("#content_views").then(($content_views) => {
  1533. var _a2;
  1534. if (_unsafeWindow.$) {
  1535. (_a2 = _unsafeWindow.$("#content_views")) == null ? void 0 : _a2.unbind("copy");
  1536. }
  1537. domutils.on(
  1538. $content_views,
  1539. "copy",
  1540. function(event) {
  1541. utils.preventEvent(event);
  1542. let selectText = _unsafeWindow.getSelection();
  1543. let copyText = selectText == null ? void 0 : selectText.toString();
  1544. log.info(
  1545. "Ctrl+C复制内容:" + (copyText.length > 8 ? copyText.substring(0, 8) + "..." : copyText)
  1546. );
  1547. utils.setClip(copyText);
  1548. return false;
  1549. },
  1550. {
  1551. capture: true
  1552. }
  1553. );
  1554. });
  1555. utils.waitNode(".hljs-button").then(() => {
  1556. setTimeout(() => {
  1557. document.querySelectorAll(".hljs-button").forEach((element) => {
  1558. element.removeAttribute("onclick");
  1559. element.removeAttribute("data-report-click");
  1560. element.setAttribute("data-title", "复制");
  1561. });
  1562. }, 250);
  1563. });
  1564. },
  1565. /**
  1566. * 点击代码块自动展开
  1567. */
  1568. clickPreCodeAutomatically() {
  1569. log.info("点击代码块自动展开");
  1570. document.addEventListener("click", function(event) {
  1571. var _a2;
  1572. let $click = event.target;
  1573. if ($click.localName !== "pre") {
  1574. return;
  1575. }
  1576. $click.style.setProperty("height", "auto");
  1577. (_a2 = $click.querySelector(".hide-preCode-box")) == null ? void 0 : _a2.remove();
  1578. });
  1579. },
  1580. /**
  1581. * 恢复评论到正确位置
  1582. */
  1583. restoreComments() {
  1584. log.info("恢复评论到正确位置-第一条评论");
  1585. utils.waitNode(".first-recommend-box").then(($firstRecommendBox) => {
  1586. let recommendBoxElement = document.querySelector(
  1587. ".recommend-box.insert-baidu-box.recommend-box-style"
  1588. );
  1589. recommendBoxElement.insertBefore(
  1590. $firstRecommendBox,
  1591. recommendBoxElement.firstChild
  1592. );
  1593. });
  1594. log.info("恢复评论到正确位置-第二条评论");
  1595. utils.waitNode(".second-recommend-box").then(($secondRecommendBox) => {
  1596. let recommendBoxElement = document.querySelector(
  1597. ".recommend-box.insert-baidu-box.recommend-box-style"
  1598. );
  1599. recommendBoxElement.insertBefore(
  1600. $secondRecommendBox,
  1601. recommendBoxElement.firstChild
  1602. );
  1603. });
  1604. },
  1605. /**
  1606. * 标识CSDN下载的链接
  1607. */
  1608. identityCSDNDownload() {
  1609. log.info("标识CSDN下载的链接");
  1610. document.querySelectorAll(
  1611. ".recommend-item-box[data-url*='https://download.csdn.net/']"
  1612. ).forEach((item) => {
  1613. if (PopsPanel.getValue("csdn-blog-removeResourceDownloadArticle")) {
  1614. item.remove();
  1615. } else {
  1616. item.querySelector(".content-box").style.setProperty("border", "2px solid red");
  1617. }
  1618. });
  1619. },
  1620. /**
  1621. * 全文居中
  1622. */
  1623. articleCenter() {
  1624. log.info("全文居中");
  1625. addStyle(BlogArticleCenterCSS);
  1626. },
  1627. /**
  1628. * 屏蔽登录(不可用)弹窗
  1629. */
  1630. shieldLoginDialog() {
  1631. log.info("屏蔽登录(不可用)弹窗");
  1632. addStyle(`.passport-login-container{display: none !important;}`);
  1633. },
  1634. /**
  1635. * 自动展开代码块
  1636. */
  1637. autoExpandCodeContent() {
  1638. log.info("自动展开代码块");
  1639. addStyle(`
  1640. pre.set-code-hide{
  1641. height: auto !important;
  1642. }
  1643. pre.set-code-hide .hide-preCode-box{
  1644. display: none !important;
  1645. }
  1646. /* 自动展开代码块 */
  1647. .comment-list-box,
  1648. main div.blog-content-box pre {
  1649. max-height: none !important;
  1650. }
  1651. `);
  1652. },
  1653. /**
  1654. * 自动展开全文
  1655. */
  1656. autoExpandContent() {
  1657. log.info("自动展开全文");
  1658. addStyle(`
  1659. /* 自动展开全文 */
  1660. #article_content,
  1661. .user-article.user-article-hide {
  1662. height: auto !important;
  1663. overflow: auto !important;
  1664. }
  1665. `);
  1666. },
  1667. /**
  1668. * 屏蔽评论区
  1669. */
  1670. blockComment() {
  1671. log.info("屏蔽评论区");
  1672. addStyle(`#pcCommentBox{display: none !important;}`);
  1673. },
  1674. /**
  1675. * 屏蔽底部推荐文章
  1676. */
  1677. shieldBottomRecommendArticle() {
  1678. log.info("屏蔽底部推荐文章");
  1679. addStyle(`main > div.recommend-box {display: none !important;}`);
  1680. },
  1681. /**
  1682. * 屏蔽底部xx技能树
  1683. */
  1684. shieldBottomSkillTree() {
  1685. log.info("屏蔽底部xx技能树");
  1686. addStyle(`#treeSkill{display: none !important;}`);
  1687. },
  1688. /**
  1689. * 屏蔽底部悬浮工具栏
  1690. */
  1691. shieldBottomFloatingToolbar() {
  1692. log.info("屏蔽底部悬浮工具栏");
  1693. addStyle(`#toolBarBox{display: none !important;}`);
  1694. },
  1695. /**
  1696. * 屏蔽左侧博客信息
  1697. */
  1698. shieldLeftBlogContainerAside() {
  1699. log.info("【屏蔽】左侧博客信息");
  1700. addStyle(`aside.blog_container_aside{display: none !important;}`);
  1701. },
  1702. /**
  1703. * 【屏蔽】右侧目录信息
  1704. */
  1705. shieldRightDirectoryInformation() {
  1706. log.info("【屏蔽】右侧目录信息");
  1707. addStyle(`
  1708. #rightAsideConcision,
  1709. #rightAside{
  1710. display: none !important;
  1711. }
  1712. `);
  1713. },
  1714. /**
  1715. * 屏蔽顶部Toolbar
  1716. */
  1717. shieldTopToolbar() {
  1718. log.info("屏蔽顶部Toolbar");
  1719. addStyle(`#toolbarBox{display: none !important;}`);
  1720. },
  1721. /**
  1722. * 屏蔽文章内的选中搜索悬浮提示
  1723. */
  1724. shieldArticleSearchTip() {
  1725. log.info("屏蔽文章内的选中搜索悬浮提示");
  1726. addStyle(`#articleSearchTip{display: none !important;}`);
  1727. },
  1728. /**
  1729. * 允许选择内容
  1730. */
  1731. allowSelectContent() {
  1732. log.info("允许选择内容");
  1733. addStyle(`
  1734. #content_views,
  1735. #content_views pre,
  1736. #content_views pre code {
  1737. user-select: text !important;
  1738. }
  1739. `);
  1740. }
  1741. };
  1742. const WenkuCSS = "#chatgpt-article-detail\r\n > div.layout-center\r\n > div.main\r\n > div.article-box\r\n > div.cont.first-show.forbid {\r\n max-height: unset !important;\r\n height: auto !important;\r\n overflow: auto !important;\r\n}\r\n\r\n.forbid {\r\n user-select: text !important;\r\n}\r\n";
  1743. const ShieldCSS$3 = "/* wenku顶部横幅 */\r\n#app > div > div.main.pb-32 > div > div.top-bar,\r\n/* 底部展开全文 */\r\n#chatgpt-article-detail > div.layout-center > div.main > div.article-box > div.cont.first-show.forbid > div.open {\r\n display: none !important;\r\n}";
  1744. const CSDNWenKu = {
  1745. init() {
  1746. addStyle(WenkuCSS);
  1747. addStyle(ShieldCSS$3);
  1748. PopsPanel.execMenu("csdn-wenku-shieldResourceRecommend", () => {
  1749. this.shieldResourceRecommend();
  1750. });
  1751. PopsPanel.execMenu("csdn-wenku-shieldRightUserInfo", () => {
  1752. this.shieldRightUserInfo();
  1753. });
  1754. PopsPanel.execMenu("csdn-wenku-shieldRightToolBar", () => {
  1755. this.shieldRightToolBar();
  1756. });
  1757. },
  1758. /**
  1759. * 【屏蔽】资源推荐
  1760. */
  1761. shieldResourceRecommend() {
  1762. log.info("【屏蔽】资源推荐");
  1763. addStyle(`#recommend{display:none !important;}`);
  1764. },
  1765. /**
  1766. * 【屏蔽】右侧用户信息
  1767. */
  1768. shieldRightUserInfo() {
  1769. log.info("【屏蔽】右侧用户信息");
  1770. addStyle(`.layout-right{display:none !important;}`);
  1771. },
  1772. /**
  1773. * 【屏蔽】右侧悬浮工具栏
  1774. */
  1775. shieldRightToolBar() {
  1776. log.info("【屏蔽】右侧悬浮工具栏");
  1777. addStyle(`.csdn-side-toolbar {display:none !important;}`);
  1778. }
  1779. };
  1780. const CSDNLink = {
  1781. init() {
  1782. PopsPanel.execMenu("csdn-link-jumpRedirect", () => {
  1783. this.jumpRedirect();
  1784. });
  1785. },
  1786. /**
  1787. * 去除CSDN拦截其它网址的url并自动跳转
  1788. */
  1789. jumpRedirect() {
  1790. if (window.location.hostname === "link.csdn.net" && window.location.search.startsWith("?target")) {
  1791. window.stop();
  1792. let search = window.location.search.replace(/^\?target=/gi, "");
  1793. search = decodeURIComponent(search);
  1794. let newURL = search;
  1795. log.success(`跳转链接 ${newURL}`);
  1796. window.location.href = newURL;
  1797. }
  1798. }
  1799. };
  1800. const CSDN = {
  1801. init() {
  1802. if (CSDNRouter.isLink()) {
  1803. log.info("Router: 中转链接");
  1804. CSDNLink.init();
  1805. } else if (CSDNRouter.isHuaWeiCloudBlog()) {
  1806. log.info("Router: 华为云联盟");
  1807. CSDNHuaWeiCloud.init();
  1808. } else if (CSDNRouter.isBlog()) {
  1809. log.info("Router: 博客");
  1810. CSDNBlog.init();
  1811. } else if (CSDNRouter.isWenKu()) {
  1812. log.info("Router: 文库");
  1813. CSDNWenKu.init();
  1814. } else {
  1815. log.error("暂未适配,请反馈开发者:" + globalThis.location.href);
  1816. }
  1817. }
  1818. };
  1819. const M_CSDNLink = {
  1820. init() {
  1821. PopsPanel.execMenu("m-csdn-link-jumpRedirect", () => {
  1822. CSDNLink.jumpRedirect();
  1823. });
  1824. }
  1825. };
  1826. const ShieldCSS$2 = "/* 右下角的 免费赢华为平板xxxx */\r\n.org-main-content .siderbar-box {\r\n display: none !important;\r\n}\r\n";
  1827. const M_CSDNHuaWeiCloud = {
  1828. init() {
  1829. addStyle(ShieldCSS$2);
  1830. PopsPanel.execMenu("m-csdn-hua-wei-cloud-autoExpandContent", () => {
  1831. CSDNHuaWeiCloud.autoExpandContent();
  1832. });
  1833. }
  1834. };
  1835. const ShieldCSS$1 = "#operate,.feed-Sign-span,\r\n.view_comment_box,\r\n.weixin-shadowbox.wap-shadowbox,\r\n.feed-Sign-span,\r\n.user-desc.user-desc-fix,\r\n.comment_read_more_box,\r\n#content_views pre.set-code-hide .hide-preCode-box,\r\n/* 登录(不可用)弹窗 */\r\n.passport-login-container,\r\n.hljs-button[data-title='登录(不可用)后复制'],\r\n.article-show-more,\r\n#treeSkill,\r\ndiv.btn_open_app_prompt_div,\r\ndiv.readall_box,\r\ndiv.aside-header-fixed,\r\ndiv.feed-Sign-weixin,\r\ndiv.ios-shadowbox {\r\n display: none !important;\r\n}\r\n";
  1836. const MBlogCSS = "#mainBox {\r\n width: auto;\r\n}\r\n.user-desc.user-desc-fix {\r\n height: auto !important;\r\n overflow: auto !important;\r\n}\r\n.component-box .praise {\r\n background: #ff5722;\r\n border-radius: 5px;\r\n padding: 0px 8px;\r\n height: auto;\r\n}\r\n.component-box .praise,\r\n.component-box .share {\r\n color: #fff;\r\n}\r\n.component-box a {\r\n display: inline-block;\r\n font-size: xx-small;\r\n}\r\n.component-box {\r\n display: inline;\r\n margin: 0;\r\n position: relative;\r\n white-space: nowrap;\r\n}\r\n.csdn-edu-title {\r\n background: #4d6de1;\r\n border-radius: 5px;\r\n padding: 0px 8px;\r\n height: auto;\r\n color: #fff !important;\r\n}\r\n\r\n.GM-csdn-dl {\r\n padding: 0.24rem 0.32rem;\r\n width: 100%;\r\n justify-content: space-between;\r\n -webkit-box-pack: justify;\r\n border-bottom: 1px solid #f5f6f7 !important;\r\n}\r\n.GM-csdn-title {\r\n font-size: 0.3rem;\r\n color: #222226;\r\n letter-spacing: 0;\r\n line-height: 0.44rem;\r\n font-weight: 600;\r\n /*max-height: .88rem;*/\r\n word-break: break-all;\r\n overflow: hidden;\r\n display: -webkit-box;\r\n -webkit-box-orient: vertical;\r\n -webkit-line-clamp: 2;\r\n}\r\n.GM-csdn-title a {\r\n word-break: break-all;\r\n color: #222226;\r\n font-weight: 600;\r\n}\r\n.GM-csdn-title em,\r\n.GM-csdn-content em {\r\n font-style: normal;\r\n color: #fc5531;\r\n}\r\n.GM-csdn-content {\r\n /*max-width: 5.58rem;*/\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 1;\r\n -webkit-box-orient: vertical;\r\n color: #555666;\r\n font-size: 0.24rem;\r\n line-height: 0.34rem;\r\n max-height: 0.34rem;\r\n word-break: break-all;\r\n -webkit-box-flex: 1;\r\n -ms-flex: 1;\r\n flex: 1;\r\n margin-top: 0.16rem;\r\n}\r\n.GM-csdn-img img {\r\n width: 2.18rem;\r\n height: 1.58rem;\r\n /*margin-left: .16rem*/\r\n}\r\n";
  1837. function waitForElementToRemove(selectorText = "") {
  1838. utils.waitNodeList(selectorText).then((nodeList) => {
  1839. nodeList.forEach((item) => item.remove());
  1840. });
  1841. }
  1842. const M_CSDNBlog = {
  1843. init() {
  1844. this.addCSS();
  1845. PopsPanel.execMenu("m-csdn-blog-shieldTopToolbar", () => {
  1846. this.shieldTopToolbar();
  1847. });
  1848. PopsPanel.execMenu("m-csdn-blog-notLimitCodePreMaxHeight", () => {
  1849. this.notLimitCodePreMaxHeight();
  1850. });
  1851. PopsPanel.execMenu("m-csdn-blog-notLimitCommentMaxHeight", () => {
  1852. this.notLimitCommentMaxHeight();
  1853. });
  1854. PopsPanel.execMenu("m-csdn-blog-allowSelectText", () => {
  1855. this.allowSelectText();
  1856. });
  1857. PopsPanel.execMenu("m-csdn-blog-autoExpandContent", () => {
  1858. this.autoExpandContent();
  1859. });
  1860. PopsPanel.execMenu("m-csdn-blog-blockBottomArticle", () => {
  1861. this.blockBottomArticle();
  1862. });
  1863. PopsPanel.execMenu("m-csdn-blog-blockComment", () => {
  1864. this.blockComment();
  1865. });
  1866. domutils.ready(() => {
  1867. PopsPanel.execMenu("m-csdn-blog-removeAds", () => {
  1868. this.removeAds();
  1869. });
  1870. PopsPanel.execMenu("m-csdn-blog-refactoringRecommendation", () => {
  1871. this.refactoringRecommendation();
  1872. });
  1873. PopsPanel.execMenu("m-csdn-blog-unBlockCopy", () => {
  1874. CSDNBlog.unBlockCopy();
  1875. });
  1876. });
  1877. },
  1878. addCSS() {
  1879. addStyle(ShieldCSS$1);
  1880. addStyle(MBlogCSS);
  1881. },
  1882. /**
  1883. * 屏蔽顶部Toolbar
  1884. */
  1885. shieldTopToolbar() {
  1886. log.info("屏蔽顶部Toolbar");
  1887. addStyle(`
  1888. #csdn-toolbar{
  1889. display: none !important;
  1890. }
  1891. /* 内容顶部要归位 */
  1892. body #main,
  1893. .margin_sides{
  1894. margin-top: unset !important;
  1895. padding-top: unset !important;
  1896. }
  1897. #article .article_title{
  1898. margin-top: .32rem !important;
  1899. padding-top: unset !important;
  1900. }
  1901. `);
  1902. },
  1903. /**
  1904. * 重构底部推荐
  1905. */
  1906. refactoringRecommendation() {
  1907. function refactoring() {
  1908. log.info("重构底部推荐");
  1909. document.querySelectorAll(
  1910. ".container-fluid"
  1911. ).forEach((item) => {
  1912. var _a2, _b;
  1913. let url = "";
  1914. let title = "";
  1915. let content = "";
  1916. let img = "";
  1917. let isCSDNDownload = false;
  1918. let isCSDNEduDownload = false;
  1919. if (item.hasAttribute("data-url")) {
  1920. url = item.getAttribute("data-url");
  1921. title = (_a2 = item.querySelector(".recommend_title div.left")) == null ? void 0 : _a2.innerHTML;
  1922. if (!item.querySelector(".text")) {
  1923. return;
  1924. }
  1925. content = (_b = item.querySelector(".text")) == null ? void 0 : _b.innerHTML;
  1926. if (item.querySelectorAll(".recommend-img").length) {
  1927. item.querySelectorAll(".recommend-img").forEach((item2) => {
  1928. img += item2.innerHTML;
  1929. });
  1930. }
  1931. } else {
  1932. log.info("节点上无data-url");
  1933. url = item.querySelector("a[data-type]").getAttribute("href");
  1934. title = item.querySelector(".recommend_title div.left").innerHTML;
  1935. content = item.querySelector(".text").innerHTML;
  1936. }
  1937. var _URL_ = new URL(url);
  1938. if (_URL_.host === "download.csdn.net" || _URL_.host === "www.iteye.com" && _URL_.pathname.match(/^\/resource/gi)) {
  1939. log.info("该链接为csdn资源下载");
  1940. isCSDNDownload = true;
  1941. title = `<div class="component-box"><a class="praise" href="javascript:;">CSDN下载</a></div>` + title;
  1942. } else if (_URL_.origin.match(/edu.csdn.net/gi)) {
  1943. isCSDNEduDownload = true;
  1944. log.info("该链接为csdn学院下载");
  1945. title = `<div class="component-box"><a class="csdn-edu-title" href="javascript:;">CSDN学院</a></div>` + title;
  1946. }
  1947. item.setAttribute("class", "GM-csdn-dl");
  1948. item.setAttribute("data-url", url);
  1949. item.innerHTML = `<div class="GM-csdn-title"><div class="left">${title}</div></div><div class="GM-csdn-content">${content}</div><div class="GM-csdn-img">${img}</div>`;
  1950. item.addEventListener("click", function() {
  1951. if (PopsPanel.getValue("m-csdn-blog-openNewTab")) {
  1952. window.open(url, "_blank");
  1953. } else {
  1954. window.location.href = url;
  1955. }
  1956. });
  1957. if ((isCSDNDownload || isCSDNEduDownload) && PopsPanel.getValue("m-csdn-blog-removeResourceArticle")) {
  1958. item.remove();
  1959. }
  1960. });
  1961. }
  1962. let lockFunction = new utils.LockFunction(refactoring, 50);
  1963. utils.waitNode("#recommend").then(($recommend) => {
  1964. log.info("重构底部推荐");
  1965. lockFunction.run();
  1966. utils.mutationObserver($recommend, {
  1967. callback: () => {
  1968. lockFunction.run();
  1969. },
  1970. config: { childList: true, subtree: true, attributes: true }
  1971. });
  1972. });
  1973. },
  1974. /**
  1975. * 屏蔽底部文章
  1976. */
  1977. blockBottomArticle() {
  1978. log.info("屏蔽底部文章");
  1979. addStyle("#recommend{display:none !important;}");
  1980. },
  1981. /**
  1982. * 屏蔽评论
  1983. */
  1984. blockComment() {
  1985. log.info("屏蔽评论");
  1986. addStyle("#comment{display:none !important;}");
  1987. },
  1988. /**
  1989. * 去除广告
  1990. */
  1991. removeAds() {
  1992. log.info("去除广告");
  1993. waitForElementToRemove(".passport-login-container");
  1994. waitForElementToRemove(".btn_open_app_prompt_box.detail-open-removed");
  1995. waitForElementToRemove(".add-firstAd");
  1996. waitForElementToRemove("div.feed-Sign-weixin");
  1997. waitForElementToRemove("div.ios-shadowbox");
  1998. },
  1999. /**
  2000. * 不限制代码块最大高度
  2001. */
  2002. notLimitCodePreMaxHeight() {
  2003. log.info("不限制代码块最大高度");
  2004. addStyle(`
  2005. pre{
  2006. max-height: unset !important;
  2007. }
  2008. `);
  2009. },
  2010. /**
  2011. * 不限制评论区最大高度
  2012. */
  2013. notLimitCommentMaxHeight() {
  2014. log.info("不限制评论区最大高度");
  2015. addStyle(`
  2016. #comment{
  2017. max-height: none !important;
  2018. }
  2019. `);
  2020. },
  2021. /**
  2022. * 允许选择文字
  2023. */
  2024. allowSelectText() {
  2025. log.info("允许选择文字");
  2026. addStyle(`
  2027. #content_views,
  2028. #content_views pre,
  2029. #content_views pre code{
  2030. webkit-touch-callout: text !important;
  2031. -webkit-user-select: text !important;
  2032. -khtml-user-select: text !important;
  2033. -moz-user-select: text !important;
  2034. -ms-user-select: text !important;
  2035. user-select: text !important;
  2036. }
  2037. `);
  2038. },
  2039. /**
  2040. * 自动展开内容
  2041. */
  2042. autoExpandContent() {
  2043. log.info("自动展开内容");
  2044. addStyle(`
  2045. #content_views pre.set-code-hide,
  2046. .article_content{
  2047. height: 100% !important;
  2048. overflow: auto !important;
  2049. }
  2050. `);
  2051. }
  2052. };
  2053. const ShieldCSS = "/* 右下角的买一年送3个月的广告图标 */\r\n.blind_box {\r\n display: none !important;\r\n}\r\n";
  2054. const M_CSDNWenKu = {
  2055. init() {
  2056. addStyle(ShieldCSS);
  2057. PopsPanel.execMenu("m-csdn-wenku-shieldBottomToolbar", () => {
  2058. this.shieldBottomToolbar();
  2059. });
  2060. },
  2061. /**
  2062. * 【屏蔽】底部工具栏
  2063. */
  2064. shieldBottomToolbar() {
  2065. log.info("【屏蔽】底部工具栏");
  2066. addStyle(`
  2067. .page-container > div.btn{
  2068. display: none !important;
  2069. }
  2070. `);
  2071. }
  2072. };
  2073. const CSDNBlockCSS = "/* 右下角悬浮图标 买1年送3个月 */\r\n.page-container .blind_box,\r\n/* 底部工具栏右边的 开会员按钮(低至xx元/次) */\r\n.page-container .btn .ml-12,\r\n/* 登录(不可用)弹窗 */\r\n.passport-login-container,\r\n/* 通用广告className匹配 */\r\n.ads {\r\n display: none !important;\r\n}\r\n";
  2074. const M_CSDNDownload = {
  2075. init() {
  2076. PopsPanel.execMenu("m-csdn-download-removeAds", () => {
  2077. addStyle(CSDNBlockCSS);
  2078. });
  2079. }
  2080. };
  2081. const M_CSDN = {
  2082. init() {
  2083. if (CSDNRouter.isLink()) {
  2084. log.info("Router: 中转链接");
  2085. M_CSDNLink.init();
  2086. } else if (CSDNRouter.isHuaWeiCloudBlog()) {
  2087. log.info("Router: 华为云联盟");
  2088. M_CSDNHuaWeiCloud.init();
  2089. } else if (CSDNRouter.isBlog()) {
  2090. log.info("Router: 博客");
  2091. M_CSDNBlog.init();
  2092. } else if (CSDNRouter.isWenKu()) {
  2093. log.info("Router: 文库");
  2094. M_CSDNWenKu.init();
  2095. } else if (CSDNRouter.isDownload()) {
  2096. log.info("Router: 资源下载");
  2097. M_CSDNDownload.init();
  2098. } else {
  2099. log.error("暂未适配,请反馈开发者:" + globalThis.location.href);
  2100. }
  2101. }
  2102. };
  2103. PopsPanel.init();
  2104. let isMobile = utils.isPhone();
  2105. let CHANGE_ENV_SET_KEY = "change_env_set";
  2106. let chooseMode = _GM_getValue(CHANGE_ENV_SET_KEY);
  2107. GM_Menu.add({
  2108. key: CHANGE_ENV_SET_KEY,
  2109. text: `⚙ 自动: ${isMobile ? "移动端" : "PC端"}`,
  2110. autoReload: false,
  2111. isStoreValue: false,
  2112. showText(text) {
  2113. if (chooseMode == null) {
  2114. return text;
  2115. }
  2116. return text + ` 手动: ${chooseMode == 1 ? "移动端" : chooseMode == 2 ? "PC端" : "未知"}`;
  2117. },
  2118. callback: () => {
  2119. let allowValue = [0, 1, 2];
  2120. let chooseText = window.prompt(
  2121. "请输入当前脚本环境判定\n\n自动判断: 0\n移动端: 1\nPC端: 2",
  2122. "0"
  2123. );
  2124. if (!chooseText) {
  2125. return;
  2126. }
  2127. let chooseMode2 = parseInt(chooseText);
  2128. if (isNaN(chooseMode2)) {
  2129. Qmsg.error("输入的不是规范的数字");
  2130. return;
  2131. }
  2132. if (!allowValue.includes(chooseMode2)) {
  2133. Qmsg.error("输入的值必须是0或1或2");
  2134. return;
  2135. }
  2136. if (chooseMode2 == 0) {
  2137. _GM_deleteValue(CHANGE_ENV_SET_KEY);
  2138. } else {
  2139. _GM_setValue(CHANGE_ENV_SET_KEY, chooseMode2);
  2140. }
  2141. }
  2142. });
  2143. if (chooseMode != null) {
  2144. log.info(`手动判定为${chooseMode === 1 ? "移动端" : "PC端"}`);
  2145. if (chooseMode == 1) {
  2146. M_CSDN.init();
  2147. } else if (chooseMode == 2) {
  2148. CSDN.init();
  2149. } else {
  2150. Qmsg.error("意外,手动判定的值不在范围内");
  2151. _GM_deleteValue(CHANGE_ENV_SET_KEY);
  2152. }
  2153. } else {
  2154. if (isMobile) {
  2155. log.info("自动判定为移动端");
  2156. M_CSDN.init();
  2157. } else {
  2158. log.info("自动判定为PC端");
  2159. CSDN.init();
  2160. }
  2161. }
  2162.  
  2163. })(Qmsg, DOMUtils, Utils);

QingJ © 2025

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