CSDN优化

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

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

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

QingJ © 2025

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