Medium Upsell Blocker

Prevent Medium subscription/upsell modals by setting lo-non-moc-upsell-v2|displayed-at in localStorage

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name               Medium Upsell Blocker
// @name:zh-TW         Medium 推銷遮罩阻擋器
// @namespace          wellstsai.com
// @version            v20251112
// @license            MIT
// @description        Prevent Medium subscription/upsell modals by setting lo-non-moc-upsell-v2|displayed-at in localStorage
// @description:zh-TW  透過在 localStorage 中設定 lo-non-moc-upsell-v2|displayed-at,防止 Medium 顯示訂閱或推銷彈出視窗
// @author             WellsTsai
// @match              *://*.medium.com/*
// @match              *://*/*
// @run-at             document-start
// @grant              none
// ==/UserScript==

(() => {
    'use strict';
    const K = 'lo-non-moc-upsell-v2|displayed-at';
    const set = () => { try { localStorage.setItem(K, `"${new Date().toISOString()}"`); } catch (_) {} };
    const isMediumHost = /(^|\.)medium\.com$/.test(location.hostname);
    const isMediumLike = () => {
        const nodes = document.querySelectorAll('meta[name],meta[property],link[href]');
        for (const el of nodes) {
            const s = `${el.content||''}${el.getAttribute('name')||''}${el.getAttribute('property')||''}${el.href||''}`.toLowerCase();
            if (s.includes('medium') || s.includes('com.medium.reader') || s.includes('miro.medium.com') || s.includes('glyph.medium.com')) return true;
        }
        return false;
    };

    if (isMediumHost) {
        set();
        window.addEventListener('DOMContentLoaded', set, { once: true });
    } else {
        const run = () => { if (isMediumLike()) set(); };
        if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', run, { once: true });
        else run();
    }
})();