Image Full Resolution + Stretch

Image Full Resolution + Stretch (Dynamic Break + Alt/Anchor fixes)

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Image Full Resolution + Stretch
// @namespace    http://tampermonkey.net/
// @version      1.27
// @description  Image Full Resolution + Stretch (Dynamic Break + Alt/Anchor fixes)
// @author       bighype
// @include      /^https:\/\/www\.empornium\.(me|sx|is)\/torrents\.php\?id=\d+/
// @include      /^https:\/\/emparadise\.rs\/torrents\.php\?id=\d+/
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // ==========================================
    // 1. CONFIGURE YOUR BLACKLIST HERE
    // ==========================================
    const imageBlacklist =[
        "25_fps_small.png",
        "Audio2.png",
        "ContactSheet.png",
        "DarkRoomVRLogo.png",
        "Date.png",
        "Details.png",
        "details11.png",
        "Disk.png",
        "Duration.png",
        "Many_Vids2-removebg-preview.png",
        "plot11.png",
        "Resolution.png",
        "screens11.png",
        "Screenshots.png",
        "transdescriptiona42c6695c0b6ff7f.png",
        "transscreens5c2af024a602b52c.png",
        "Unknown.png",
        "Up2.png",
        "Video.png",
        "VR2Normal.png",
        "VR2NormalFile.png",
        '1080p_small77cdb8aab8ac9b6f.png',
        '1440p_small.png',
        '24_fps_small.png',
        '6WeZ8Wb3.png',
        '8gznl0Wd.png',
        'cast11.jpg',
        'codec_avc.png',
        'codec_hevc.png',
        'DailyUploadTrophy.png',
        'description.png',
        'Description.png',
        'details.png',
        'DhJP_5Ad.png',
        'image-11CE_51D7BCFD.gif',
        'image-186D_51D7488B.gif',
        'image-23EC_51D7BCFD.gif',
        'image-3CB6_51D7BCFD.gif',
        'image-A37C_4F735C36.gif',
        'image-B367_51D7461D.jpg',
        'image-BAAC_51D7BCFD.gif',
        'image-C696_51D7461D.jpg',
        'info.png',
        'Info.png',
        'lrCYQL12.png',
        'mp4_small9dfd7fe55e0fad20.png',
        'onlyfans-02-logo.png',
        'other.png',
        'plot11.jpg',
        'resolution.png',
        'screens.png',
        'Screens.png',
        'screens11.jpg',
        'screenshots.png',
        'transdescription.png',
        'transinfo.png',
        'transscreens.png',
        'zciirfa1.png',
        'Plot.png',
        'Previews.png',
        'Information.png',
        'test5.png',
        'Cast.png',
        'image-E8A8_53B31227.jpg',
        'image-C08E_53B32551.jpg',
        'image-D988_53B330EC.jpg',
        'descp-comicsansms.png',
        'info-comicsansms.png',
        'details-comincsansms.png',
        'screens-comicsansms.png',
        'cb-384.png',
        'info11.jpg',
        'sup_Casting.png',
        'sup_Deets.png',
        'sup_CS.png',
        'cast11.png',
        'info11.png',
        '1080p.png',
        'H264.png',
        'mp4.png',
        '24-fps.png',
        'medium_1200px-OnlyFans_logo.svg.png',
        '60_fps_small.png',
        "30_fps_small.png",
        "50_fps_small.png",
        "nav-plot.png",
        "nav-comments.png",
        "description-s7s.png",
        "header-icon27e75.png",
        "screens-s7s.png",
        "nav-top.png",
        "se7enseas.png",
        "mediainfo-s7s.png",
        "PervyJourney160.png",
        "broke_logo2XL8.png",
        "Se7enSeas.jpg",
        "pointing-down-hand-clip-art-Moving-animated-eyes-finger-pointing-down.gif",
        "logo.png",
        "mrsparkle.png",
        "sparkleheader3.png",
        "sparkleuploads2.png",
        // '/smilies/',      // Example: Ignore all images in a 'smilies' directory
        // 'icon_user.gif'   // Example: Ignore specific icon names
    ];

    const MAX_ICON_WIDTH = 60;

    const supportedImageHosts =[
        "hamsterimg.net",
        "fapping.empornium.sx",
    ];

    const thumbnailReplacements =[
        { from: ".md.jpg", to: ".jpg" },
        { from: ".th.jpg", to: ".jpg" },
        { from: ".md.jpeg", to: ".jpeg" },
        { from: ".th.jpeg", to: ".jpeg" },
        { from: ".md.png", to: ".png" },
        { from: ".th.png", to: ".png" },
        { from: ".md.webp", to: ".webp" },
        { from: ".th.webp", to: ".webp" },
        { from: "thumb-", to: "image-" },
    ];

    const style = document.createElement('style');
    style.textContent = `
        .body img.bbcode:not(.icon):not(.no-stretch) {
            display: block !important;
            width: 100% !important;
            height: auto !important;
            max-width: none !important;
            max-height: none !important;
            margin: 0 auto !important;
        }

        .main_column table,
        .main_column div.bbcode {
            width: 100% !important;
            max-width: none !important;
        }

        /* ----- STYLES: Stack rows vertically and force blocks ----- */
        .stacked-row {
            display: flex !important;
            flex-direction: column !important;
            width: 100% !important;
        }

        .stacked-cell {
            display: block !important;
            width: 100% !important;
            max-width: none !important;
            box-sizing: border-box !important;
        }
    `;
    document.head.appendChild(style);

    function isSupportedHost(url) {
        try {
            const hostname = new URL(url).hostname;
            return supportedImageHosts.some(domain => hostname.includes(domain));
        } catch {
            return false;
        }
    }

    function upgradeImages() {
        document.querySelectorAll('img').forEach(img => {
            if (!isSupportedHost(img.src)) return;

            let src = img.src;
            let alt = img.getAttribute('alt') || "";

            let fullSrc = src;
            let fullAlt = alt;

            // Upgrade both the src and the alt (preventing Lightbox/LazyLoad from reverting it)
            thumbnailReplacements.forEach(rule => {
                if (fullSrc.includes(rule.from)) fullSrc = fullSrc.split(rule.from).join(rule.to);
                if (fullAlt.includes(rule.from)) fullAlt = fullAlt.split(rule.from).join(rule.to);
            });

            if (fullSrc !== src) {
                img.src = fullSrc;
            }
            if (fullAlt !== alt) {
                img.setAttribute('alt', fullAlt);
            }

            // If the image is wrapped in a link pointing to a thumbnail, upgrade the link too
            let parentA = img.closest('a');
            if (parentA) {
                let href = parentA.getAttribute('href') || "";
                let fullHref = href;
                thumbnailReplacements.forEach(rule => {
                    if (fullHref.includes(rule.from)) fullHref = fullHref.split(rule.from).join(rule.to);
                });
                if (fullHref !== href) {
                    parentA.setAttribute('href', fullHref);
                }
            }
        });
    }

    function breakLayoutTable(table) {
        if (!table || table.dataset.layoutFixed) return;
        table.dataset.layoutFixed = "true";

        Array.from(table.rows).forEach(tr => {
            if (tr.cells.length > 1) {
                tr.classList.add('stacked-row');

                Array.from(tr.cells).forEach(td => {
                    td.classList.add('stacked-cell');
                    td.removeAttribute('width');
                    if (td.style.width) {
                        td.style.width = '';
                    }
                });
            }
        });
    }

    function processImageAndLayout(img) {
        if (img.classList.contains('no-stretch') || img.classList.contains('icon')) return;

        const isBlacklisted = imageBlacklist.some(keyword =>
            img.src.toLowerCase().includes(keyword.toLowerCase())
        );

        if (isBlacklisted) {
            img.classList.add('no-stretch');
            return;
        }

        if (img.naturalWidth > 0) {
            if (img.naturalWidth < MAX_ICON_WIDTH) {
                img.classList.add('no-stretch');
            } else {
                let table = img.closest('table.bbcode');
                while (table) {
                    breakLayoutTable(table);
                    table = table.parentElement ? table.parentElement.closest('table.bbcode') : null;
                }
            }
        }
    }

    function initLayoutAndImages() {
        document.querySelectorAll('.main_column table, .main_column div.bbcode')
            .forEach(el => {
                el.removeAttribute('width');
                if (el.style.width) {
                    el.style.width = '100%';
                }
            });

        // Ensure <a> wrapper tags do not constrain image stretching width
        document.querySelectorAll('.body a').forEach(a => {
            if (a.querySelector('img.bbcode')) {
                a.style.display = 'block';
                a.style.width = '100%';
            }
        });

        document.querySelectorAll('img.bbcode').forEach(img => {
            if (img.complete) {
                processImageAndLayout(img);
            } else {
                img.addEventListener('load', () => processImageAndLayout(img));
            }
        });
    }

    // 1. Upgrade SRCs and ALTs first so the new images begin fetching
    upgradeImages();
    // 2. Break layout restrictions once natural sizes are determined
    initLayoutAndImages();

    // 3. Catch dynamically added images later (just in case the page uses AJAX to load comments/posts)
    const observer = new MutationObserver((mutations) => {
        let newlyAdded = false;
        mutations.forEach(m => {
            if (m.addedNodes.length > 0) {
                m.addedNodes.forEach(node => {
                    if (node.nodeType === 1 && (node.tagName === 'IMG' || node.querySelector('img'))) {
                        newlyAdded = true;
                    }
                });
            }
        });
        if (newlyAdded) {
            upgradeImages();
            initLayoutAndImages();
        }
    });
    observer.observe(document.body, { childList: true, subtree: true });

})();