// ==UserScript== // @name 简书优化 // @namespace https://github.com/WhiteSevs/TamperMonkeyScript // @version 2025.7.11 // @author WhiteSevs // @description 支持手机端和PC端、屏蔽广告、优化浏览体验、重定向链接、全文居中、自动展开全文、允许复制文字、劫持唤醒/跳转App、自定义屏蔽元素等 // @license GPL-3.0-only // @icon data:image/png;base64,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 // @supportURL https://github.com/WhiteSevs/TamperMonkeyScript/issues // @match *://*.jianshu.com/* // @match *://*.jianshu.io/* // @require https://fastly.jsdelivr.net/gh/WhiteSevs/TamperMonkeyScript@86be74b83fca4fa47521cded28377b35e1d7d2ac/lib/CoverUMD/index.js // @require https://fastly.jsdelivr.net/npm/@whitesev/utils@2.7.0/dist/index.umd.js // @require https://fastly.jsdelivr.net/npm/@whitesev/domutils@1.5.11/dist/index.umd.js // @require https://fastly.jsdelivr.net/npm/@whitesev/pops@2.1.11/dist/index.umd.js // @require https://fastly.jsdelivr.net/npm/qmsg@1.3.8/dist/index.umd.js // @connect * // @grant GM_deleteValue // @grant GM_getResourceText // @grant GM_getValue // @grant GM_info // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_unregisterMenuCommand // @grant GM_xmlhttpRequest // @grant unsafeWindow // @run-at document-start // @downloadURL none // ==/UserScript== (function (Qmsg, DOMUtils, Utils, pops) { 'use strict'; const blockCSS = `.download-app-guidance,\r .call-app-btn,\r .collapse-tips,\r .note-graceful-button,\r .app-open,\r .header-wrap,\r .recommend-wrap.recommend-ad,\r .call-app-Ad-bottom,\r #recommended-notes p.top-title span.more,\r #homepage .modal,\r button.index_call-app-btn,\r span.note__flow__download,\r .download-guide,\r #footer,\r .comment-open-app-btn-wrap,\r .nav.navbar-nav + div,\r .self-flow-ad,\r #free-reward-panel,\r div[id*='AdFive'],\r #index-aside-download-qrbox,\r .baidu-app-download-2eIkf_1,\r /* 底部的"小礼物走一走,来简书关注我"、赞赏支持和更多精彩内容,就在简书APP */\r div[role="main"] > div > section:first-child > div:nth-last-child(2),\r /* 它的内部是script标签,可能影响部分评论之间的高度问题 */\r div.adad_container ,\r /* 顶部导航栏的【下载App】 */\r #__next nav a[href*="navbar-app"] {\r display: none !important;\r }\r body.reader-day-mode.normal-size {\r overflow: auto !important;\r }\r .collapse-free-content {\r height: auto !important;\r }\r .copyright {\r color: #000 !important;\r }\r #note-show .content .show-content-free .collapse-free-content:after {\r background-image: none !important;\r }\r footer > div > div {\r justify-content: center;\r }\r /* 修复底部最后编辑于:。。。在某些套壳浏览器上的错位问题 */\r #note-show .content .show-content-free .note-meta-time {\r margin-top: 0px !important;\r }\r `; var _GM_deleteValue = /* @__PURE__ */ (() => typeof GM_deleteValue != "undefined" ? GM_deleteValue : void 0)(); var _GM_getResourceText = /* @__PURE__ */ (() => typeof GM_getResourceText != "undefined" ? GM_getResourceText : void 0)(); var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)(); var _GM_info = /* @__PURE__ */ (() => typeof GM_info != "undefined" ? GM_info : void 0)(); var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)(); var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)(); var _GM_unregisterMenuCommand = /* @__PURE__ */ (() => typeof GM_unregisterMenuCommand != "undefined" ? GM_unregisterMenuCommand : void 0)(); var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)(); var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)(); var _monkeyWindow = /* @__PURE__ */ (() => window)(); const KEY = "GM_Panel"; const ATTRIBUTE_INIT = "data-init"; const ATTRIBUTE_KEY = "data-key"; const ATTRIBUTE_DEFAULT_VALUE = "data-default-value"; const ATTRIBUTE_INIT_MORE_VALUE = "data-init-more-value"; const PROPS_STORAGE_API = "data-storage-api"; const PanelUISize = { /** * 一般设置界面的尺寸 */ setting: { get width() { if (window.innerWidth < 550) { return "88vw"; } else if (window.innerWidth < 700) { return "550px"; } else { return "700px"; } }, get height() { if (window.innerHeight < 450) { return "70vh"; } else if (window.innerHeight < 550) { return "450px"; } else { return "550px"; } } } }; class StorageUtils { /** 存储的键名 */ storageKey; listenerData; /** * 存储的键名,可以是多层的,如:a.b.c * * 那就是 * { * "a": { * "b": { * "c": { * ...你的数据 * } * } * } * } * @param key */ constructor(key) { if (typeof key === "string") { let trimKey = key.trim(); if (trimKey == "") { throw new Error("key参数不能为空字符串"); } this.storageKey = trimKey; } else { throw new Error("key参数类型错误,必须是字符串"); } this.listenerData = new Utils.Dictionary(); } /** * 获取本地值 */ getLocalValue() { let localValue = _GM_getValue(this.storageKey); if (localValue == null) { localValue = {}; this.setLocalValue(localValue); } return localValue; } /** * 设置本地值 * @param value */ setLocalValue(value) { _GM_setValue(this.storageKey, value); } /** * 设置值 * @param key 键 * @param value 值 */ set(key, value) { let oldValue = this.get(key); let localValue = this.getLocalValue(); Reflect.set(localValue, key, value); this.setLocalValue(localValue); this.triggerValueChangeListener(key, oldValue, value); } /** * 获取值 * @param key 键 * @param defaultValue 默认值 */ get(key, defaultValue) { let localValue = this.getLocalValue(); return Reflect.get(localValue, key) ?? defaultValue; } /** * 获取所有值 */ getAll() { let localValue = this.getLocalValue(); return localValue; } /** * 删除值 * @param key 键 */ delete(key) { let oldValue = this.get(key); let localValue = this.getLocalValue(); Reflect.deleteProperty(localValue, key); this.setLocalValue(localValue); this.triggerValueChangeListener(key, oldValue, void 0); } /** * 判断是否存在该值 */ has(key) { let localValue = this.getLocalValue(); return Reflect.has(localValue, key); } /** * 获取所有键 */ keys() { let localValue = this.getLocalValue(); return Reflect.ownKeys(localValue); } /** * 获取所有值 */ values() { let localValue = this.getLocalValue(); return Reflect.ownKeys(localValue).map( (key) => Reflect.get(localValue, key) ); } /** * 清空所有值 */ clear() { _GM_deleteValue(this.storageKey); } /** * 监听值改变 * + .set * + .delete * @param key 监听的键 * @param callback 值改变的回调函数 */ addValueChangeListener(key, callback) { let listenerId = Math.random(); let listenerData = this.listenerData.get(key) || []; listenerData.push({ id: listenerId, key, callback }); this.listenerData.set(key, listenerData); return listenerId; } /** * 移除监听 * @param listenerId 监听的id或键名 */ removeValueChangeListener(listenerId) { let flag = false; for (const [key, listenerData] of this.listenerData.entries()) { for (let index = 0; index < listenerData.length; index++) { const value = listenerData[index]; if (typeof listenerId === "string" && value.key === listenerId || typeof listenerId === "number" && value.id === listenerId) { listenerData.splice(index, 1); index--; flag = true; } } this.listenerData.set(key, listenerData); } return flag; } /** * 主动触发监听器 * @param key 键 * @param oldValue (可选)旧值 * @param newValue (可选)新值 */ triggerValueChangeListener(key, oldValue, newValue) { if (!this.listenerData.has(key)) { return; } let listenerData = this.listenerData.get(key); for (let index = 0; index < listenerData.length; index++) { const data = listenerData[index]; if (typeof data.callback === "function") { let value = this.get(key); let __newValue; let __oldValue; if (typeof oldValue !== "undefined" && arguments.length >= 2) { __oldValue = oldValue; } else { __oldValue = value; } if (typeof newValue !== "undefined" && arguments.length > 2) { __newValue = newValue; } else { __newValue = value; } data.callback(key, __oldValue, __newValue); } } } } const PopsPanelStorageApi = new StorageUtils(KEY); const PanelContent = { $data: { /** * @private */ __contentConfig: null, get contentConfig() { if (this.__contentConfig == null) { this.__contentConfig = new utils.Dictionary(); } return this.__contentConfig; } }, /** * 设置所有配置项,用于初始化默认的值 * * 如果是第一组添加的话,那么它默认就是设置菜单打开的配置 * @param configList 配置项 */ addContentConfig(configList) { if (!Array.isArray(configList)) { configList = [configList]; } let index = this.$data.contentConfig.keys().length; this.$data.contentConfig.set(index, configList); }, /** * 获取所有的配置内容,用于初始化默认的值 */ getAllContentConfig() { return this.$data.contentConfig.values().flat(); }, /** * 获取配置内容 * @param index 配置索引 */ getConfig(index = 0) { return this.$data.contentConfig.get(index) ?? []; }, /** * 获取默认左侧底部的配置项 */ getDefaultBottomContentConfig() { return [ { id: "script-version", title: `版本:${_GM_info?.script?.version || "未知"}`, isBottom: true, forms: [], clickFirstCallback(event, rightHeaderElement, rightContainerElement) { window.open( _GM_info?.script?.namespace || "https://github.com/WhiteSevs/TamperMonkeyScript", "_blank" ); return false; } } ]; } }; const PanelMenu = { $data: { __menuOption: [ { key: "show_pops_panel_setting", text: "⚙ 设置", autoReload: false, isStoreValue: false, showText(text) { return text; }, callback: () => { Panel.showPanel(PanelContent.getConfig(0)); } } ], get menuOption() { return this.__menuOption; } }, init() { this.initExtensionsMenu(); }, /** * 初始化菜单项 */ initExtensionsMenu() { if (!Panel.isTopWindow()) { return; } GM_Menu.add(this.$data.menuOption); }, /** * 添加菜单项 * @param option 菜单配置 */ addMenuOption(option) { if (!Array.isArray(option)) { option = [option]; } this.$data.menuOption.push(...option); }, /** * 更新菜单项 * @param option 菜单配置 */ updateMenuOption(option) { if (!Array.isArray(option)) { option = [option]; } option.forEach((optionItem) => { let findIndex = this.$data.menuOption.findIndex((it) => { return it.key === optionItem.key; }); if (findIndex !== -1) { this.$data.menuOption[findIndex] = optionItem; } }); }, /** * 获取菜单项 * @param [index=0] 索引 */ getMenuOption(index = 0) { return this.$data.menuOption[index]; }, /** * 删除菜单项 * @param [index=0] 索引 */ deleteMenuOption(index = 0) { this.$data.menuOption.splice(index, 1); } }; const Panel = { /** 数据 */ $data: { /** * @private */ __configDefaultValueData: null, /** * @private */ __onceExecMenuData: null, /** * @private */ __onceExecData: null, /** * @private */ __panelConfig: {}, $panel: null, /** * 菜单项的默认值 */ get configDefaultValueData() { if (this.__configDefaultValueData == null) { this.__configDefaultValueData = new utils.Dictionary(); } return this.__configDefaultValueData; }, /** * 成功只执行了一次的项 */ get onceExecMenuData() { if (this.__onceExecMenuData == null) { this.__onceExecMenuData = new utils.Dictionary(); } return this.__onceExecMenuData; }, /** * 成功只执行了一次的项 */ get onceExecData() { if (this.__onceExecData == null) { this.__onceExecData = new utils.Dictionary(); } return this.__onceExecData; }, /** 脚本名,一般用在设置的标题上 */ get scriptName() { return SCRIPT_NAME; }, /** * pops.panel的默认配置 */ get panelConfig() { return this.__panelConfig; }, set panelConfig(value) { this.__panelConfig = value; }, /** 菜单项的总值在本地数据配置的键名 */ key: KEY, /** 菜单项在attributes上配置的菜单键 */ attributeKeyName: ATTRIBUTE_KEY, /** 菜单项在attributes上配置的菜单默认值 */ attributeDefaultValueName: ATTRIBUTE_DEFAULT_VALUE }, init() { this.initContentDefaultValue(); PanelMenu.init(); }, /** 判断是否是顶层窗口 */ isTopWindow() { return _unsafeWindow.top === _unsafeWindow.self; }, /** 初始化菜单项的默认值保存到本地数据中 */ initContentDefaultValue() { const initDefaultValue = (config) => { if (!config.attributes) { return; } if (config.type === "button" || config.type === "forms" || config.type === "deepMenu") { return; } let needInitConfig = {}; let key = config.attributes[ATTRIBUTE_KEY]; if (key != null) { needInitConfig[key] = config.attributes[ATTRIBUTE_DEFAULT_VALUE]; } let __attr_init__ = config.attributes[ATTRIBUTE_INIT]; if (typeof __attr_init__ === "function") { let __attr_result__ = __attr_init__(); if (typeof __attr_result__ === "boolean" && !__attr_result__) { return; } } let initMoreValue = config.attributes[ATTRIBUTE_INIT_MORE_VALUE]; if (initMoreValue && typeof initMoreValue === "object") { Object.assign(needInitConfig, initMoreValue); } let needInitConfigList = Object.keys(needInitConfig); if (!needInitConfigList.length) { log.warn(["请先配置键", config]); return; } needInitConfigList.forEach((__key) => { let __defaultValue = needInitConfig[__key]; this.setDefaultValue(__key, __defaultValue); }); }; const loopInitDefaultValue = (configList) => { for (let index = 0; index < configList.length; index++) { let configItem = configList[index]; initDefaultValue(configItem); let childForms = configItem.forms; if (childForms && Array.isArray(childForms)) { loopInitDefaultValue(childForms); } } }; const contentConfigList = [...PanelContent.getAllContentConfig()]; for (let index = 0; index < contentConfigList.length; index++) { let leftContentConfigItem = contentConfigList[index]; if (!leftContentConfigItem.forms) { continue; } const rightContentConfigList = leftContentConfigItem.forms; if (rightContentConfigList && Array.isArray(rightContentConfigList)) { loopInitDefaultValue(rightContentConfigList); } } }, /** * 设置初始化使用的默认值 */ setDefaultValue(key, defaultValue) { if (this.$data.configDefaultValueData.has(key)) { log.warn("请检查该key(已存在): " + key); } this.$data.configDefaultValueData.set(key, defaultValue); }, /** * 设置值 * @param key 键 * @param value 值 */ setValue(key, value) { PopsPanelStorageApi.set(key, value); }, /** * 获取值 * @param key 键 * @param defaultValue 默认值 */ getValue(key, defaultValue) { let localValue = PopsPanelStorageApi.get(key); if (localValue == null) { if (this.$data.configDefaultValueData.has(key)) { return this.$data.configDefaultValueData.get(key); } return defaultValue; } return localValue; }, /** * 删除值 * @param key 键 */ deleteValue(key) { PopsPanelStorageApi.delete(key); }, /** * 判断该键是否存在 * @param key 键 */ hasKey(key) { return PopsPanelStorageApi.has(key); }, /** * 监听调用setValue、deleteValue * @param key 需要监听的键 * @param callback */ addValueChangeListener(key, callback) { let listenerId = PopsPanelStorageApi.addValueChangeListener( key, (__key, __newValue, __oldValue) => { callback(key, __oldValue, __newValue); } ); return listenerId; }, /** * 移除监听 * @param listenerId 监听的id */ removeValueChangeListener(listenerId) { PopsPanelStorageApi.removeValueChangeListener(listenerId); }, /** * 主动触发菜单值改变的回调 * @param key 菜单键 * @param newValue 想要触发的新值,默认使用当前值 * @param oldValue 想要触发的旧值,默认使用当前值 */ triggerMenuValueChange(key, newValue, oldValue) { PopsPanelStorageApi.triggerValueChangeListener(key, oldValue, newValue); }, /** * 移除已执行的仅执行一次的菜单 * @param key 键 */ deleteExecMenuOnce(key) { this.$data.onceExecMenuData.delete(key); let flag = PopsPanelStorageApi.removeValueChangeListener(key); return flag; }, /** * 移除已执行的仅执行一次的菜单 * @param key 键 */ deleteOnceExec(key) { this.$data.onceExecData.delete(key); }, /** * 执行菜单 * * @param queryKey 键|键数组 * @param callback 执行的回调函数 * @param checkExec 判断是否执行回调 * * (默认)如果想要每个菜单是`与`关系,即每个菜单都判断为开启,那么就判断它们的值&就行 * * 如果想要任意菜单存在true再执行,那么判断它们的值|就行 * * + 返回值都为`true`,执行回调,如果回调返回了