CSDN优化

支持PC和手机端、屏蔽广告、优化浏览体验、重定向拦截的Url、自动展开全文、自动展开代码块、全文居中、允许复制内容、去除复制内容的小尾巴、自定义屏蔽元素等

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

  1. // ==UserScript==
  2. // @name CSDN优化
  3. // @namespace https://github.com/WhiteSevs/TamperMonkeyScript
  4. // @version 2024.7.22
  5. // @author WhiteSevs
  6. // @description 支持PC和手机端、屏蔽广告、优化浏览体验、重定向拦截的Url、自动展开全文、自动展开代码块、全文居中、允许复制内容、去除复制内容的小尾巴、自定义屏蔽元素等
  7. // @license GPL-3.0-only
  8. // @icon data:image/png;base64,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
  9. // @supportURL https://github.com/WhiteSevs/TamperMonkeyScript/issues
  10. // @match *://*.csdn.net/*
  11. // @require https://update.greasyfork.org/scripts/494167/1413255/CoverUMD.js
  12. // @require https://fastly.jsdelivr.net/npm/qmsg@1.2.1/dist/index.umd.js
  13. // @require https://fastly.jsdelivr.net/npm/@whitesev/utils@1.9.2/dist/index.umd.js
  14. // @require https://fastly.jsdelivr.net/npm/@whitesev/domutils@1.1.2/dist/index.umd.js
  15. // @require https://fastly.jsdelivr.net/npm/@whitesev/pops@1.4.0/dist/index.umd.js
  16. // @grant GM_addStyle
  17. // @grant GM_deleteValue
  18. // @grant GM_getValue
  19. // @grant GM_info
  20. // @grant GM_registerMenuCommand
  21. // @grant GM_setValue
  22. // @grant GM_unregisterMenuCommand
  23. // @grant GM_xmlhttpRequest
  24. // @grant unsafeWindow
  25. // @run-at document-start
  26. // ==/UserScript==
  27.  
  28. (function (Qmsg, DOMUtils, Utils, pops) {
  29. 'use strict';
  30.  
  31. var _a;
  32. var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)();
  33. var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  34. var _GM_info = /* @__PURE__ */ (() => typeof GM_info != "undefined" ? GM_info : void 0)();
  35. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  36. var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  37. var _GM_unregisterMenuCommand = /* @__PURE__ */ (() => typeof GM_unregisterMenuCommand != "undefined" ? GM_unregisterMenuCommand : void 0)();
  38. var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  39. var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
  40. var _monkeyWindow = /* @__PURE__ */ (() => window)();
  41. const _SCRIPT_NAME_ = "CSDN优化";
  42. const utils = Utils.noConflict();
  43. const domutils = DOMUtils.noConflict();
  44. const __pops = pops;
  45. const log = new utils.Log(
  46. _GM_info,
  47. _unsafeWindow.console || _monkeyWindow.console
  48. );
  49. const SCRIPT_NAME = ((_a = _GM_info == null ? void 0 : _GM_info.script) == null ? void 0 : _a.name) || _SCRIPT_NAME_;
  50. const DEBUG = false;
  51. log.config({
  52. debug: DEBUG,
  53. logMaxCount: 1e3,
  54. autoClearConsole: true,
  55. tag: true
  56. });
  57. Qmsg.config(
  58. Object.defineProperties(
  59. {
  60. html: true,
  61. autoClose: true,
  62. showClose: false
  63. },
  64. {
  65. position: {
  66. get() {
  67. return PopsPanel.getValue("qmsg-config-position", "bottom");
  68. }
  69. },
  70. maxNums: {
  71. get() {
  72. return PopsPanel.getValue("qmsg-config-maxnums", 5);
  73. }
  74. },
  75. showReverse: {
  76. get() {
  77. return PopsPanel.getValue("qmsg-config-showreverse", true);
  78. }
  79. },
  80. zIndex: {
  81. get() {
  82. let maxZIndex = Utils.getMaxZIndex();
  83. let popsMaxZIndex = pops.config.InstanceUtils.getPopsMaxZIndex(maxZIndex).zIndex;
  84. return Utils.getMaxValue(maxZIndex, popsMaxZIndex) + 100;
  85. }
  86. }
  87. }
  88. )
  89. );
  90. const GM_Menu = new utils.GM_Menu({
  91. GM_getValue: _GM_getValue,
  92. GM_setValue: _GM_setValue,
  93. GM_registerMenuCommand: _GM_registerMenuCommand,
  94. GM_unregisterMenuCommand: _GM_unregisterMenuCommand
  95. });
  96. const httpx = new utils.Httpx(_GM_xmlhttpRequest);
  97. httpx.interceptors.response.use(void 0, (data) => {
  98. log.error(["拦截器-请求错误", data]);
  99. if (data.type === "onabort") {
  100. Qmsg.warning("请求取消");
  101. } else if (data.type === "onerror") {
  102. Qmsg.error("请求异常");
  103. } else if (data.type === "ontimeout") {
  104. Qmsg.error("请求超时");
  105. } else {
  106. Qmsg.error("其它错误");
  107. }
  108. return data;
  109. });
  110. httpx.config({
  111. logDetails: DEBUG
  112. });
  113. ({
  114. Object: {
  115. defineProperty: _unsafeWindow.Object.defineProperty
  116. },
  117. Function: {
  118. apply: _unsafeWindow.Function.prototype.apply,
  119. call: _unsafeWindow.Function.prototype.call
  120. },
  121. Element: {
  122. appendChild: _unsafeWindow.Element.prototype.appendChild
  123. },
  124. setTimeout: _unsafeWindow.setTimeout
  125. });
  126. const addStyle = utils.addStyle;
  127. const KEY = "GM_Panel";
  128. const ATTRIBUTE_KEY = "data-key";
  129. const ATTRIBUTE_DEFAULT_VALUE = "data-default-value";
  130. const CSDNRouter = {
  131. /**
  132. * 判断是否是华为云联盟
  133. * + huaweicloud.csdn.net
  134. */
  135. isHuaWeiCloudBlog() {
  136. return Boolean(/huaweicloud.csdn.net/i.test(window.location.origin));
  137. },
  138. /**
  139. * 判断是否是博客
  140. * + blog.csdn.net
  141. */
  142. isBlog() {
  143. return Boolean(/blog.csdn.net/i.test(window.location.origin));
  144. },
  145. /**
  146. * 判断是否是文库
  147. * + wenku.csdn.net
  148. */
  149. isWenKu() {
  150. return Boolean(/wenku.csdn.net/i.test(window.location.origin));
  151. },
  152. /**
  153. * 判断是否是链接
  154. * + link.csdn.net
  155. */
  156. isLink() {
  157. return window.location.hostname === "link.csdn.net";
  158. },
  159. /**
  160. * 判断是否是搜索
  161. * + so.csdn.net
  162. */
  163. isSo() {
  164. return window.location.hostname === "so.csdn.net";
  165. },
  166. /**
  167. * 判断是否是C知道
  168. * + so.csdn.net/know
  169. * + /chat
  170. * + /so/ai
  171. */
  172. isSoCKnow() {
  173. return this.isSo() && (window.location.pathname.startsWith("/chat") || window.location.pathname.startsWith("/so/ai"));
  174. },
  175. /**
  176. * 判断是否是资源页面
  177. * + download.csdn.net
  178. */
  179. isDownload() {
  180. return window.location.hostname === "download.csdn.net";
  181. }
  182. };
  183. const UISlider = function(text, key, defaultValue, min, max, changeCallBack, getToolTipContent, description) {
  184. let result = {
  185. text,
  186. type: "slider",
  187. description,
  188. attributes: {},
  189. getValue() {
  190. return PopsPanel.getValue(key, defaultValue);
  191. },
  192. getToolTipContent(value) {
  193. if (typeof getToolTipContent === "function") {
  194. return getToolTipContent(value);
  195. } else {
  196. return `${value}`;
  197. }
  198. },
  199. callback(event, value) {
  200. if (typeof changeCallBack === "function") {
  201. if (changeCallBack(event, value)) {
  202. return;
  203. }
  204. }
  205. PopsPanel.setValue(key, value);
  206. },
  207. min,
  208. max
  209. };
  210. if (result.attributes) {
  211. result.attributes[ATTRIBUTE_KEY] = key;
  212. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = defaultValue;
  213. }
  214. return result;
  215. };
  216. const UISwitch = function(text, key, defaultValue, clickCallBack, description) {
  217. let result = {
  218. text,
  219. type: "switch",
  220. description,
  221. attributes: {},
  222. getValue() {
  223. return Boolean(PopsPanel.getValue(key, defaultValue));
  224. },
  225. callback(event, value) {
  226. log.success(`${value ? "开启" : "关闭"} ${text}`);
  227. if (typeof clickCallBack === "function") {
  228. if (clickCallBack(event, value)) {
  229. return;
  230. }
  231. }
  232. PopsPanel.setValue(key, Boolean(value));
  233. },
  234. afterAddToUListCallBack: void 0
  235. };
  236. if (result.attributes) {
  237. result.attributes[ATTRIBUTE_KEY] = key;
  238. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = Boolean(defaultValue);
  239. }
  240. return result;
  241. };
  242. const SettingUIBlog = {
  243. id: "panel-blog",
  244. title: "博客",
  245. isDefault() {
  246. return CSDNRouter.isBlog();
  247. },
  248. forms: [
  249. {
  250. text: "",
  251. type: "forms",
  252. forms: [
  253. {
  254. text: "全局屏蔽",
  255. type: "deepMenu",
  256. forms: [
  257. {
  258. text: "",
  259. type: "forms",
  260. forms: [
  261. UISwitch(
  262. "【屏蔽】登录弹窗",
  263. "csdn-blog-shieldLoginDialog",
  264. true
  265. ),
  266. UISwitch(
  267. "【屏蔽】左侧博客信息",
  268. "csdn-blog-shieldLeftBlogContainerAside",
  269. false
  270. ),
  271. UISwitch(
  272. "【屏蔽】右侧目录信息",
  273. "csdn-blog-shieldRightDirectoryInformation",
  274. false
  275. ),
  276. UISwitch(
  277. "【屏蔽】顶部工具栏",
  278. "csdn-blog-shieldTopToolbar",
  279. false
  280. ),
  281. UISwitch(
  282. "【屏蔽】底部的悬浮工具栏",
  283. "csdn-blog-shieldBottomFloatingToolbar",
  284. false
  285. )
  286. ]
  287. }
  288. ]
  289. },
  290. {
  291. text: "右侧悬浮工具栏",
  292. type: "deepMenu",
  293. forms: [
  294. {
  295. text: "功能",
  296. type: "forms",
  297. forms: [
  298. UISwitch(
  299. "启用",
  300. "csdn-blog-rightToolbarEnable",
  301. true,
  302. void 0,
  303. "创作中心,隐藏/显示侧栏,新手引导,客服、举报..."
  304. ),
  305. UISwitch(
  306. "【添加按钮】前往评论",
  307. "csdn-blog-addGotoRecommandButton",
  308. true,
  309. void 0,
  310. "在悬浮工具栏最后面添加"
  311. ),
  312. UISlider(
  313. "right偏移",
  314. "csdn-blog-rightToolbarRightOffset",
  315. 90,
  316. 0,
  317. document.documentElement.clientWidth,
  318. (event, value) => {
  319. let csdnSideToolbar = document.querySelector(
  320. ".csdn-side-toolbar"
  321. );
  322. domutils.css(csdnSideToolbar, {
  323. right: value + "px"
  324. });
  325. },
  326. (value) => {
  327. return `当前:${value}px,默认:90px`;
  328. }
  329. ),
  330. UISlider(
  331. "top偏移",
  332. "csdn-blog-rightToolbarTopOffset",
  333. 140,
  334. 0,
  335. document.documentElement.clientHeight,
  336. (event, value) => {
  337. let csdnSideToolbar = document.querySelector(
  338. ".csdn-side-toolbar"
  339. );
  340. domutils.css(csdnSideToolbar, {
  341. top: value + "px"
  342. });
  343. },
  344. (value) => {
  345. return `当前:${value}px,默认:90px`;
  346. }
  347. )
  348. ]
  349. },
  350. {
  351. text: "屏蔽",
  352. type: "forms",
  353. forms: [
  354. UISwitch(
  355. "【屏蔽】创作中心",
  356. "csdn-blog-rightToolbarCreativeCenter",
  357. false
  358. ),
  359. UISwitch(
  360. "【屏蔽】显示/隐藏侧栏",
  361. "csdn-blog-rightToolbarShowOrSidebar",
  362. false
  363. ),
  364. UISwitch(
  365. "【屏蔽】新手引导",
  366. "csdn-blog-rightToolbarBeginnerGuidance",
  367. false
  368. ),
  369. UISwitch(
  370. "【屏蔽】客服",
  371. "csdn-blog-rightToolbarCustomerService",
  372. false
  373. ),
  374. UISwitch("【屏蔽】举报", "csdn-blog-rightToolbarReport", false),
  375. UISwitch(
  376. "【屏蔽】返回顶部",
  377. "csdn-blog-rightToolbarBackToTop",
  378. false
  379. )
  380. ]
  381. }
  382. ]
  383. },
  384. {
  385. text: "内容",
  386. type: "deepMenu",
  387. forms: [
  388. {
  389. text: "功能",
  390. type: "forms",
  391. forms: [
  392. UISwitch(
  393. "点击代码块自动展开",
  394. "csdn-blog-clickPreCodeAutomatically",
  395. true,
  396. void 0,
  397. "当鼠标点击代码块区域时,将自动展开内容"
  398. ),
  399. UISwitch(
  400. "自动展开代码块",
  401. "csdn-blog-autoExpandCodeContent",
  402. true,
  403. void 0,
  404. "懒人操作,免手动点击展开"
  405. ),
  406. UISwitch(
  407. "自动展开内容",
  408. "csdn-blog-autoExpandContent",
  409. true,
  410. void 0,
  411. "懒人操作,免手动点击展开"
  412. ),
  413. UISwitch(
  414. "全文居中",
  415. "csdn-blog-articleCenter",
  416. true,
  417. function(event, enable) {
  418. if (enable) {
  419. alert(
  420. "为了更好的呈现效果,请开启功能:【屏蔽】左侧博客信息、【屏蔽】右侧目录信息"
  421. );
  422. }
  423. },
  424. "自动屏蔽左侧和右侧的信息,且将文章居中"
  425. ),
  426. UISwitch(
  427. "允许选择内容",
  428. "csdn-blog-allowSelectContent",
  429. true,
  430. void 0
  431. )
  432. ]
  433. },
  434. {
  435. text: "屏蔽",
  436. type: "forms",
  437. forms: [
  438. UISwitch(
  439. "【屏蔽】底部xx技能树",
  440. "csdn-blog-shieldBottomSkillTree",
  441. false
  442. ),
  443. UISwitch(
  444. "【屏蔽】选中文字悬浮栏",
  445. "csdn-blog-shieldArticleSearchTip",
  446. false,
  447. void 0,
  448. "选中文字弹出的,例如:搜索、评论、笔记"
  449. )
  450. ]
  451. }
  452. ]
  453. },
  454. {
  455. text: "评论区",
  456. type: "deepMenu",
  457. forms: [
  458. {
  459. text: "",
  460. type: "forms",
  461. forms: [
  462. UISwitch(
  463. "启用",
  464. "csdn-blog-blockComment",
  465. true,
  466. void 0,
  467. "关闭是屏蔽评论区"
  468. ),
  469. UISwitch("优化评论区的位置", "csdn-blog-restoreComments", true)
  470. ]
  471. }
  472. ]
  473. },
  474. {
  475. text: "底部文章",
  476. type: "deepMenu",
  477. forms: [
  478. {
  479. text: "",
  480. type: "forms",
  481. forms: [
  482. UISwitch(
  483. "启用",
  484. "csdn-blog-bottomRecommendArticleEnable",
  485. true,
  486. void 0,
  487. "关闭是屏蔽底部文章"
  488. ),
  489. UISwitch(
  490. "标识CSDN下载",
  491. "csdn-blog-identityCSDNDownload",
  492. true,
  493. void 0,
  494. "使用红框标识"
  495. ),
  496. UISwitch(
  497. "移除资源下载的文章",
  498. "csdn-blog-removeResourceDownloadArticle",
  499. false,
  500. void 0,
  501. "移除download.csdn.net、www.iteye.com、edu.csdn.net的文章链接"
  502. )
  503. ]
  504. }
  505. ]
  506. },
  507. {
  508. text: "劫持/拦截",
  509. type: "deepMenu",
  510. forms: [
  511. {
  512. text: "",
  513. type: "forms",
  514. forms: [
  515. UISwitch(
  516. "拦截-复制的小尾巴",
  517. "csdn-blog-removeClipboardHijacking",
  518. true
  519. ),
  520. UISwitch(
  521. "劫持-禁止复制",
  522. "csdn-blog-unBlockCopy",
  523. true,
  524. void 0,
  525. "允许点击复制按钮进行复制"
  526. )
  527. ]
  528. }
  529. ]
  530. }
  531. ]
  532. }
  533. ]
  534. };
  535. const SettingUILink = {
  536. id: "panel-link",
  537. title: "链接",
  538. isDefault() {
  539. return CSDNRouter.isLink();
  540. },
  541. forms: [
  542. {
  543. text: "功能",
  544. type: "forms",
  545. forms: [
  546. UISwitch(
  547. "重定向链接",
  548. "csdn-link-jumpRedirect",
  549. true,
  550. void 0,
  551. "自动跳转至被拦截的Url链接"
  552. )
  553. ]
  554. }
  555. ]
  556. };
  557. const SettingUIHuaWeiCloud = {
  558. id: "panel-hua-wei-cloud",
  559. title: "华为云开发者联盟",
  560. isDefault() {
  561. return CSDNRouter.isHuaWeiCloudBlog();
  562. },
  563. forms: [
  564. {
  565. text: "功能",
  566. type: "forms",
  567. forms: [
  568. UISwitch("自动展开全文", "csdn-hua-wei-cloud-autoExpandContent", true)
  569. ]
  570. },
  571. {
  572. text: "屏蔽",
  573. type: "forms",
  574. forms: [
  575. UISwitch(
  576. "【屏蔽】云开发者任务挑战活动",
  577. "csdn-hua-wei-cloud-shieldCloudDeveloperTaskChallengeEvent",
  578. true
  579. ),
  580. UISwitch(
  581. "【屏蔽】左侧悬浮按钮",
  582. "csdn-hua-wei-cloud-shieldLeftFloatingButton",
  583. false,
  584. function(event, enable) {
  585. if (enable) {
  586. alert(
  587. "开启后将屏蔽【当前阅读量】、【点赞按钮】、【评论按钮】、【分享按钮】"
  588. );
  589. }
  590. }
  591. ),
  592. UISwitch(
  593. "【屏蔽】右侧栏",
  594. "csdn-hua-wei-cloud-blockRightColumn",
  595. false,
  596. function(event, enable) {
  597. if (enable) {
  598. alert(
  599. "开启后将屏蔽【相关产品】-【活动日历】-【运营活动】-【热门标签】"
  600. );
  601. }
  602. }
  603. ),
  604. UISwitch(
  605. "【屏蔽】底部推荐内容",
  606. "csdn-hua-wei-cloud-blockRecommendedContentAtTheBottom",
  607. false
  608. ),
  609. UISwitch(
  610. "【屏蔽】底部更多推荐",
  611. "csdn-hua-wei-cloud-shieldTheBottomForMoreRecommendations",
  612. false
  613. )
  614. ]
  615. }
  616. ]
  617. };
  618. const SettingUIWenKu = {
  619. id: "panel-wenku",
  620. title: "资源",
  621. isDefault() {
  622. return CSDNRouter.isLink();
  623. },
  624. forms: [
  625. {
  626. text: "屏蔽",
  627. type: "forms",
  628. forms: [
  629. UISwitch(
  630. "【屏蔽】资源推荐",
  631. "csdn-wenku-shieldResourceRecommend",
  632. false
  633. ),
  634. UISwitch(
  635. "【屏蔽】右侧用户信息",
  636. "csdn-wenku-shieldRightUserInfo",
  637. false
  638. ),
  639. UISwitch(
  640. "【屏蔽】右侧悬浮工具栏",
  641. "csdn-wenku-shieldRightToolBar",
  642. false
  643. )
  644. ]
  645. }
  646. ]
  647. };
  648. const SettingUISo = {
  649. id: "panel-so",
  650. title: "搜索",
  651. isDefault() {
  652. return CSDNRouter.isSo();
  653. },
  654. forms: [
  655. {
  656. text: "C知道-功能",
  657. type: "forms",
  658. forms: [UISwitch("去除水印", "csdn-so-cknow-removeMaskCover", true)]
  659. }
  660. ]
  661. };
  662. const MSettingUIBlog = {
  663. id: "m-panel-blog",
  664. title: "博客",
  665. isDefault() {
  666. return CSDNRouter.isBlog();
  667. },
  668. forms: [
  669. {
  670. text: "",
  671. type: "forms",
  672. forms: [
  673. {
  674. text: "全局屏蔽",
  675. type: "deepMenu",
  676. forms: [
  677. {
  678. text: "",
  679. type: "forms",
  680. forms: [
  681. UISwitch(
  682. "【屏蔽】广告",
  683. "m-csdn-blog-removeAds",
  684. true,
  685. void 0,
  686. "包括:登录弹窗、打开APP、ios版本提示等"
  687. ),
  688. UISwitch(
  689. "【屏蔽】顶部Toolbar",
  690. "m-csdn-blog-shieldTopToolbar",
  691. false
  692. )
  693. ]
  694. }
  695. ]
  696. },
  697. {
  698. text: "内容",
  699. type: "deepMenu",
  700. forms: [
  701. {
  702. text: "",
  703. type: "forms",
  704. forms: [
  705. UISwitch(
  706. "允许选中文字",
  707. "m-csdn-blog-allowSelectText",
  708. true,
  709. void 0,
  710. "设置user-select: text;"
  711. ),
  712. UISwitch(
  713. "自动展开",
  714. "m-csdn-blog-autoExpandContent",
  715. true,
  716. void 0,
  717. "包括内容、代码块"
  718. ),
  719. UISwitch(
  720. "不限制代码块的最大高度",
  721. "m-csdn-blog-notLimitCodePreMaxHeight",
  722. false,
  723. void 0,
  724. "让代码块的高度直接被撑开"
  725. )
  726. ]
  727. }
  728. ]
  729. },
  730. {
  731. text: "评论",
  732. type: "deepMenu",
  733. forms: [
  734. {
  735. text: "",
  736. type: "forms",
  737. forms: [
  738. UISwitch(
  739. "启用",
  740. "m-csdn-blog-comment-enable",
  741. true,
  742. void 0,
  743. "关闭是屏蔽评论区"
  744. ),
  745. UISwitch(
  746. "不限制评论区的最大高度",
  747. "m-csdn-blog-notLimitCommentMaxHeight",
  748. true,
  749. void 0,
  750. "让评论区高度直接被撑开"
  751. )
  752. ]
  753. }
  754. ]
  755. },
  756. {
  757. text: "底部文章",
  758. type: "deepMenu",
  759. forms: [
  760. {
  761. text: "",
  762. type: "forms",
  763. forms: [
  764. UISwitch(
  765. "启用",
  766. "m-csdn-blog-bottomArticleEnable",
  767. true,
  768. void 0,
  769. "关闭是屏蔽底部文章"
  770. ),
  771. UISwitch(
  772. "移除资源下载",
  773. "m-csdn-blog-removeResourceArticle",
  774. false,
  775. void 0,
  776. "移除download.csdn.net、www.iteye.com、edu.csdn.net的文章链接"
  777. ),
  778. UISwitch(
  779. "重构",
  780. "m-csdn-blog-refactoringRecommendation",
  781. true,
  782. void 0,
  783. "文章的样式统一"
  784. ),
  785. UISwitch(
  786. "新标签页打开",
  787. "m-csdn-blog-openNewTab",
  788. true,
  789. void 0,
  790. "新标签页打开文章"
  791. )
  792. ]
  793. }
  794. ]
  795. },
  796. {
  797. text: "劫持/拦截",
  798. type: "deepMenu",
  799. forms: [
  800. {
  801. text: "",
  802. type: "forms",
  803. forms: [
  804. UISwitch(
  805. "劫持-禁止复制",
  806. "m-csdn-blog-unBlockCopy",
  807. true,
  808. void 0,
  809. "允许点击复制按钮进行复制"
  810. )
  811. ]
  812. }
  813. ]
  814. }
  815. ]
  816. }
  817. ]
  818. };
  819. const MSettingUILink = {
  820. id: "m-panel-link",
  821. title: "链接",
  822. isDefault() {
  823. return CSDNRouter.isLink();
  824. },
  825. forms: [
  826. {
  827. text: "功能",
  828. type: "forms",
  829. forms: [
  830. UISwitch(
  831. "重定向链接",
  832. "m-csdn-link-jumpRedirect",
  833. true,
  834. void 0,
  835. "自动跳转至被拦截的Url链接"
  836. )
  837. ]
  838. }
  839. ]
  840. };
  841. const MSettingUISo = {
  842. id: "panel-so",
  843. title: "搜索",
  844. isDefault() {
  845. return CSDNRouter.isSo();
  846. },
  847. forms: [
  848. {
  849. text: "C知道-功能",
  850. type: "forms",
  851. forms: [UISwitch("去除水印", "m-csdn-so-cknow-removeMaskCover", true)]
  852. }
  853. ]
  854. };
  855. const MSettingUIWenKu = {
  856. id: "m-panel-wenku",
  857. title: "文库",
  858. isDefault() {
  859. return CSDNRouter.isWenKu();
  860. },
  861. forms: [
  862. {
  863. text: "屏蔽",
  864. type: "forms",
  865. forms: [
  866. UISwitch(
  867. "【屏蔽】底部工具栏",
  868. "m-csdn-wenku-shieldBottomToolbar",
  869. false
  870. )
  871. ]
  872. }
  873. ]
  874. };
  875. const MSettingUIHuaWeiCloud = {
  876. id: "m-panel-hua-wei-cloud",
  877. title: "华为云开发者联盟",
  878. isDefault() {
  879. return CSDNRouter.isHuaWeiCloudBlog();
  880. },
  881. forms: [
  882. {
  883. text: "功能",
  884. type: "forms",
  885. forms: [
  886. UISwitch(
  887. "自动展开全文",
  888. "m-csdn-hua-wei-cloud-autoExpandContent",
  889. true
  890. )
  891. ]
  892. },
  893. {
  894. text: "屏蔽",
  895. type: "forms",
  896. forms: [
  897. UISwitch(
  898. "【屏蔽】底部加入社区",
  899. "m-csdn-hua-wei-cloud-blockBottomJoinTheCommunity",
  900. true
  901. )
  902. ]
  903. }
  904. ]
  905. };
  906. const MSettingUIDownload = {
  907. id: "m-panel-download",
  908. title: "资源",
  909. isDefault() {
  910. return CSDNRouter.isDownload();
  911. },
  912. forms: [
  913. {
  914. text: "功能",
  915. type: "forms",
  916. forms: [
  917. UISwitch(
  918. "自动展开资源介绍",
  919. "m-csdn-download-automaticallyExpandResourceIntroduction",
  920. true,
  921. void 0,
  922. "屏蔽资源介绍【展开全部】按钮并展开资源介绍"
  923. )
  924. ]
  925. },
  926. {
  927. text: "屏蔽",
  928. type: "forms",
  929. forms: [
  930. UISwitch(
  931. "【屏蔽】广告",
  932. "m-csdn-download-removeAds",
  933. true,
  934. void 0,
  935. "包括:登录弹窗、会员降价等"
  936. )
  937. ]
  938. }
  939. ]
  940. };
  941. const UISelect = function(text, key, defaultValue, data, callback, description) {
  942. let selectData = [];
  943. if (typeof data === "function") {
  944. selectData = data();
  945. } else {
  946. selectData = data;
  947. }
  948. let result = {
  949. text,
  950. type: "select",
  951. description,
  952. attributes: {},
  953. getValue() {
  954. return PopsPanel.getValue(key, defaultValue);
  955. },
  956. callback(event, isSelectedValue, isSelectedText) {
  957. PopsPanel.setValue(key, isSelectedValue);
  958. if (typeof callback === "function") {
  959. callback(event, isSelectedValue, isSelectedText);
  960. }
  961. },
  962. data: selectData
  963. };
  964. if (result.attributes) {
  965. result.attributes[ATTRIBUTE_KEY] = key;
  966. result.attributes[ATTRIBUTE_DEFAULT_VALUE] = defaultValue;
  967. }
  968. return result;
  969. };
  970. const SettingUICommon = {
  971. id: "component-common",
  972. title: "通用",
  973. forms: [
  974. {
  975. text: "Toast配置",
  976. type: "forms",
  977. forms: [
  978. UISelect(
  979. "Toast位置",
  980. "qmsg-config-position",
  981. "bottom",
  982. [
  983. {
  984. value: "topleft",
  985. text: "左上角"
  986. },
  987. {
  988. value: "top",
  989. text: "顶部"
  990. },
  991. {
  992. value: "topright",
  993. text: "右上角"
  994. },
  995. {
  996. value: "left",
  997. text: "左边"
  998. },
  999. {
  1000. value: "center",
  1001. text: "中间"
  1002. },
  1003. {
  1004. value: "right",
  1005. text: "右边"
  1006. },
  1007. {
  1008. value: "bottomleft",
  1009. text: "左下角"
  1010. },
  1011. {
  1012. value: "bottom",
  1013. text: "底部"
  1014. },
  1015. {
  1016. value: "bottomright",
  1017. text: "右下角"
  1018. }
  1019. ],
  1020. (event, isSelectValue, isSelectText) => {
  1021. log.info("设置当前Qmsg弹出位置" + isSelectText);
  1022. },
  1023. "Toast显示在页面九宫格的位置"
  1024. ),
  1025. UISelect(
  1026. "最多显示的数量",
  1027. "qmsg-config-maxnums",
  1028. 3,
  1029. [
  1030. {
  1031. value: 1,
  1032. text: "1"
  1033. },
  1034. {
  1035. value: 2,
  1036. text: "2"
  1037. },
  1038. {
  1039. value: 3,
  1040. text: "3"
  1041. },
  1042. {
  1043. value: 4,
  1044. text: "4"
  1045. },
  1046. {
  1047. value: 5,
  1048. text: "5"
  1049. }
  1050. ],
  1051. void 0,
  1052. "限制Toast显示的数量"
  1053. ),
  1054. UISwitch(
  1055. "逆序弹出",
  1056. "qmsg-config-showreverse",
  1057. false,
  1058. void 0,
  1059. "修改Toast弹出的顺序"
  1060. )
  1061. ]
  1062. }
  1063. // {
  1064. // text: "Cookie配置",
  1065. // type: "forms",
  1066. // forms: [
  1067. // UISwitch(
  1068. // "启用",
  1069. // "httpx-use-cookie-enable",
  1070. // false,
  1071. // void 0,
  1072. // "启用后,将根据下面的配置进行添加cookie"
  1073. // ),
  1074. // UISwitch(
  1075. // "使用document.cookie",
  1076. // "httpx-use-document-cookie",
  1077. // false,
  1078. // void 0,
  1079. // "自动根据请求的域名来设置对应的cookie"
  1080. // ),
  1081. // UITextArea(
  1082. // "tieba.baidu.com",
  1083. // "httpx-cookie-tieba.baidu.com",
  1084. // "",
  1085. // void 0,
  1086. // void 0,
  1087. // "Cookie格式:xxx=xxxx;xxx=xxxx"
  1088. // ),
  1089. // ],
  1090. // },
  1091. ]
  1092. };
  1093. const MSettingUICommon = {
  1094. id: "component-common",
  1095. title: "通用",
  1096. forms: [
  1097. {
  1098. text: "Toast配置",
  1099. type: "forms",
  1100. forms: [
  1101. UISelect(
  1102. "Toast位置",
  1103. "qmsg-config-position",
  1104. "bottom",
  1105. [
  1106. {
  1107. value: "topleft",
  1108. text: "左上角"
  1109. },
  1110. {
  1111. value: "top",
  1112. text: "顶部"
  1113. },
  1114. {
  1115. value: "topright",
  1116. text: "右上角"
  1117. },
  1118. {
  1119. value: "left",
  1120. text: "左边"
  1121. },
  1122. {
  1123. value: "center",
  1124. text: "中间"
  1125. },
  1126. {
  1127. value: "right",
  1128. text: "右边"
  1129. },
  1130. {
  1131. value: "bottomleft",
  1132. text: "左下角"
  1133. },
  1134. {
  1135. value: "bottom",
  1136. text: "底部"
  1137. },
  1138. {
  1139. value: "bottomright",
  1140. text: "右下角"
  1141. }
  1142. ],
  1143. (event, isSelectValue, isSelectText) => {
  1144. log.info("设置当前Qmsg弹出位置" + isSelectText);
  1145. },
  1146. "Toast显示在页面九宫格的位置"
  1147. ),
  1148. UISelect(
  1149. "最多显示的数量",
  1150. "qmsg-config-maxnums",
  1151. 3,
  1152. [
  1153. {
  1154. value: 1,
  1155. text: "1"
  1156. },
  1157. {
  1158. value: 2,
  1159. text: "2"
  1160. },
  1161. {
  1162. value: 3,
  1163. text: "3"
  1164. },
  1165. {
  1166. value: 4,
  1167. text: "4"
  1168. },
  1169. {
  1170. value: 5,
  1171. text: "5"
  1172. }
  1173. ],
  1174. void 0,
  1175. "限制Toast显示的数量"
  1176. ),
  1177. UISwitch(
  1178. "逆序弹出",
  1179. "qmsg-config-showreverse",
  1180. false,
  1181. void 0,
  1182. "修改Toast弹出的顺序"
  1183. )
  1184. ]
  1185. }
  1186. // {
  1187. // text: "Cookie配置",
  1188. // type: "forms",
  1189. // forms: [
  1190. // UISwitch(
  1191. // "启用",
  1192. // "httpx-use-cookie-enable",
  1193. // false,
  1194. // void 0,
  1195. // "启用后,将根据下面的配置进行添加cookie"
  1196. // ),
  1197. // UISwitch(
  1198. // "使用document.cookie",
  1199. // "httpx-use-document-cookie",
  1200. // false,
  1201. // void 0,
  1202. // "自动根据请求的域名来设置对应的cookie"
  1203. // ),
  1204. // UITextArea(
  1205. // "tieba.baidu.com",
  1206. // "httpx-cookie-tieba.baidu.com",
  1207. // "",
  1208. // void 0,
  1209. // void 0,
  1210. // "Cookie格式:xxx=xxxx;xxx=xxxx"
  1211. // ),
  1212. // ],
  1213. // },
  1214. ]
  1215. };
  1216. const __PopsPanel__ = {
  1217. data: null,
  1218. oneSuccessExecMenu: null,
  1219. onceExec: null,
  1220. listenData: null
  1221. };
  1222. const PopsPanel = {
  1223. /** 数据 */
  1224. $data: {
  1225. /**
  1226. * 菜单项的默认值
  1227. */
  1228. get data() {
  1229. if (__PopsPanel__.data == null) {
  1230. __PopsPanel__.data = new utils.Dictionary();
  1231. }
  1232. return __PopsPanel__.data;
  1233. },
  1234. /**
  1235. * 成功只执行了一次的项
  1236. */
  1237. get oneSuccessExecMenu() {
  1238. if (__PopsPanel__.oneSuccessExecMenu == null) {
  1239. __PopsPanel__.oneSuccessExecMenu = new utils.Dictionary();
  1240. }
  1241. return __PopsPanel__.oneSuccessExecMenu;
  1242. },
  1243. /**
  1244. * 成功只执行了一次的项
  1245. */
  1246. get onceExec() {
  1247. if (__PopsPanel__.onceExec == null) {
  1248. __PopsPanel__.onceExec = new utils.Dictionary();
  1249. }
  1250. return __PopsPanel__.onceExec;
  1251. },
  1252. /** 脚本名,一般用在设置的标题上 */
  1253. get scriptName() {
  1254. return SCRIPT_NAME;
  1255. },
  1256. /** 菜单项的总值在本地数据配置的键名 */
  1257. key: KEY,
  1258. /** 菜单项在attributes上配置的菜单键 */
  1259. attributeKeyName: ATTRIBUTE_KEY,
  1260. /** 菜单项在attributes上配置的菜单默认值 */
  1261. attributeDefaultValueName: ATTRIBUTE_DEFAULT_VALUE
  1262. },
  1263. /** 监听器 */
  1264. $listener: {
  1265. /**
  1266. * 值改变的监听器
  1267. */
  1268. get listenData() {
  1269. if (__PopsPanel__.listenData == null) {
  1270. __PopsPanel__.listenData = new utils.Dictionary();
  1271. }
  1272. return __PopsPanel__.listenData;
  1273. }
  1274. },
  1275. init() {
  1276. this.initPanelDefaultValue();
  1277. this.initExtensionsMenu();
  1278. },
  1279. initExtensionsMenu() {
  1280. if (_unsafeWindow.top !== _unsafeWindow.self) {
  1281. return;
  1282. }
  1283. GM_Menu.add([
  1284. {
  1285. key: "show_pops_panel_setting",
  1286. text: "⚙ PC端设置",
  1287. autoReload: false,
  1288. isStoreValue: false,
  1289. showText(text) {
  1290. return text;
  1291. },
  1292. callback: () => {
  1293. this.showPanel();
  1294. }
  1295. },
  1296. {
  1297. key: "m_show_pops_panel_setting",
  1298. text: "⚙ 移动端端设置",
  1299. autoReload: false,
  1300. isStoreValue: false,
  1301. showText(text) {
  1302. return text;
  1303. },
  1304. callback: () => {
  1305. this.showMPanel();
  1306. }
  1307. },
  1308. {
  1309. key: "gotoCSDNCKnow",
  1310. text: "⚙ 前往C知道",
  1311. isStoreValue: false,
  1312. autoReload: false,
  1313. showText(text) {
  1314. return text;
  1315. },
  1316. callback() {
  1317. window.open("https://so.csdn.net/chat", "_blank");
  1318. }
  1319. }
  1320. ]);
  1321. },
  1322. /** 初始化本地设置默认的值 */
  1323. initPanelDefaultValue() {
  1324. let that = this;
  1325. function initDefaultValue(config) {
  1326. if (!config["attributes"]) {
  1327. return;
  1328. }
  1329. let key = config.attributes[ATTRIBUTE_KEY];
  1330. let defaultValue = config["attributes"][ATTRIBUTE_DEFAULT_VALUE];
  1331. if (key == null) {
  1332. log.warn(["请先配置键", config]);
  1333. return;
  1334. }
  1335. if (that.$data.data.has(key)) {
  1336. log.warn("请检查该key(已存在): " + key);
  1337. }
  1338. that.$data.data.set(key, defaultValue);
  1339. }
  1340. function loopInitDefaultValue(configList) {
  1341. for (let index = 0; index < configList.length; index++) {
  1342. let configItem = configList[index];
  1343. initDefaultValue(configItem);
  1344. let childForms = configItem.forms;
  1345. if (childForms && Array.isArray(childForms)) {
  1346. loopInitDefaultValue(childForms);
  1347. }
  1348. }
  1349. }
  1350. let contentConfigList = this.getPanelContentConfig().concat(
  1351. this.getMPanelContentConfig()
  1352. );
  1353. for (let index = 0; index < contentConfigList.length; index++) {
  1354. let leftContentConfigItem = contentConfigList[index];
  1355. if (!leftContentConfigItem.forms) {
  1356. continue;
  1357. }
  1358. let rightContentConfigList = leftContentConfigItem.forms;
  1359. if (rightContentConfigList && Array.isArray(rightContentConfigList)) {
  1360. loopInitDefaultValue(rightContentConfigList);
  1361. }
  1362. }
  1363. },
  1364. /**
  1365. * 设置值
  1366. * @param key 键
  1367. * @param value 值
  1368. */
  1369. setValue(key, value) {
  1370. let locaData = _GM_getValue(KEY, {});
  1371. let oldValue = locaData[key];
  1372. locaData[key] = value;
  1373. _GM_setValue(KEY, locaData);
  1374. if (this.$listener.listenData.has(key)) {
  1375. this.$listener.listenData.get(key).callback(key, oldValue, value);
  1376. }
  1377. },
  1378. /**
  1379. * 判断该键是否存在
  1380. * @param key 键
  1381. */
  1382. hasKey(key) {
  1383. let locaData = _GM_getValue(KEY, {});
  1384. return key in locaData;
  1385. },
  1386. /**
  1387. * 获取值
  1388. * @param key 键
  1389. * @param defaultValue 默认值
  1390. */
  1391. getValue(key, defaultValue) {
  1392. let locaData = _GM_getValue(KEY, {});
  1393. let localValue = locaData[key];
  1394. if (localValue == null) {
  1395. if (this.$data.data.has(key)) {
  1396. return this.$data.data.get(key);
  1397. }
  1398. return defaultValue;
  1399. }
  1400. return localValue;
  1401. },
  1402. /**
  1403. * 删除值
  1404. * @param key 键
  1405. */
  1406. deleteValue(key) {
  1407. let locaData = _GM_getValue(KEY, {});
  1408. let oldValue = locaData[key];
  1409. Reflect.deleteProperty(locaData, key);
  1410. _GM_setValue(KEY, locaData);
  1411. if (this.$listener.listenData.has(key)) {
  1412. this.$listener.listenData.get(key).callback(key, oldValue, void 0);
  1413. }
  1414. },
  1415. /**
  1416. * 监听调用setValue、deleteValue
  1417. * @param key 需要监听的键
  1418. * @param callback
  1419. */
  1420. addValueChangeListener(key, callback) {
  1421. let listenerId = Math.random();
  1422. this.$listener.listenData.set(key, {
  1423. id: listenerId,
  1424. key,
  1425. callback
  1426. });
  1427. return listenerId;
  1428. },
  1429. /**
  1430. * 移除监听
  1431. * @param listenerId 监听的id
  1432. */
  1433. removeValueChangeListener(listenerId) {
  1434. let deleteKey = null;
  1435. for (const [key, value] of this.$listener.listenData.entries()) {
  1436. if (value.id === listenerId) {
  1437. deleteKey = key;
  1438. break;
  1439. }
  1440. }
  1441. if (typeof deleteKey === "string") {
  1442. this.$listener.listenData.delete(deleteKey);
  1443. } else {
  1444. console.warn("没有找到对应的监听器");
  1445. }
  1446. },
  1447. /**
  1448. * 自动判断菜单是否启用,然后执行回调
  1449. * @param key
  1450. * @param callback 回调
  1451. * @param [isReverse=false] 逆反判断菜单启用
  1452. */
  1453. execMenu(key, callback, isReverse = false) {
  1454. if (typeof key !== "string") {
  1455. throw new TypeError("key 必须是字符串");
  1456. }
  1457. if (!this.$data.data.has(key)) {
  1458. log.warn(`${key} 键不存在`);
  1459. return;
  1460. }
  1461. let value = PopsPanel.getValue(key);
  1462. if (isReverse) {
  1463. value = !value;
  1464. }
  1465. if (value) {
  1466. callback(value);
  1467. }
  1468. },
  1469. /**
  1470. * 自动判断菜单是否启用,然后执行回调,只会执行一次
  1471. * @param key
  1472. * @param callback 回调
  1473. * @param [isReverse=false] 逆反判断菜单启用
  1474. */
  1475. execMenuOnce(key, callback, isReverse = false) {
  1476. if (typeof key !== "string") {
  1477. throw new TypeError("key 必须是字符串");
  1478. }
  1479. if (!this.$data.data.has(key)) {
  1480. log.warn(`${key} 键不存在`);
  1481. return;
  1482. }
  1483. if (this.$data.oneSuccessExecMenu.has(key)) {
  1484. return;
  1485. }
  1486. this.$data.oneSuccessExecMenu.set(key, 1);
  1487. let resultStyleList = [];
  1488. let pushStyleNode = (style) => {
  1489. let __value = PopsPanel.getValue(key);
  1490. changeCallBack(__value, style);
  1491. };
  1492. let changeCallBack = (currentValue, resultStyle) => {
  1493. let resultList = [];
  1494. if (currentValue) {
  1495. let result = resultStyle ?? callback(currentValue, pushStyleNode);
  1496. if (result instanceof HTMLStyleElement) {
  1497. resultList = [result];
  1498. } else if (Array.isArray(result)) {
  1499. resultList = [
  1500. ...result.filter(
  1501. (item) => item != null && item instanceof HTMLStyleElement
  1502. )
  1503. ];
  1504. }
  1505. }
  1506. for (let index = 0; index < resultStyleList.length; index++) {
  1507. let $css = resultStyleList[index];
  1508. $css.remove();
  1509. resultStyleList.splice(index, 1);
  1510. index--;
  1511. }
  1512. resultStyleList = [...resultList];
  1513. };
  1514. this.addValueChangeListener(
  1515. key,
  1516. (__key, oldValue, newValue) => {
  1517. if (isReverse) {
  1518. newValue = !newValue;
  1519. }
  1520. changeCallBack(newValue);
  1521. }
  1522. );
  1523. let value = PopsPanel.getValue(key);
  1524. if (isReverse) {
  1525. value = !value;
  1526. }
  1527. if (value) {
  1528. changeCallBack(value);
  1529. }
  1530. },
  1531. /**
  1532. * 根据key执行一次
  1533. * @param key
  1534. */
  1535. onceExec(key, callback) {
  1536. if (typeof key !== "string") {
  1537. throw new TypeError("key 必须是字符串");
  1538. }
  1539. if (this.$data.onceExec.has(key)) {
  1540. return;
  1541. }
  1542. callback();
  1543. this.$data.onceExec.set(key, 1);
  1544. },
  1545. /**
  1546. * 显示设置面板
  1547. */
  1548. showPanel() {
  1549. __pops.panel({
  1550. title: {
  1551. text: `${SCRIPT_NAME}-PC端设置`,
  1552. position: "center",
  1553. html: false,
  1554. style: ""
  1555. },
  1556. content: this.getPanelContentConfig(),
  1557. mask: {
  1558. enable: true,
  1559. clickEvent: {
  1560. toClose: true,
  1561. toHide: false
  1562. }
  1563. },
  1564. isMobile: this.isMobile(),
  1565. width: this.getWidth(),
  1566. height: this.getHeight(),
  1567. drag: true,
  1568. only: true
  1569. });
  1570. },
  1571. /**
  1572. * 显示设置面板
  1573. */
  1574. showMPanel() {
  1575. __pops.panel({
  1576. title: {
  1577. text: `${SCRIPT_NAME}-移动端设置`,
  1578. position: "center",
  1579. html: false,
  1580. style: ""
  1581. },
  1582. content: this.getMPanelContentConfig(),
  1583. mask: {
  1584. enable: true,
  1585. clickEvent: {
  1586. toClose: true,
  1587. toHide: false
  1588. }
  1589. },
  1590. isMobile: this.isMobile(),
  1591. width: this.getWidth(),
  1592. height: this.getHeight(),
  1593. drag: true,
  1594. only: true
  1595. });
  1596. },
  1597. isMobile() {
  1598. return window.outerWidth < 550;
  1599. },
  1600. /**
  1601. * 获取设置面板的宽度
  1602. */
  1603. getWidth() {
  1604. if (window.outerWidth < 800) {
  1605. return "92vw";
  1606. } else {
  1607. return "800px";
  1608. }
  1609. },
  1610. /**
  1611. * 获取设置面板的高度
  1612. */
  1613. getHeight() {
  1614. if (window.outerHeight > 450) {
  1615. return "80vh";
  1616. } else {
  1617. return "450px";
  1618. }
  1619. },
  1620. /**
  1621. * 获取配置内容
  1622. */
  1623. getPanelContentConfig() {
  1624. let configList = [
  1625. SettingUICommon,
  1626. SettingUIBlog,
  1627. SettingUILink,
  1628. SettingUIHuaWeiCloud,
  1629. SettingUIWenKu,
  1630. SettingUISo
  1631. ];
  1632. return configList;
  1633. },
  1634. /**
  1635. * 获取配置内容
  1636. */
  1637. getMPanelContentConfig() {
  1638. let configList = [
  1639. MSettingUICommon,
  1640. MSettingUIBlog,
  1641. MSettingUILink,
  1642. MSettingUIHuaWeiCloud,
  1643. MSettingUIWenKu,
  1644. MSettingUISo,
  1645. MSettingUIDownload
  1646. ];
  1647. return configList;
  1648. }
  1649. };
  1650. 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";
  1651. const CSDNUtils = {
  1652. /**
  1653. * 移除元素(未出现也可以等待出现)
  1654. * @param selectorText 元素选择器
  1655. */
  1656. waitForElementToRemove(selectorText = "") {
  1657. utils.waitNodeList(selectorText).then((nodeList) => {
  1658. nodeList.forEach((item) => item.remove());
  1659. });
  1660. },
  1661. /**
  1662. * 添加屏蔽CSS
  1663. * @param args
  1664. * @example
  1665. * addBlockCSS("")
  1666. * addBlockCSS("","")
  1667. * addBlockCSS(["",""])
  1668. */
  1669. addBlockCSS(...args) {
  1670. let selectorList = [];
  1671. if (args.length === 0) {
  1672. return;
  1673. }
  1674. if (args.length === 1 && typeof args[0] === "string" && args[0].trim() === "") {
  1675. return;
  1676. }
  1677. args.forEach((selector) => {
  1678. if (Array.isArray(selector)) {
  1679. selectorList = selectorList.concat(selector);
  1680. } else {
  1681. selectorList.push(selector);
  1682. }
  1683. });
  1684. return addStyle(`${selectorList.join(",\n")}{display: none !important;}`);
  1685. }
  1686. };
  1687. const CSDNHuaWeiCloud = {
  1688. init() {
  1689. addStyle(ShieldCSS$4);
  1690. PopsPanel.execMenuOnce(
  1691. "csdn-hua-wei-cloud-shieldCloudDeveloperTaskChallengeEvent",
  1692. () => {
  1693. return this.shieldCloudDeveloperTaskChallengeEvent();
  1694. }
  1695. );
  1696. PopsPanel.execMenuOnce("csdn-hua-wei-cloud-autoExpandContent", () => {
  1697. return this.autoExpandContent();
  1698. });
  1699. PopsPanel.execMenuOnce(
  1700. "csdn-hua-wei-cloud-shieldLeftFloatingButton",
  1701. () => {
  1702. return this.shieldLeftFloatingButton();
  1703. }
  1704. );
  1705. PopsPanel.execMenuOnce("csdn-hua-wei-cloud-blockRightColumn", () => {
  1706. return this.blockRightColumn();
  1707. });
  1708. PopsPanel.execMenuOnce(
  1709. "csdn-hua-wei-cloud-blockRecommendedContentAtTheBottom",
  1710. () => {
  1711. return this.blockRecommendedContentAtTheBottom();
  1712. }
  1713. );
  1714. PopsPanel.execMenuOnce(
  1715. "csdn-hua-wei-cloud-shieldTheBottomForMoreRecommendations",
  1716. () => {
  1717. return this.shieldTheBottomForMoreRecommendations();
  1718. }
  1719. );
  1720. },
  1721. /**
  1722. * 自动展开内容
  1723. */
  1724. autoExpandContent() {
  1725. log.info("自动展开全文");
  1726. return [
  1727. CSDNUtils.addBlockCSS("div.article-show-more"),
  1728. addStyle(`
  1729. /* 自动展开全文 */
  1730. .main-content .user-article{
  1731. height: auto !important;
  1732. overflow: auto !important;
  1733. }
  1734. `)
  1735. ];
  1736. },
  1737. /**
  1738. * 屏蔽云开发者任务挑战活动
  1739. */
  1740. shieldCloudDeveloperTaskChallengeEvent() {
  1741. log.info("屏蔽云开发者任务挑战活动");
  1742. return CSDNUtils.addBlockCSS(".luck-draw-modal-warp");
  1743. },
  1744. /**
  1745. * 屏蔽左侧悬浮按钮
  1746. */
  1747. shieldLeftFloatingButton() {
  1748. log.info("屏蔽左侧悬浮按钮,包括当前阅读量、点赞按钮、评论按钮、分享按钮");
  1749. return CSDNUtils.addBlockCSS("div.toolbar-wrapper.article-interact-bar");
  1750. },
  1751. /**
  1752. * 屏蔽右侧栏
  1753. */
  1754. blockRightColumn() {
  1755. log.info("屏蔽右侧栏,包括相关产品-活动日历-运营活动-热门标签");
  1756. return CSDNUtils.addBlockCSS("div.page-home-right.dp-aside-right");
  1757. },
  1758. /**
  1759. * 屏蔽底部推荐内容
  1760. */
  1761. blockRecommendedContentAtTheBottom() {
  1762. log.info("屏蔽底部推荐内容");
  1763. return CSDNUtils.addBlockCSS("div.recommend-card-box");
  1764. },
  1765. /**
  1766. * 屏蔽底部更多推荐
  1767. */
  1768. shieldTheBottomForMoreRecommendations() {
  1769. log.info("屏蔽底部更多推荐");
  1770. return CSDNUtils.addBlockCSS("div.more-article");
  1771. }
  1772. };
  1773. 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";
  1774. 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";
  1775. 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';
  1776. const CSDNBlogRightToolBar = {
  1777. init() {
  1778. PopsPanel.execMenuOnce(
  1779. "csdn-blog-rightToolbarEnable",
  1780. () => {
  1781. return this.shieldRightToolbar();
  1782. },
  1783. true
  1784. );
  1785. PopsPanel.execMenuOnce("csdn-blog-rightToolbarCreativeCenter", () => {
  1786. return this.shieldCreativeCenter();
  1787. });
  1788. PopsPanel.execMenuOnce("csdn-blog-rightToolbarShowOrSidebar", () => {
  1789. return this.shieldShowOrSidebar();
  1790. });
  1791. PopsPanel.execMenuOnce("csdn-blog-rightToolbarBeginnerGuidance", () => {
  1792. return this.shieldBeginnerGuidance();
  1793. });
  1794. PopsPanel.execMenuOnce("csdn-blog-rightToolbarCustomerService", () => {
  1795. return this.shieldCustomerService();
  1796. });
  1797. PopsPanel.execMenuOnce("csdn-blog-rightToolbarReport", () => {
  1798. return this.shieldReport();
  1799. });
  1800. PopsPanel.execMenuOnce("csdn-blog-rightToolbarBackToTop", () => {
  1801. return this.shieldBackToTop();
  1802. });
  1803. this.initRightToolbarOffset();
  1804. domutils.ready(() => {
  1805. PopsPanel.execMenuOnce("csdn-blog-addGotoRecommandButton", () => {
  1806. this.addGotoRecommandButton();
  1807. });
  1808. });
  1809. },
  1810. /**
  1811. * 【添加】前往评论按钮,在返回顶部的下面
  1812. */
  1813. addGotoRecommandButton() {
  1814. log.info("【添加】前往评论按钮,在返回顶部的上面");
  1815. let gotoRecommandNode = document.createElement("a");
  1816. gotoRecommandNode.className = "option-box";
  1817. gotoRecommandNode.setAttribute("data-type", "gorecommand");
  1818. gotoRecommandNode.innerHTML = `<span class="show-txt" style="display:flex;opacity:100;">前往<br>评论</span>`;
  1819. gotoRecommandNode.addEventListener("click", function() {
  1820. let toolbarBoxElement = document.querySelector(
  1821. "#toolBarBox"
  1822. );
  1823. if (!toolbarBoxElement.getClientRects().length) {
  1824. log.error("评论区处于隐藏状态");
  1825. return;
  1826. }
  1827. log.info("滚动到评论");
  1828. let toolbarBoxOffsetTop = toolbarBoxElement.getBoundingClientRect().top + window.scrollY;
  1829. let csdnToolBarElement = document.querySelector(
  1830. "#csdn-toolbar"
  1831. );
  1832. let csdnToolBarStyles = window.getComputedStyle(csdnToolBarElement);
  1833. let csdnToolBarHeight = csdnToolBarElement.clientHeight - parseFloat(csdnToolBarStyles.paddingTop) - parseFloat(csdnToolBarStyles.paddingBottom);
  1834. window.scrollTo({
  1835. top: toolbarBoxOffsetTop - csdnToolBarHeight - 8,
  1836. left: 0,
  1837. behavior: "smooth"
  1838. });
  1839. });
  1840. utils.waitNode(".csdn-side-toolbar").then(() => {
  1841. let targetElement = document.querySelector(
  1842. ".csdn-side-toolbar a:nth-last-child(2)"
  1843. );
  1844. targetElement.parentElement.insertBefore(
  1845. gotoRecommandNode,
  1846. targetElement.nextSibling
  1847. );
  1848. });
  1849. },
  1850. /**
  1851. * 初始化右侧工具栏的偏移(top、right)
  1852. */
  1853. initRightToolbarOffset() {
  1854. log.info("初始化右侧工具栏的偏移(top、right)");
  1855. addStyle(
  1856. /*css*/
  1857. `
  1858. .csdn-side-toolbar{
  1859. left: unset !important;
  1860. }
  1861. `
  1862. );
  1863. utils.waitNode(".csdn-side-toolbar").then(($sideToolbar) => {
  1864. domutils.css($sideToolbar, {
  1865. top: parseInt(PopsPanel.getValue("csdn-blog-rightToolbarTopOffset")) + "px",
  1866. right: parseInt(PopsPanel.getValue("csdn-blog-rightToolbarRightOffset")) + "px"
  1867. });
  1868. });
  1869. },
  1870. /**
  1871. * 屏蔽右侧工具栏
  1872. */
  1873. shieldRightToolbar() {
  1874. log.info("屏蔽右侧工具栏");
  1875. return CSDNUtils.addBlockCSS(`div.csdn-side-toolbar`);
  1876. },
  1877. /**
  1878. * 【屏蔽】创作中心
  1879. */
  1880. shieldCreativeCenter() {
  1881. log.info("【屏蔽】创作中心");
  1882. return CSDNUtils.addBlockCSS(".csdn-side-toolbar .sidetool-writeguide-box");
  1883. },
  1884. /**
  1885. * 【屏蔽】显示/隐藏侧栏
  1886. */
  1887. shieldShowOrSidebar() {
  1888. log.info("【屏蔽】显示/隐藏侧栏");
  1889. return CSDNUtils.addBlockCSS(".csdn-side-toolbar a.sidecolumn");
  1890. },
  1891. /**
  1892. * 【屏蔽】新手引导
  1893. */
  1894. shieldBeginnerGuidance() {
  1895. log.info("【屏蔽】新手引导");
  1896. return CSDNUtils.addBlockCSS(
  1897. '.csdn-side-toolbar a.option-box[data-type="guide"]'
  1898. );
  1899. },
  1900. /**
  1901. * 【屏蔽】客服
  1902. */
  1903. shieldCustomerService() {
  1904. log.info("【屏蔽】客服");
  1905. return CSDNUtils.addBlockCSS(
  1906. '.csdn-side-toolbar a.option-box[data-type="cs"]'
  1907. );
  1908. },
  1909. /**
  1910. * 【屏蔽】举报
  1911. */
  1912. shieldReport() {
  1913. log.info("【屏蔽】举报");
  1914. return CSDNUtils.addBlockCSS(
  1915. '.csdn-side-toolbar a.option-box[data-type="report"]'
  1916. );
  1917. },
  1918. /**
  1919. * 【屏蔽】返回顶部
  1920. */
  1921. shieldBackToTop() {
  1922. log.info("【屏蔽】返回顶部");
  1923. return CSDNUtils.addBlockCSS(
  1924. '.csdn-side-toolbar a.option-box[data-type="gotop"]'
  1925. );
  1926. }
  1927. };
  1928. const CSDNBlog = {
  1929. init() {
  1930. this.addCSS();
  1931. CSDNBlogRightToolBar.init();
  1932. PopsPanel.execMenuOnce("csdn-blog-articleCenter", () => {
  1933. return this.articleCenter();
  1934. });
  1935. PopsPanel.execMenuOnce("csdn-blog-shieldLoginDialog", () => {
  1936. return this.shieldLoginDialog();
  1937. });
  1938. PopsPanel.execMenuOnce("csdn-blog-autoExpandContent", () => {
  1939. return this.autoExpandContent();
  1940. });
  1941. PopsPanel.execMenuOnce("csdn-blog-autoExpandCodeContent", () => {
  1942. return this.autoExpandCodeContent();
  1943. });
  1944. PopsPanel.execMenuOnce(
  1945. "csdn-blog-blockComment",
  1946. () => {
  1947. return this.blockComment();
  1948. },
  1949. true
  1950. );
  1951. PopsPanel.execMenuOnce(
  1952. "csdn-blog-bottomRecommendArticleEnable",
  1953. () => {
  1954. return this.shieldBottomRecommendArticle();
  1955. },
  1956. true
  1957. );
  1958. PopsPanel.execMenuOnce("csdn-blog-shieldBottomSkillTree", () => {
  1959. return this.shieldBottomSkillTree();
  1960. });
  1961. PopsPanel.execMenuOnce("csdn-blog-shieldBottomFloatingToolbar", () => {
  1962. return this.shieldBottomFloatingToolbar();
  1963. });
  1964. PopsPanel.execMenuOnce("csdn-blog-shieldLeftBlogContainerAside", () => {
  1965. return this.shieldLeftBlogContainerAside();
  1966. });
  1967. PopsPanel.execMenuOnce("csdn-blog-shieldRightDirectoryInformation", () => {
  1968. return this.shieldRightDirectoryInformation();
  1969. });
  1970. PopsPanel.execMenuOnce("csdn-blog-shieldTopToolbar", () => {
  1971. return this.shieldTopToolbar();
  1972. });
  1973. PopsPanel.execMenuOnce("csdn-blog-shieldArticleSearchTip", () => {
  1974. return this.shieldArticleSearchTip();
  1975. });
  1976. PopsPanel.execMenuOnce("csdn-blog-allowSelectContent", () => {
  1977. return this.allowSelectContent();
  1978. });
  1979. domutils.ready(() => {
  1980. PopsPanel.execMenuOnce("csdn-blog-removeClipboardHijacking", () => {
  1981. this.removeClipboardHijacking();
  1982. });
  1983. PopsPanel.execMenuOnce("csdn-blog-unBlockCopy", () => {
  1984. this.unBlockCopy();
  1985. });
  1986. PopsPanel.execMenuOnce("csdn-blog-identityCSDNDownload", () => {
  1987. this.identityCSDNDownload();
  1988. });
  1989. PopsPanel.execMenuOnce("csdn-blog-clickPreCodeAutomatically", () => {
  1990. this.clickPreCodeAutomatically();
  1991. });
  1992. PopsPanel.execMenuOnce("csdn-blog-restoreComments", () => {
  1993. this.restoreComments();
  1994. });
  1995. });
  1996. },
  1997. /**
  1998. * 添加屏蔽CSS和功能CSS
  1999. */
  2000. addCSS() {
  2001. log.info("添加屏蔽CSS和功能CSS");
  2002. return [addStyle(BlogShieldCSS), addStyle(BlogCSS)];
  2003. },
  2004. /**
  2005. * 去除剪贴板劫持
  2006. */
  2007. removeClipboardHijacking() {
  2008. log.info("去除剪贴板劫持");
  2009. let $article_copyright = document.querySelector(".article-copyright");
  2010. if ($article_copyright) {
  2011. $article_copyright.remove();
  2012. }
  2013. if (_unsafeWindow.articleType) {
  2014. _unsafeWindow.articleType = 0;
  2015. }
  2016. if (_unsafeWindow.csdn && _unsafeWindow.csdn.copyright && _unsafeWindow.csdn.copyright.textData) {
  2017. _unsafeWindow.csdn.copyright.textData = "";
  2018. }
  2019. if (_unsafeWindow.csdn && _unsafeWindow.csdn.copyright && _unsafeWindow.csdn.copyright.htmlData) {
  2020. _unsafeWindow.csdn.copyright.htmlData = "";
  2021. }
  2022. },
  2023. /**
  2024. * 取消禁止复制
  2025. */
  2026. unBlockCopy() {
  2027. log.info("取消禁止复制");
  2028. domutils.on(
  2029. document,
  2030. "click",
  2031. function(event) {
  2032. let $click = event.target;
  2033. let $parent = $click.parentElement;
  2034. if (!$click.classList.contains("hljs-button")) {
  2035. return;
  2036. }
  2037. utils.preventEvent(event);
  2038. let copyText = ($parent.innerText || $parent.textContent || "").toString();
  2039. log.info(
  2040. "点击复制按钮复制内容:" + (copyText.length > 8 ? copyText.substring(0, 8) + "..." : copyText)
  2041. );
  2042. utils.setClip(copyText);
  2043. $click.setAttribute("data-title", "复制成功");
  2044. },
  2045. {
  2046. capture: true
  2047. }
  2048. );
  2049. let changeDataTitle = new utils.LockFunction(function(event) {
  2050. let $mouse = event.target;
  2051. if ($mouse.localName !== "pre") {
  2052. return;
  2053. }
  2054. let $hljsBtn = $mouse.querySelector(".hljs-button");
  2055. if ($hljsBtn) {
  2056. $hljsBtn.setAttribute("data-title", "复制");
  2057. }
  2058. });
  2059. domutils.on(
  2060. document,
  2061. ["mouseenter", "mouseleave"],
  2062. function(event) {
  2063. changeDataTitle.run(event);
  2064. },
  2065. {
  2066. capture: true
  2067. }
  2068. );
  2069. utils.waitNode("#content_views").then(($content_views) => {
  2070. var _a2;
  2071. if (_unsafeWindow.$) {
  2072. (_a2 = _unsafeWindow.$("#content_views")) == null ? void 0 : _a2.unbind("copy");
  2073. }
  2074. domutils.on(
  2075. $content_views,
  2076. "copy",
  2077. function(event) {
  2078. utils.preventEvent(event);
  2079. let selectText = _unsafeWindow.getSelection();
  2080. let copyText = selectText == null ? void 0 : selectText.toString();
  2081. log.info(
  2082. "Ctrl+C复制内容:" + (copyText.length > 8 ? copyText.substring(0, 8) + "..." : copyText)
  2083. );
  2084. utils.setClip(copyText);
  2085. return false;
  2086. },
  2087. {
  2088. capture: true
  2089. }
  2090. );
  2091. });
  2092. utils.waitNode(".hljs-button").then(() => {
  2093. setTimeout(() => {
  2094. document.querySelectorAll(".hljs-button").forEach((element) => {
  2095. element.removeAttribute("onclick");
  2096. element.removeAttribute("data-report-click");
  2097. element.setAttribute("data-title", "复制");
  2098. });
  2099. }, 250);
  2100. });
  2101. },
  2102. /**
  2103. * 点击代码块自动展开
  2104. */
  2105. clickPreCodeAutomatically() {
  2106. log.info("点击代码块自动展开");
  2107. document.addEventListener("click", function(event) {
  2108. var _a2;
  2109. let $click = event.target;
  2110. if ($click.localName !== "pre") {
  2111. return;
  2112. }
  2113. $click.style.setProperty("height", "auto");
  2114. (_a2 = $click.querySelector(".hide-preCode-box")) == null ? void 0 : _a2.remove();
  2115. });
  2116. },
  2117. /**
  2118. * 恢复评论到正确位置
  2119. */
  2120. restoreComments() {
  2121. log.info("恢复评论到正确位置-第一条评论");
  2122. utils.waitNode(".first-recommend-box").then(($firstRecommendBox) => {
  2123. let recommendBoxElement = document.querySelector(
  2124. ".recommend-box.insert-baidu-box.recommend-box-style"
  2125. );
  2126. recommendBoxElement.insertBefore(
  2127. $firstRecommendBox,
  2128. recommendBoxElement.firstChild
  2129. );
  2130. });
  2131. log.info("恢复评论到正确位置-第二条评论");
  2132. utils.waitNode(".second-recommend-box").then(($secondRecommendBox) => {
  2133. let recommendBoxElement = document.querySelector(
  2134. ".recommend-box.insert-baidu-box.recommend-box-style"
  2135. );
  2136. recommendBoxElement.insertBefore(
  2137. $secondRecommendBox,
  2138. recommendBoxElement.firstChild
  2139. );
  2140. });
  2141. },
  2142. /**
  2143. * 标识CSDN下载的链接
  2144. */
  2145. identityCSDNDownload() {
  2146. log.info("标识CSDN下载的链接");
  2147. document.querySelectorAll(
  2148. ".recommend-item-box[data-url*='https://download.csdn.net/']"
  2149. ).forEach((item) => {
  2150. if (PopsPanel.getValue("csdn-blog-removeResourceDownloadArticle")) {
  2151. item.remove();
  2152. } else {
  2153. item.querySelector(".content-box").style.setProperty("border", "2px solid red");
  2154. }
  2155. });
  2156. },
  2157. /**
  2158. * 全文居中
  2159. */
  2160. articleCenter() {
  2161. log.info("全文居中");
  2162. return addStyle(BlogArticleCenterCSS);
  2163. },
  2164. /**
  2165. * 屏蔽登录弹窗
  2166. */
  2167. shieldLoginDialog() {
  2168. log.info("屏蔽登录弹窗");
  2169. return CSDNUtils.addBlockCSS(`.passport-login-container`);
  2170. },
  2171. /**
  2172. * 自动展开代码块
  2173. */
  2174. autoExpandCodeContent() {
  2175. log.info("自动展开代码块");
  2176. return [
  2177. CSDNUtils.addBlockCSS("pre.set-code-hide .hide-preCode-box"),
  2178. addStyle(
  2179. /*css*/
  2180. `
  2181. pre.set-code-hide{
  2182. height: auto !important;
  2183. }
  2184. /* 自动展开代码块 */
  2185. .comment-list-box,
  2186. main div.blog-content-box pre {
  2187. max-height: none !important;
  2188. }
  2189. `
  2190. )
  2191. ];
  2192. },
  2193. /**
  2194. * 自动展开全文
  2195. */
  2196. autoExpandContent() {
  2197. log.info("自动展开全文");
  2198. return addStyle(
  2199. /*css*/
  2200. `
  2201. /* 自动展开全文 */
  2202. #article_content,
  2203. .user-article.user-article-hide {
  2204. height: auto !important;
  2205. overflow: auto !important;
  2206. }
  2207. `
  2208. );
  2209. },
  2210. /**
  2211. * 屏蔽评论区
  2212. */
  2213. blockComment() {
  2214. log.info("屏蔽评论区");
  2215. return CSDNUtils.addBlockCSS(`#pcCommentBox`);
  2216. },
  2217. /**
  2218. * 屏蔽底部推荐文章
  2219. */
  2220. shieldBottomRecommendArticle() {
  2221. log.info("屏蔽底部推荐文章");
  2222. return CSDNUtils.addBlockCSS(`main > div.recommend-box`);
  2223. },
  2224. /**
  2225. * 屏蔽底部xx技能树
  2226. */
  2227. shieldBottomSkillTree() {
  2228. log.info("屏蔽底部xx技能树");
  2229. return CSDNUtils.addBlockCSS(`#treeSkill`);
  2230. },
  2231. /**
  2232. * 屏蔽底部悬浮工具栏
  2233. */
  2234. shieldBottomFloatingToolbar() {
  2235. log.info("屏蔽底部悬浮工具栏");
  2236. return CSDNUtils.addBlockCSS(`#toolBarBox`);
  2237. },
  2238. /**
  2239. * 屏蔽左侧博客信息
  2240. */
  2241. shieldLeftBlogContainerAside() {
  2242. log.info("【屏蔽】左侧博客信息");
  2243. return CSDNUtils.addBlockCSS(`aside.blog_container_aside`);
  2244. },
  2245. /**
  2246. * 【屏蔽】右侧目录信息
  2247. */
  2248. shieldRightDirectoryInformation() {
  2249. log.info("【屏蔽】右侧目录信息");
  2250. return CSDNUtils.addBlockCSS("#rightAsideConcision", "#rightAside");
  2251. },
  2252. /**
  2253. * 屏蔽顶部Toolbar
  2254. */
  2255. shieldTopToolbar() {
  2256. log.info("屏蔽顶部Toolbar");
  2257. return CSDNUtils.addBlockCSS(`#toolbarBox`);
  2258. },
  2259. /**
  2260. * 屏蔽文章内的选中搜索悬浮提示
  2261. */
  2262. shieldArticleSearchTip() {
  2263. log.info("屏蔽文章内的选中搜索悬浮提示");
  2264. return CSDNUtils.addBlockCSS(`#articleSearchTip`);
  2265. },
  2266. /**
  2267. * 允许选择内容
  2268. */
  2269. allowSelectContent() {
  2270. log.info("允许选择内容");
  2271. return addStyle(
  2272. /*css*/
  2273. `
  2274. #content_views,
  2275. #content_views pre,
  2276. #content_views pre code {
  2277. user-select: text !important;
  2278. }
  2279. `
  2280. );
  2281. }
  2282. };
  2283. 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";
  2284. 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}";
  2285. const CSDNWenKu = {
  2286. init() {
  2287. addStyle(WenkuCSS);
  2288. addStyle(ShieldCSS$3);
  2289. PopsPanel.execMenuOnce("csdn-wenku-shieldResourceRecommend", () => {
  2290. return this.shieldResourceRecommend();
  2291. });
  2292. PopsPanel.execMenuOnce("csdn-wenku-shieldRightUserInfo", () => {
  2293. return this.shieldRightUserInfo();
  2294. });
  2295. PopsPanel.execMenuOnce("csdn-wenku-shieldRightToolBar", () => {
  2296. return this.shieldRightToolBar();
  2297. });
  2298. },
  2299. /**
  2300. * 【屏蔽】资源推荐
  2301. */
  2302. shieldResourceRecommend() {
  2303. log.info("【屏蔽】资源推荐");
  2304. return CSDNUtils.addBlockCSS("#recommend");
  2305. },
  2306. /**
  2307. * 【屏蔽】右侧用户信息
  2308. */
  2309. shieldRightUserInfo() {
  2310. log.info("【屏蔽】右侧用户信息");
  2311. return CSDNUtils.addBlockCSS(".layout-right");
  2312. },
  2313. /**
  2314. * 【屏蔽】右侧悬浮工具栏
  2315. */
  2316. shieldRightToolBar() {
  2317. log.info("【屏蔽】右侧悬浮工具栏");
  2318. return CSDNUtils.addBlockCSS(".csdn-side-toolbar");
  2319. }
  2320. };
  2321. const CSDNLink = {
  2322. init() {
  2323. PopsPanel.execMenuOnce("csdn-link-jumpRedirect", () => {
  2324. this.jumpRedirect();
  2325. });
  2326. },
  2327. /**
  2328. * 去除CSDN拦截其它网址的url并自动跳转
  2329. */
  2330. jumpRedirect() {
  2331. if (window.location.hostname === "link.csdn.net" && window.location.search.startsWith("?target")) {
  2332. window.stop();
  2333. let search = window.location.search.replace(/^\?target=/gi, "");
  2334. search = decodeURIComponent(search);
  2335. let newURL = search;
  2336. log.success(`跳转链接 ${newURL}`);
  2337. window.location.href = newURL;
  2338. }
  2339. }
  2340. };
  2341. const CSDN = {
  2342. init() {
  2343. if (CSDNRouter.isLink()) {
  2344. log.info("Router: 中转链接");
  2345. CSDNLink.init();
  2346. } else if (CSDNRouter.isHuaWeiCloudBlog()) {
  2347. log.info("Router: 华为云联盟");
  2348. CSDNHuaWeiCloud.init();
  2349. } else if (CSDNRouter.isBlog()) {
  2350. log.info("Router: 博客");
  2351. CSDNBlog.init();
  2352. } else if (CSDNRouter.isWenKu()) {
  2353. log.info("Router: 文库");
  2354. CSDNWenKu.init();
  2355. } else {
  2356. log.error("暂未适配,请反馈开发者:" + globalThis.location.href);
  2357. }
  2358. }
  2359. };
  2360. const M_CSDNLink = {
  2361. init() {
  2362. PopsPanel.execMenuOnce("m-csdn-link-jumpRedirect", () => {
  2363. CSDNLink.jumpRedirect();
  2364. });
  2365. }
  2366. };
  2367. const ShieldCSS$2 = "/* 右下角的 免费赢华为平板xxxx */\r\n.org-main-content .siderbar-box {\r\n display: none !important;\r\n}\r\n";
  2368. const M_CSDNHuaWeiCloud = {
  2369. init() {
  2370. addStyle(ShieldCSS$2);
  2371. PopsPanel.execMenuOnce("m-csdn-hua-wei-cloud-autoExpandContent", () => {
  2372. return CSDNHuaWeiCloud.autoExpandContent();
  2373. });
  2374. PopsPanel.execMenuOnce(
  2375. "m-csdn-hua-wei-cloud-blockBottomJoinTheCommunity",
  2376. () => {
  2377. return this.blockBottomJoinTheCommunity();
  2378. }
  2379. );
  2380. },
  2381. /**
  2382. * 【屏蔽】底部加入社区
  2383. */
  2384. blockBottomJoinTheCommunity() {
  2385. log.info("【屏蔽】底部加入社区");
  2386. return CSDNUtils.addBlockCSS(".user-desc");
  2387. }
  2388. };
  2389. 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";
  2390. 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";
  2391. const M_CSDNBlog = {
  2392. init() {
  2393. this.addCSS();
  2394. PopsPanel.execMenuOnce("m-csdn-blog-shieldTopToolbar", () => {
  2395. return this.shieldTopToolbar();
  2396. });
  2397. PopsPanel.execMenuOnce("m-csdn-blog-notLimitCodePreMaxHeight", () => {
  2398. return this.notLimitCodePreMaxHeight();
  2399. });
  2400. PopsPanel.execMenuOnce("m-csdn-blog-notLimitCommentMaxHeight", () => {
  2401. return this.notLimitCommentMaxHeight();
  2402. });
  2403. PopsPanel.execMenuOnce("m-csdn-blog-allowSelectText", () => {
  2404. return this.allowSelectText();
  2405. });
  2406. PopsPanel.execMenuOnce("m-csdn-blog-autoExpandContent", () => {
  2407. return this.autoExpandContent();
  2408. });
  2409. PopsPanel.execMenuOnce(
  2410. "m-csdn-blog-bottomArticleEnable",
  2411. () => {
  2412. return this.blockBottomArticle();
  2413. },
  2414. true
  2415. );
  2416. PopsPanel.execMenuOnce(
  2417. "m-csdn-blog-comment-enable",
  2418. () => {
  2419. return this.blockComment();
  2420. },
  2421. true
  2422. );
  2423. domutils.ready(() => {
  2424. PopsPanel.execMenuOnce("m-csdn-blog-removeAds", () => {
  2425. return this.removeAds();
  2426. });
  2427. PopsPanel.execMenuOnce("m-csdn-blog-refactoringRecommendation", () => {
  2428. this.refactoringRecommendation();
  2429. });
  2430. PopsPanel.execMenuOnce("m-csdn-blog-unBlockCopy", () => {
  2431. CSDNBlog.unBlockCopy();
  2432. });
  2433. });
  2434. },
  2435. addCSS() {
  2436. addStyle(ShieldCSS$1);
  2437. addStyle(MBlogCSS);
  2438. },
  2439. /**
  2440. * 屏蔽顶部Toolbar
  2441. */
  2442. shieldTopToolbar() {
  2443. log.info("屏蔽顶部Toolbar");
  2444. return [
  2445. CSDNUtils.addBlockCSS("#csdn-toolbar"),
  2446. addStyle(
  2447. /*css*/
  2448. `
  2449. /* 内容顶部要归位 */
  2450. body #main,
  2451. .margin_sides{
  2452. margin-top: unset !important;
  2453. padding-top: unset !important;
  2454. }
  2455. #article .article_title{
  2456. margin-top: .32rem !important;
  2457. padding-top: unset !important;
  2458. }
  2459. `
  2460. )
  2461. ];
  2462. },
  2463. /**
  2464. * 重构底部推荐
  2465. */
  2466. refactoringRecommendation() {
  2467. function refactoring() {
  2468. log.info("重构底部推荐");
  2469. document.querySelectorAll(
  2470. ".container-fluid"
  2471. ).forEach((item) => {
  2472. var _a2, _b;
  2473. let url = "";
  2474. let title = "";
  2475. let content = "";
  2476. let img = "";
  2477. let isCSDNDownload = false;
  2478. let isCSDNEduDownload = false;
  2479. if (item.hasAttribute("data-url")) {
  2480. url = item.getAttribute("data-url");
  2481. title = (_a2 = item.querySelector(".recommend_title div.left")) == null ? void 0 : _a2.innerHTML;
  2482. if (!item.querySelector(".text")) {
  2483. return;
  2484. }
  2485. content = (_b = item.querySelector(".text")) == null ? void 0 : _b.innerHTML;
  2486. if (item.querySelectorAll(".recommend-img").length) {
  2487. item.querySelectorAll(".recommend-img").forEach((item2) => {
  2488. img += item2.innerHTML;
  2489. });
  2490. }
  2491. } else {
  2492. log.info("节点上无data-url");
  2493. url = item.querySelector("a[data-type]").getAttribute("href");
  2494. title = item.querySelector(".recommend_title div.left").innerHTML;
  2495. content = item.querySelector(".text").innerHTML;
  2496. }
  2497. var _URL_ = new URL(url);
  2498. if (_URL_.host === "download.csdn.net" || _URL_.host === "www.iteye.com" && _URL_.pathname.match(/^\/resource/gi)) {
  2499. log.info("该链接为csdn资源下载");
  2500. isCSDNDownload = true;
  2501. title = `<div class="component-box"><a class="praise" href="javascript:;">CSDN下载</a></div>` + title;
  2502. } else if (_URL_.origin.match(/edu.csdn.net/gi)) {
  2503. isCSDNEduDownload = true;
  2504. log.info("该链接为csdn学院下载");
  2505. title = `<div class="component-box"><a class="csdn-edu-title" href="javascript:;">CSDN学院</a></div>` + title;
  2506. }
  2507. item.setAttribute("class", "GM-csdn-dl");
  2508. item.setAttribute("data-url", url);
  2509. 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>`;
  2510. item.addEventListener("click", function() {
  2511. if (PopsPanel.getValue("m-csdn-blog-openNewTab")) {
  2512. window.open(url, "_blank");
  2513. } else {
  2514. window.location.href = url;
  2515. }
  2516. });
  2517. if ((isCSDNDownload || isCSDNEduDownload) && PopsPanel.getValue("m-csdn-blog-removeResourceArticle")) {
  2518. item.remove();
  2519. }
  2520. });
  2521. }
  2522. let lockFunction = new utils.LockFunction(refactoring, 50);
  2523. utils.waitNode("#recommend").then(($recommend) => {
  2524. log.info("重构底部推荐");
  2525. lockFunction.run();
  2526. utils.mutationObserver($recommend, {
  2527. callback: () => {
  2528. lockFunction.run();
  2529. },
  2530. config: { childList: true, subtree: true, attributes: true }
  2531. });
  2532. });
  2533. },
  2534. /**
  2535. * 屏蔽底部文章
  2536. */
  2537. blockBottomArticle() {
  2538. log.info("屏蔽底部文章");
  2539. return CSDNUtils.addBlockCSS("#recommend");
  2540. },
  2541. /**
  2542. * 屏蔽评论
  2543. */
  2544. blockComment() {
  2545. log.info("屏蔽评论");
  2546. return CSDNUtils.addBlockCSS("#comment");
  2547. },
  2548. /**
  2549. * 去除广告
  2550. */
  2551. removeAds() {
  2552. log.info("去除广告");
  2553. CSDNUtils.waitForElementToRemove(".passport-login-container");
  2554. CSDNUtils.waitForElementToRemove(
  2555. ".btn_open_app_prompt_box.detail-open-removed"
  2556. );
  2557. CSDNUtils.waitForElementToRemove(".add-firstAd");
  2558. CSDNUtils.waitForElementToRemove("div.feed-Sign-weixin");
  2559. CSDNUtils.waitForElementToRemove("div.ios-shadowbox");
  2560. },
  2561. /**
  2562. * 不限制代码块最大高度
  2563. */
  2564. notLimitCodePreMaxHeight() {
  2565. log.info("不限制代码块最大高度");
  2566. return addStyle(
  2567. /*css*/
  2568. `
  2569. pre{
  2570. max-height: unset !important;
  2571. }
  2572. `
  2573. );
  2574. },
  2575. /**
  2576. * 不限制评论区最大高度
  2577. */
  2578. notLimitCommentMaxHeight() {
  2579. log.info("不限制评论区最大高度");
  2580. return addStyle(
  2581. /*css*/
  2582. `
  2583. #comment{
  2584. max-height: none !important;
  2585. }
  2586. `
  2587. );
  2588. },
  2589. /**
  2590. * 允许选择文字
  2591. */
  2592. allowSelectText() {
  2593. log.info("允许选择文字");
  2594. return addStyle(
  2595. /*css*/
  2596. `
  2597. #content_views,
  2598. #content_views pre,
  2599. #content_views pre code{
  2600. webkit-touch-callout: text !important;
  2601. -webkit-user-select: text !important;
  2602. -khtml-user-select: text !important;
  2603. -moz-user-select: text !important;
  2604. -ms-user-select: text !important;
  2605. user-select: text !important;
  2606. }
  2607. `
  2608. );
  2609. },
  2610. /**
  2611. * 自动展开内容
  2612. */
  2613. autoExpandContent() {
  2614. log.info("自动展开内容");
  2615. return addStyle(
  2616. /*css*/
  2617. `
  2618. #content_views pre.set-code-hide,
  2619. .article_content{
  2620. height: 100% !important;
  2621. overflow: auto !important;
  2622. }
  2623. `
  2624. );
  2625. }
  2626. };
  2627. const ShieldCSS = "/* 右下角的买一年送3个月的广告图标 */\r\n.blind_box {\r\n display: none !important;\r\n}\r\n";
  2628. const M_CSDNWenKu = {
  2629. init() {
  2630. addStyle(ShieldCSS);
  2631. PopsPanel.execMenu("m-csdn-wenku-shieldBottomToolbar", () => {
  2632. this.shieldBottomToolbar();
  2633. });
  2634. },
  2635. /**
  2636. * 【屏蔽】底部工具栏
  2637. */
  2638. shieldBottomToolbar() {
  2639. log.info("【屏蔽】底部工具栏");
  2640. CSDNUtils.addBlockCSS(`.page-container > div.btn`);
  2641. }
  2642. };
  2643. const CSDNBlockCSS = "/* 右下角悬浮图标 买1年送3个月 */\r\n.page-container .blind_box,\r\n/* 底部工具栏右边的 开会员按钮(低至xx元/次) */\r\n.page-container .btn .ml-12,\r\n/* 登录弹窗 */\r\n.passport-login-container,\r\n/* 通用广告className匹配 */\r\n.ads {\r\n display: none !important;\r\n}\r\n";
  2644. const M_CSDNDownload = {
  2645. init() {
  2646. PopsPanel.execMenuOnce("m-csdn-download-removeAds", () => {
  2647. return addStyle(CSDNBlockCSS);
  2648. });
  2649. PopsPanel.execMenuOnce(
  2650. "m-csdn-download-automaticallyExpandResourceIntroduction",
  2651. () => {
  2652. return this.automaticallyExpandResourceIntroduction();
  2653. }
  2654. );
  2655. },
  2656. /**
  2657. * 自动展开资源介绍
  2658. */
  2659. automaticallyExpandResourceIntroduction() {
  2660. log.info("自动展开资源介绍");
  2661. return [
  2662. CSDNUtils.addBlockCSS("label.unfold-font"),
  2663. addStyle(
  2664. /*css*/
  2665. `
  2666. .resource-desc{
  2667. max-height: unset !important;
  2668. overflow: unset !important;
  2669. }
  2670. `
  2671. )
  2672. ];
  2673. }
  2674. };
  2675. const M_CSDN = {
  2676. init() {
  2677. if (CSDNRouter.isLink()) {
  2678. log.info("Router: 中转链接");
  2679. M_CSDNLink.init();
  2680. } else if (CSDNRouter.isHuaWeiCloudBlog()) {
  2681. log.info("Router: 华为云联盟");
  2682. M_CSDNHuaWeiCloud.init();
  2683. } else if (CSDNRouter.isBlog()) {
  2684. log.info("Router: 博客");
  2685. M_CSDNBlog.init();
  2686. } else if (CSDNRouter.isWenKu()) {
  2687. log.info("Router: 文库");
  2688. M_CSDNWenKu.init();
  2689. } else if (CSDNRouter.isDownload()) {
  2690. log.info("Router: 资源下载");
  2691. M_CSDNDownload.init();
  2692. } else {
  2693. log.error("暂未适配,请反馈开发者:" + globalThis.location.href);
  2694. }
  2695. }
  2696. };
  2697. PopsPanel.init();
  2698. let isMobile = utils.isPhone();
  2699. let CHANGE_ENV_SET_KEY = "change_env_set";
  2700. let chooseMode = _GM_getValue(CHANGE_ENV_SET_KEY);
  2701. GM_Menu.add({
  2702. key: CHANGE_ENV_SET_KEY,
  2703. text: `⚙ 自动: ${isMobile ? "移动端" : "PC端"}`,
  2704. autoReload: false,
  2705. isStoreValue: false,
  2706. showText(text) {
  2707. if (chooseMode == null) {
  2708. return text;
  2709. }
  2710. return text + ` 手动: ${chooseMode == 1 ? "移动端" : chooseMode == 2 ? "PC端" : "未知"}`;
  2711. },
  2712. callback: () => {
  2713. let allowValue = [0, 1, 2];
  2714. let chooseText = window.prompt(
  2715. "请输入当前脚本环境判定\n\n自动判断: 0\n移动端: 1\nPC端: 2",
  2716. "0"
  2717. );
  2718. if (!chooseText) {
  2719. return;
  2720. }
  2721. let chooseMode2 = parseInt(chooseText);
  2722. if (isNaN(chooseMode2)) {
  2723. Qmsg.error("输入的不是规范的数字");
  2724. return;
  2725. }
  2726. if (!allowValue.includes(chooseMode2)) {
  2727. Qmsg.error("输入的值必须是0或1或2");
  2728. return;
  2729. }
  2730. if (chooseMode2 == 0) {
  2731. _GM_deleteValue(CHANGE_ENV_SET_KEY);
  2732. } else {
  2733. _GM_setValue(CHANGE_ENV_SET_KEY, chooseMode2);
  2734. }
  2735. }
  2736. });
  2737. if (chooseMode != null) {
  2738. log.info(`手动判定为${chooseMode === 1 ? "移动端" : "PC端"}`);
  2739. if (chooseMode == 1) {
  2740. M_CSDN.init();
  2741. } else if (chooseMode == 2) {
  2742. CSDN.init();
  2743. } else {
  2744. Qmsg.error("意外,手动判定的值不在范围内");
  2745. _GM_deleteValue(CHANGE_ENV_SET_KEY);
  2746. }
  2747. } else {
  2748. if (isMobile) {
  2749. log.info("自动判定为移动端");
  2750. M_CSDN.init();
  2751. } else {
  2752. log.info("自动判定为PC端");
  2753. CSDN.init();
  2754. }
  2755. }
  2756.  
  2757. })(Qmsg, DOMUtils, Utils, pops);