CSDN优化

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

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

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

QingJ © 2025

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