// ==UserScript== // @name 论坛文章页宽屏 // @version 1.1.0 // @description 适配了微信公众号、知乎、掘金、简书,贴吧,百度搜索 // @author sakura-flutter // @namespace https://github.com/sakura-flutter // @compatible chrome >= 80 // @compatible firefox >= 75 // @run-at document-start // @match https://mp.weixin.qq.com/s* // @match https://zhuanlan.zhihu.com/p/* // @match https://www.zhihu.com/question/* // @match https://juejin.im/post/* // @match https://www.jianshu.com/p/* // @match https://www.baidu.com/s?* // @match https://www.baidu.com/ // @match https://tieba.baidu.com/p/* // @grant unsafeWindow // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @require https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js // @require https://greasyfork.org/scripts/411093-toast/code/Toast.js?version=847261 // @downloadURL none // ==/UserScript== /* global Vue Toast */ (function() { 'use strict' const isDebug = false const $ = document.querySelector.bind(document) const $$ = document.querySelectorAll.bind(document) function log(...args) { if (!isDebug) return console.log(...args) } // 主函数 function main() { const sites = checkWebsites() sites.forEach(site => { const hanlder = handlers.get(site) log(site) hanlder && hanlder() }) } // 检查网站 function checkWebsites() { const { origin, pathname } = location const url = origin + pathname // 格式[ ['xx', true|false], ] const sites = [ ['mpWeixin', /mp.weixin.qq.com\/s/.test(url)], ['zhihu', /zhuanlan.zhihu.com\/p\//.test(url) || /zhihu.com\/question\//.test(url)], ['juejin', /juejin.im\/post\//.test(url)], ['jianshu', /jianshu.com\/p\//.test(url)], ['baidu', /www.baidu.com\/s?/.test(url)], ['tieba', /tieba.baidu.com\/p\//.test(url)], ] // 返回匹配的页面 return sites .filter(item => item[1]) .map(item => item[0]) } // 对应网页要执行的操作操作 const handlers = new Map() /* ===微信文章===start */ handlers.set('mpWeixin', function() { const store = createStore('mpWeixin') function execute() { GM_addStyle(` /* 文章宽屏 */ .rich_media_area_primary_inner { max-width: 100vw !important; } /* 二维码位置 */ #js_pc_qr_code .qr_code_pc { position: fixed; top: 25vh; right: 3vw; opacity: .4;} #js_pc_qr_code .qr_code_pc:hover { opacity: 1;} @media screen and (min-width: 1024px) { .rich_media_area_primary_inner { max-width: 75vw !important; } #js_pc_qr_code .qr_code_pc { position: fixed; top: 25vh; right: 3vw; } } `) window.addEventListener('DOMContentLoaded', () => { // 文章图片宽高(仅对大图处理) const imgEls = $$('.rich_media_area_primary_inner img') imgEls.forEach(img => { img.addEventListener('load', () => { // 页面本身对图片有宽高处理,延时后再处理 setTimeout(() => { const width = parseFloat(getComputedStyle(img).width) if (width >= 400) { img.style.cssText += 'width: auto !important; height: auto !important;' } },16) }) }) }) } createWidescreenControl({ store, execute }) }) /* ===微信文章===end */ /* ===知乎===start */ handlers.set('zhihu', function() { const store = createStore('zhihu') function execute() { GM_addStyle(` /* 知乎专栏 */ .Post-NormalMain .Post-Header, .Post-NormalMain>div, .Post-NormalSub>div { width: 65vw; min-width: 690px; } .Post-SideActions { left: calc((100vw - 82vw)/2); } /* 知乎问答 */ .QuestionHeader-content, .QuestionHeader-footer { width: 75vw; min-width: 1000px; margin-left: auto; margin-right: auto; } .QuestionHeader-footer-inner { width: auto; } .QuestionHeader-footer-main { padding-left: 0; } .QuestionHeader-main { width: auto; flex: 1; } .Question-main { width: 75vw; min-width: 1000px; } .Question-main .ListShortcut { flex: 1; } .Question-mainColumn { flex: 1; width: auto; padding-right: 10px; } `) } createWidescreenControl({ store, execute }) }) /* ===知乎===end */ /* ===掘金===start */ handlers.set('juejin', function() { const store = createStore('juejin') function execute() { GM_addStyle(` /* 掘金文章 */ @media screen and (min-width: 1300px) { .main-container { max-width: 75vw; } .main-container .main-area { width: calc(100% - 21rem); } } `) } createWidescreenControl({ store, execute }) }) /* ===掘金===end */ /* ===简书===start */ handlers.set('jianshu', function() { const store = createStore('jianshu') function execute() { GM_addStyle(` /* 简书文章 */ @media screen and (min-width: 1250px) { [role=main] > div:first-child { flex: 1; width: auto; } } @media screen and (min-width: 1250px) { [role=main] { width: 85vw; } #__next > div:last-child { left: 30px; } } @media screen and (min-width: 1450px) { [role=main] { width: 75vw; } #__next > div:last-child { left: 7vw; } } `) } createWidescreenControl({ store, execute }) }) /* ===简书===end */ /* ===百度搜索===start */ handlers.set('baidu', function() { const store = createStore('baidu') function execute() { const styleEl = GM_addStyle(` :root { --inject-page-width: 70vw; } @media screen and (min-width: 1490px) { /* 顶部搜索 */ .head_wrapper .s_form { margin-left: auto; margin-right: auto; width: fit-content; width: -moz-fit-content; } /* 搜索tab */ .s_tab { padding-left: 0 !important; } .s_tab { margin-left: auto; margin-right: auto; width: fit-content; width: -moz-fit-content; } /* 搜索内容 */ #container { margin-left: auto !important; margin-right: auto !important; } /* 仅对新闻流处理宽屏 */ .container_new { width: var(--inject-page-width) !important; } /* 左侧搜索结果 */ .container_new #content_left { width: calc(var(--inject-page-width) - 450px) !important; } .container_new #content_left > div { width: 100% !important; } .container_new #content_left .new-pmd .c-span9 { width: 70%; } .container_new #content_left .c-group-wrapper .c-group { width: 95% !important; } /* 分页 */ .page-inner { margin-left: auto; margin-right: auto; padding-left: 0 !important; width: var(--inject-page-width); } /* 页脚 */ .foot-inner { margin-left: auto; margin-right: auto; width: var(--inject-page-width); } #foot .foot-inner #help { padding-left: 0 !important; } } `) // 搜索时百度会清除文档这里需要将样式重新插入 function redo() { if (document.head.contains(styleEl)) return document.head.appendChild(styleEl) } window.addEventListener('DOMContentLoaded', () => { const { jQuery } = unsafeWindow jQuery(document).ajaxSuccess((event, xhr, settings) => { if (!settings.url.startsWith('/s?')) return redo() }) }) window.addEventListener('popstate', redo) } createWidescreenControl({ store, execute }) }) /* ===百度搜索===end */ /* ===贴吧===start */ handlers.set('tieba', function() { const store = createStore('tieba') function execute() { GM_addStyle(` /* 帖子 */ @media screen and (min-width: 1390px) { #container { width: 70vw; } #container > .content { width: 100%; } .nav_wrap, .p_thread, .pb_content, .core_title_wrap_bright, .l_post_bright, .core_reply_wrapper, .l_post_bright .core_reply_wrapper, .pb_footer { width: 100%; } .core_title_absolute_bright { width: calc(70vw - 240px); } /* 内容区域 */ .pb_content { display: flex; background-size: 100%; } .pb_content::after { content: none; } /* 楼区域 */ .left_section { flex: 1; border-right: 2px solid #e4e6eb; } /* 楼层 */ .l_post_bright { display: flex; } .l_post_bright .d_post_content_main{ width: auto; flex: 1; } /* 右侧悬浮按钮 */ .tbui_aside_float_bar { left: auto; right: 11vw; margin-left: 0; } } `) } createWidescreenControl({ store, execute }) }) /* ===贴吧===end */ // 存储 以网站作为模块 function createStore(sitename) { if (!sitename) throw new TypeError('缺少sitename,期望') const getRealProp = property => `${sitename}_${property}` const target = {} const handler = { get(target, property) { const realProp = getRealProp(property) let value = target[realProp] if (value == null) { value = GM_getValue(realProp) target[realProp] = value } return value }, set(target, property, value) { const realProp = getRealProp(property) target[realProp] = value GM_setValue(realProp, value) return true }, deleteProperty(target, property) { const realProp = getRealProp(property) const deleted = delete target[realProp] GM_deleteValue(realProp) return deleted }, } const store = new Proxy(target, handler) return store } // 添加按钮样式 GM_addStyle(` .inject-widescreen-js { position: fixed; z-index: 99; top: 150px; right: 8vw; opacity: .5; border: none; color :#fff; padding: 6px 12px; font-size: 14px; background: #3385ff; box-shadow: 0 1px 6px rgba(0,0,0,.2); transition: opacity .3s; } .inject-widescreen-js:hover { opacity: 1; } `) // 宽屏开关 options: store, execute要执行的函数 function createWidescreenControl(options) { const { store, execute } = options const buttonComponent = new Vue({ template: ` `, data() { return { isOpen: store.is_open || false, } }, beforeCreate() { store.is_open && (execute(), Toast('已宽屏处理')) }, methods: { async toggle() { store.is_open = !this.isOpen location.reload() } }, }).$mount() window.addEventListener('DOMContentLoaded', () => { document.body.appendChild(buttonComponent.$el) }) } main() })();