CSDN优化

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

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

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