Greasy Fork

Greasy Fork is available in English.

Blog Widescreen Responsive

Expands blog articles to use full widescreen space by removing restrictive max-width constraints on Substack, Medium, Ghost, WordPress and other platforms

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Blog Widescreen Responsive
// @namespace    http://greasyfork.icu/users/umsibaba
// @version      2.5.0
// @description  Expands blog articles to use full widescreen space by removing restrictive max-width constraints on Substack, Medium, Ghost, WordPress and other platforms
// @author       umsibaba
// @match        https://*.substack.com/*
// @match        https://substack.com/*
// @match        https://*.zerodha.com/*   
// @match        https://*.medium.com/*
// @match        https://medium.com/*
// @match        https://*.ghost.io/*
// @match        https://*.ghost.org/*
// @match        https://*.wordpress.com/*
// @match        https://*.wordpress.org/*
// @match        https://*.blogspot.com/*
// @match        https://*.blogger.com/*
// @match        https://*.dev.to/*
// @match        https://dev.to/*
// @match        https://*.hashnode.dev/*
// @match        https://*.notion.site/*
// @match        https://*.beehiiv.com/*
// @match        https://*.convertkit.com/*
// @match        https://*.mailchimp.com/*
// @match        https://*.github.io/*
// @match        https://*.netlify.app/*
// @match        https://*.vercel.app/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @supportURL   http://greasyfork.icu/scripts/yourscriptid/feedback
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    
    // Configuration
    const CONFIG = {
        maxWidth: GM_getValue('maxWidth', '95%'),
        padding: GM_getValue('padding', '2rem'),
        enabled: GM_getValue('enabled', true),
        preserveReadability: GM_getValue('preserveReadability', false),
        animationDuration: '0.3s'
    };
    
    // Platform-specific selectors using modern CSS techniques
    const PLATFORM_SELECTORS = {
        // Substack selectors
        substack: [
            '.single-post',
            '.post-content',
            '.reader2-post-content',
            '.post-header',
            '.frontend-pencraft-Box-module__Box--4o0Ow',
            'article[data-testid="post-content"]',
            '.post',
            'main article'
        ],
        
        // Medium selectors
        medium: [
            'article',
            '.postArticle-content',
            '.meteredContent',
            'main article',
            '[data-testid="storyBody"]',
            '.ab.cd.ce.cf.cg'
        ],
        
        // Ghost selectors
        ghost: [
            '.post-content',
            '.post-full-content',
            'article.post',
            '.gh-content',
            '.gh-article',
            'main article'
        ],
        
        // WordPress selectors
        wordpress: [
            '.post-content',
            '.entry-content',
            'article.post',
            '.single-post-container',
            'main article',
            '.wp-block-post-content'
        ],
        
        // Dev.to selectors
        devto: [
            '#article-wrapper',
            '.crayons-article',
            'article[data-article-path]',
            'main .crayons-article__main'
        ],
        
        // Hashnode selectors
        hashnode: [
            '.prose',
            'article',
            '.post-content-wrapper'
        ],
        
        // Generic blog selectors
        generic: [
            'article',
            '.post',
            '.post-content',
            '.entry-content',
            '.content',
            'main article',
            '[role="main"] article'
        ]
    };
    
    // Detect platform
    function detectPlatform() {
        const hostname = window.location.hostname.toLowerCase();
        
        if (hostname.includes('substack')) return 'substack';
        if (hostname.includes('medium')) return 'medium';
        if (hostname.includes('ghost')) return 'ghost';
        if (hostname.includes('wordpress') || hostname.includes('wp.')) return 'wordpress';
        if (hostname.includes('dev.to')) return 'devto';
        if (hostname.includes('hashnode')) return 'hashnode';
        
        return 'generic';
    }
    
    // Modern CSS styles using 2024/2025 features
    function createStyles() {
        return `
            /* Blog Widescreen Responsive - Fixed to expand content, not constrain it */
            
            /* CSS Custom Properties for dynamic theming */
            :root {
                --bwr-max-width: ${CONFIG.maxWidth};
                --bwr-padding: ${CONFIG.padding};
                --bwr-transition: all ${CONFIG.animationDuration} ease-in-out;
                --bwr-reading-measure: ${CONFIG.preserveReadability ? '75ch' : 'none'};
            }
            
            /* Remove restrictive max-width constraints from blog platforms */
            ${PLATFORM_SELECTORS[detectPlatform()].concat(PLATFORM_SELECTORS.generic)
                .map(selector => selector)
                .join(',\n            ')} {
                max-width: var(--bwr-max-width) !important;
                width: 100% !important;
                margin-left: auto !important;
                margin-right: auto !important;
                padding-left: var(--bwr-padding) !important;
                padding-right: var(--bwr-padding) !important;
                transition: var(--bwr-transition) !important;
                box-sizing: border-box !important;
            }
            
            /* Override platform-specific narrow constraints */
            .bwr-enhanced,
            .bwr-enhanced * {
                max-width: none !important;
            }
            
            /* Re-apply our desired max-width only to the main container */
            .bwr-enhanced {
                max-width: var(--bwr-max-width) !important;
                width: 100% !important;
                margin: 0 auto !important;
                padding-left: var(--bwr-padding) !important;
                padding-right: var(--bwr-padding) !important;
            }
            
            /* Typography enhancement - only if preserveReadability is enabled */
            ${CONFIG.preserveReadability ? `
            .bwr-enhanced :where(p, li, blockquote) {
                max-width: var(--bwr-reading-measure) !important;
                margin-left: auto !important;
                margin-right: auto !important;
            }` : ''}
            
            /* Responsive images and media - make them use full available width */
            .bwr-enhanced :where(img, video, iframe, embed, object, figure) {
                max-width: 100% !important;
                width: auto !important;
                height: auto !important;
                display: block !important;
                margin-left: auto !important;
                margin-right: auto !important;
            }
            
            /* Code blocks responsive handling */
            .bwr-enhanced :where(pre, code) {
                max-width: 100% !important;
                overflow-x: auto !important;
                white-space: pre-wrap !important;
                word-wrap: break-word !important;
            }
            
            /* Platform-specific fixes to remove narrow constraints */
            
            /* Substack specific overrides */
            .substack-post-content,
            .single-post,
            .post-content,
            .reader2-post-content,
            .frontend-pencraft-Box-module__Box--4o0Ow {
                max-width: var(--bwr-max-width) !important;
                width: 100% !important;
            }
            
            /* Medium specific overrides */
            .postArticle-content,
            .meteredContent,
            [data-testid="storyBody"] {
                max-width: var(--bwr-max-width) !important;
                width: 100% !important;
            }
            
            /* Ghost specific overrides */
            .post-content,
            .post-full-content,
            .gh-content,
            .gh-article {
                max-width: var(--bwr-max-width) !important;
                width: 100% !important;
            }
            
            /* WordPress specific overrides */
            .entry-content,
            .post-content,
            .wp-block-post-content {
                max-width: var(--bwr-max-width) !important;
                width: 100% !important;
            }
            
            /* Responsive breakpoints */
            @media (max-width: 768px) {
                .bwr-enhanced {
                    padding-left: 1rem !important;
                    padding-right: 1rem !important;
                }
            }
            
            @media (min-width: 1600px) {
                .bwr-enhanced {
                    max-width: 95% !important;
                }
            }
            
            @media (min-width: 1920px) {
                .bwr-enhanced {
                    max-width: 90% !important;
                }
            }
            
            /* Dark mode support */
            @media (prefers-color-scheme: dark) {
                .bwr-enhanced {
                    color-scheme: dark;
                }
            }
            
            /* Reduced motion support */
            @media (prefers-reduced-motion: reduce) {
                .bwr-enhanced {
                    transition: none !important;
                }
            }
            
            /* Status indicator */
            .bwr-status {
                position: fixed;
                top: 10px;
                right: 10px;
                background: #4CAF50;
                color: white;
                padding: 8px 12px;
                border-radius: 6px;
                font-size: 12px;
                font-family: system-ui, -apple-system, sans-serif;
                z-index: 10000;
                opacity: 0;
                transform: translateX(100%);
                transition: all 0.3s ease;
                cursor: pointer;
                user-select: none;
            }
            
            .bwr-status.show {
                opacity: 1;
                transform: translateX(0);
            }
            
            .bwr-status.disabled {
                background: #f44336;
            }
        `;
    }
    
    // Enhanced element detection using modern selectors
    function findContentElements() {
        const platform = detectPlatform();
        const selectors = PLATFORM_SELECTORS[platform].concat(PLATFORM_SELECTORS.generic);
        
        for (const selector of selectors) {
            const elements = document.querySelectorAll(selector);
            if (elements.length > 0) {
                return Array.from(elements).filter(el => {
                    // Use getBoundingClientRect for better detection
                    const rect = el.getBoundingClientRect();
                    return rect.width > 100 && rect.height > 100;
                });
            }
        }
        
        return [];
    }
    
    // Apply enhancements to elements
    function applyEnhancements() {
        if (!CONFIG.enabled) return;
        
        const elements = findContentElements();
        
        elements.forEach(element => {
            if (!element.classList.contains('bwr-enhanced')) {
                element.classList.add('bwr-enhanced');
                
                // Add container query support for modern browsers
                if (CSS.supports('container-type: inline-size')) {
                    element.style.containerType = 'inline-size';
                }
            }
        });
        
        showStatus(`Enhanced ${elements.length} elements`);
    }
    
    // Status notification
    function showStatus(message) {
        let status = document.querySelector('.bwr-status');
        if (!status) {
            status = document.createElement('div');
            status.className = 'bwr-status';
            status.addEventListener('click', toggleScript);
            document.body.appendChild(status);
        }
        
        status.textContent = CONFIG.enabled ? `✓ BWR: ${message}` : '✗ BWR: Disabled';
        status.classList.toggle('disabled', !CONFIG.enabled);
        status.classList.add('show');
        
        setTimeout(() => {
            status.classList.remove('show');
        }, 3000);
    }
    
    // Toggle script functionality
    function toggleScript() {
        CONFIG.enabled = !CONFIG.enabled;
        GM_setValue('enabled', CONFIG.enabled);
        
        if (CONFIG.enabled) {
            applyEnhancements();
        } else {
            document.querySelectorAll('.bwr-enhanced').forEach(el => {
                el.classList.remove('bwr-enhanced');
            });
        }
        
        showStatus(CONFIG.enabled ? 'Enabled' : 'Disabled');
    }
    
    // Settings management
    function openSettings() {
        const newMaxWidth = prompt('Enter max width (e.g., 95%, 1400px, or 100%):', CONFIG.maxWidth);
        if (newMaxWidth) {
            CONFIG.maxWidth = newMaxWidth;
            GM_setValue('maxWidth', newMaxWidth);
        }
        
        const newPadding = prompt('Enter side padding (e.g., 2rem, 20px):', CONFIG.padding);
        if (newPadding) {
            CONFIG.padding = newPadding;
            GM_setValue('padding', newPadding);
        }
        
        const preserveReadability = confirm('Limit paragraph width for better readability? (Unchecked = full width)');
        CONFIG.preserveReadability = preserveReadability;
        GM_setValue('preserveReadability', preserveReadability);
        
        // Reapply styles with new settings
        initializeScript();
        showStatus('Settings updated');
    }
    
    // Main initialization
    function initializeScript() {
        // Inject CSS
        GM_addStyle(createStyles());
        
        // Apply enhancements immediately
        applyEnhancements();
        
        // Use modern ResizeObserver for better performance
        if (window.ResizeObserver) {
            const resizeObserver = new ResizeObserver(() => {
                applyEnhancements();
            });
            resizeObserver.observe(document.body);
        }
        
        // Fallback to MutationObserver for content changes
        const mutationObserver = new MutationObserver((mutations) => {
            let shouldReapply = false;
            mutations.forEach(mutation => {
                if (mutation.addedNodes.length > 0) {
                    shouldReapply = true;
                }
            });
            
            if (shouldReapply) {
                setTimeout(applyEnhancements, 100);
            }
        });
        
        mutationObserver.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
    
    // Register menu commands
    GM_registerMenuCommand('Toggle Blog Widescreen', toggleScript);
    GM_registerMenuCommand('BWR Settings', openSettings);
    
    // Wait for DOM and initialize
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initializeScript);
    } else {
        initializeScript();
    }
    
    // Handle SPA navigation
    let lastUrl = location.href;
    new MutationObserver(() => {
        const url = location.href;
        if (url !== lastUrl) {
            lastUrl = url;
            setTimeout(applyEnhancements, 500);
        }
    }).observe(document, { subtree: true, childList: true });
    
})();