Greasy Fork

来自缓存

Greasy Fork is available in English.

知乎净化工具

一个强大的知乎净化工具:专注宽屏 | 匿名模式 | 彻底移除元素 | 隐藏顶栏 | 全方位屏蔽 | 智能跳转。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         知乎净化工具
// @name:en      Zhihu Purifier
// @namespace    https://github.com/b1n // 使用你的ID,确保全球唯一
// @version      1.0
// @description  一个强大的知乎净化工具:专注宽屏 | 匿名模式 | 彻底移除元素 | 隐藏顶栏 | 全方位屏蔽 | 智能跳转。
// @description:en A powerful Zhihu purification tool: Widescreen | Anonymous Mode | Remove Elements | Hide Header | Block Everything | Smart Redirect.
// @author       bin
// @match        *://*.zhihu.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @license      MIT
// @homepageURL  http://greasyfork.icu/zh-CN/scripts/你的脚本发布后的ID // 发布后再回来填
// @supportURL   http://greasyfork.icu/zh-CN/scripts/你的脚本发布后的ID/feedback // 发布后再回来填
// ==/UserScript==

(function() {
    'use strict';

    // --- 配置与日志 ---
    let minLength = GM_getValue('minLength', 200);
    let removalMethod = GM_getValue('removalMethod', 'remove');
    let widescreenEnabled = GM_getValue('widescreenEnabled', true);
    let hideHeaderEnabled = GM_getValue('hideHeaderEnabled', true);
    let anonymousModeEnabled = GM_getValue('anonymousModeEnabled', false); // 新增:匿名模式,默认关闭
    let blockAnswerCardEnabled = GM_getValue('blockAnswerCardEnabled', true);
    let autoExpandEnabled = GM_getValue('autoExpandEnabled', true);
    let blockAdsEnabled = GM_getValue('blockAdsEnabled', true);
    const log = (message) => console.log(`[知乎净化器] ${message}`);

    // --- 核心处理函数 ---
    const processElement = (element) => {
        if (element.dataset.processed === 'true') return;

        let shouldProcess = false;
        let reason = '';

        if (blockAdsEnabled && element.matches('.Pc-word-new')) {
            shouldProcess = true; reason = '广告';
        }
        else if (blockAnswerCardEnabled && element.matches('.AnswerTopCard, [class*="KfeCollection"]')) {
            shouldProcess = true; reason = '回答内推荐';
        }
        else if (element.matches('.AnswerItem, .CommentItem')) {
            const contentElement = element.querySelector('.RichContent, .CommentContent');
            if (contentElement && contentElement.innerText.trim().length < minLength) {
                shouldProcess = true; reason = `短内容 (字数=${contentElement.innerText.trim().length})`;
            }
        }

        if (shouldProcess) {
            const container = element.closest('.List-item') || element;
            log(`判定: [${reason}] -> 操作目标: ${container.className}`);
            if (removalMethod === 'remove') container.remove();
            else container.style.display = 'none';
        }

        element.dataset.processed = 'true';
    };

    // --- 重新处理所有内容 ---
    const reprocessAllContent = () => {
        log(`--- 用户触发重新处理 ---`);
        document.querySelectorAll('.AnswerItem, .CommentItem, .Pc-word-new, .AnswerTopCard, [class*="KfeCollection"]').forEach(item => {
            item.dataset.processed = 'false';
            if (removalMethod === 'hide') item.style.display = '';
            processElement(item);
        });
    };

    // --- 注入/应用全局样式 ---
    const applyGlobalStyles = () => {
        const styleId = 'zh-purifier-styles';
        let existingStyle = document.getElementById(styleId);
        if (existingStyle) existingStyle.remove();

        let styles = `
            /* 匿名模式 */
            .zh-purifier-anonymous .AnswerItem-authorInfo { display: none !important; }
            /* 专注宽屏 */
            .zh-purifier-widescreen .Question-sideColumn { display: none !important; }
            .zh-purifier-widescreen .Question-mainColumn { width: 100% !important; max-width: none !important; }
            /* 隐藏顶栏 */
            .zh-purifier-hide-header #root > div > div.css-s8xum0 > header { display: none !important; }
        `;

        GM_addStyle(styles, styleId);

        document.body.classList.toggle('zh-purifier-anonymous', anonymousModeEnabled);
        document.body.classList.toggle('zh-purifier-widescreen', widescreenEnabled);
        document.body.classList.toggle('zh-purifier-hide-header', hideHeaderEnabled);

        log('全局样式已应用。');
    };

    // --- UI创建 (V2.0 最终版) ---
    const createUI = () => {
        const uiHTML = `
            <div id="zhihu-helper-fab">
                <svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61-.25-1.17-.59-1.69-.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19-.15-.24-.42-.12.64l2 3.46c.12-.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49.42l.38-2.65c.61-.25 1.17-.59-1.69-.98l2.49 1c.23-.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg>
            </div>
            <div id="zhihu-helper-sidebar" class="closed">
                <div id="zhihu-helper-content">
                    <h3>知乎遗风净化器</h3>
                    <div class="setting-row"><label>回答最短字数</label><input type="number" id="minLengthInput" value="${minLength}"></div>
                    <div class="setting-row"><label>屏蔽回答方式</label><select id="removalMethodSelect"><option value="remove">移除 (彻底)</option><option value="hide">隐藏 (可逆)</option></select></div>
                    <div class="setting-row"><label>专注宽屏</label><label class="switch"><input type="checkbox" id="widescreenToggle" ${widescreenEnabled ? 'checked' : ''}><span class="slider"></span></label></div>
                    <div class="setting-row"><label>隐藏顶栏</label><label class="switch"><input type="checkbox" id="hideHeaderToggle" ${hideHeaderEnabled ? 'checked' : ''}><span class="slider"></span></label></div>
                    <div class="setting-row"><label>匿名模式</label><label class="switch"><input type="checkbox" id="anonymousModeToggle" ${anonymousModeEnabled ? 'checked' : ''}><span class="slider"></span></label></div>
                    <div class="setting-row"><label>屏蔽广告</label><label class="switch"><input type="checkbox" id="blockAdsToggle" ${blockAdsEnabled ? 'checked' : ''}><span class="slider"></span></label></div>
                    <div class="setting-row"><label>屏蔽回答内推荐</label><label class="switch"><input type="checkbox" id="blockAnswerCardToggle" ${blockAnswerCardEnabled ? 'checked' : ''}><span class="slider"></span></label></div>
                    <div class="setting-row"><label>自动跳转</label><label class="switch"><input type="checkbox" id="autoExpandToggle" ${autoExpandEnabled ? 'checked' : ''}><span class="slider"></span></label></div>
                    <button id="saveBtn">保存并应用</button>
                    <p id="statusMsg"></p>
                </div>
            </div>
        `;
        const uiCSS = `
            #zhihu-helper-fab { position: fixed; bottom: 30px; right: 30px; width: 48px; height: 48px; background-color: rgba(0, 0, 0, 0.45); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.2); transition: all 0.2s ease; z-index: 9998; }
            #zhihu-helper-fab:hover { background-color: rgba(0, 0, 0, 0.6); transform: scale(1.05); }
            #zhihu-helper-sidebar { position: fixed; top: 120px; right: -280px; width: 260px; background: rgba(245, 245, 245, 0.75); backdrop-filter: blur(16px) saturate(180%); -webkit-backdrop-filter: blur(16px) saturate(180%); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); z-index: 9999; transition: right 0.4s cubic-bezier(0.25, 1, 0.5, 1); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; }
            #zhihu-helper-sidebar.open { right: 20px; }
            #zhihu-helper-content { padding: 20px; }
            #zhihu-helper-content h3 { margin-top: 0; margin-bottom: 20px; color: #1d1d1f; font-weight: 600; }
            .setting-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; }
            #zhihu-helper-content label { font-size: 15px; color: #333; }
            #zhihu-helper-content input[type="number"] { width: 70px; padding: 8px; border: 1px solid rgba(0, 0, 0, 0.1); background: rgba(255, 255, 255, 0.6); border-radius: 8px; font-size: 15px; color: #1d1d1f; text-align: center; }
            #zhihu-helper-content select { padding: 8px; border: 1px solid rgba(0, 0, 0, 0.1); background: rgba(255, 255, 255, 0.6); border-radius: 8px; font-size: 14px; }
            #zhihu-helper-content button { width: 100%; padding: 10px; background-color: rgba(0, 122, 255, 0.9); color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 15px; font-weight: 500; transition: background-color 0.2s ease; margin-top: 10px; }
            #zhihu-helper-content button:hover { background-color: rgba(0, 122, 255, 1); }
            #statusMsg { margin-top: 15px; font-size: 13px; color: #007bff; min-height: 1.2em; text-align: center; }
            .switch { position: relative; display: inline-block; width: 50px; height: 28px; } .switch input { opacity: 0; width: 0; height: 0; }
            .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 28px; }
            .slider:before { position: absolute; content: ""; height: 20px; width: 20px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; }
            input:checked + .slider { background-color: #007bff; } input:checked + .slider:before { transform: translateX(22px); }
            /* --- 手机端适配样式 --- */
@media (max-width: 768px) {
    /* 当屏幕宽度小于768像素时,以下样式生效 */

    /* 1. 让悬浮按钮变得更小、更靠边 */
    #zhihu-helper-fab {
        width: 40px;       /* 变小一点 */
        height: 40px;
        bottom: 20px;      /* 更贴近角落 */
        right: 20px;
    }

    /* 2. 让设置面板不再悬浮,而是从底部滑出,占满整个屏幕宽度 */
    #zhihu-helper-sidebar {
        width: 100%;       /* 占满宽度 */
        top: auto;         /* 解除顶部固定 */
        bottom: -100%;     /* 初始状态下藏在屏幕下方 */
        right: 0;          /* 贴紧右边 */
        left: 0;           /* 贴紧左边 */
        border-radius: 12px 12px 0 0; /* 只保留顶部圆角 */
        transition: bottom 0.3s ease-in-out; /* 动画效果改成从底部滑出 */
    }

    #zhihu-helper-sidebar.open {
        bottom: 0;         /* 打开时,滑到屏幕底部 */
        right: 0;          /* 确保贴紧 */
    }
}
        `;
        GM_addStyle(uiCSS);
        document.body.insertAdjacentHTML('beforeend', uiHTML);

        document.getElementById('removalMethodSelect').value = removalMethod;

        document.getElementById('saveBtn').addEventListener('click', () => {
            minLength = parseInt(document.getElementById('minLengthInput').value, 10);
            removalMethod = document.getElementById('removalMethodSelect').value;
            widescreenEnabled = document.getElementById('widescreenToggle').checked;
            hideHeaderEnabled = document.getElementById('hideHeaderToggle').checked;
            anonymousModeEnabled = document.getElementById('anonymousModeToggle').checked;
            blockAdsEnabled = document.getElementById('blockAdsToggle').checked;
            blockAnswerCardEnabled = document.getElementById('blockAnswerCardToggle').checked;
            autoExpandEnabled = document.getElementById('autoExpandToggle').checked;

            GM_setValue('minLength', minLength); GM_setValue('removalMethod', removalMethod);
            GM_setValue('widescreenEnabled', widescreenEnabled); GM_setValue('hideHeaderEnabled', hideHeaderEnabled);
            GM_setValue('anonymousModeEnabled', anonymousModeEnabled); GM_setValue('blockAdsEnabled', blockAdsEnabled);
            GM_setValue('blockAnswerCardEnabled', blockAnswerCardEnabled); GM_setValue('autoExpandEnabled', autoExpandEnabled);

            document.getElementById('statusMsg').textContent = '设置已保存';
            applyGlobalStyles();
            reprocessAllContent();
            setTimeout(() => document.getElementById('statusMsg').textContent = '', 2000);
        });
        document.getElementById('zhihu-helper-fab').addEventListener('click', () => {
            document.getElementById('zhihu-helper-sidebar').classList.toggle('open');
        });
    };

    // --- “哨兵”:监视新加载的内容 ---
    const observeNewContent = (container) => {
        const observer = new MutationObserver((mutationsList) => {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType !== 1) return;
                        processElement(node);
                        node.querySelectorAll('.AnswerItem, .CommentItem, .Pc-word-new, .AnswerTopCard, [class*="KfeCollection"]').forEach(processElement);
                    });
                }
            }
        });
        observer.observe(container, { childList: true, subtree: true });
    };

    // --- 自动跳转功能 ---
    const handleAutoExpand = () => {
        if (!autoExpandEnabled) return false;
        const expandButton = document.querySelector('a.ViewAll-QuestionMainAction');
        if (expandButton) {
            log("发现“查看全部回答”按钮,即将自动跳转...");
            setTimeout(() => expandButton.click(), 500);
            return true;
        }
        return false;
    };

    // --- 脚本主程序 ---
    const main = () => {
        log(`脚本启动!`);
        applyGlobalStyles();
        createUI();

        if (handleAutoExpand()) {
            log("自动跳转已触发。此页面任务结束。");
            return;
        }

        const startupObserver = new MutationObserver((mutations, observer) => {
            const container = document.querySelector('#QuestionAnswers-answers, .Comments-container');
            if (container) {
                observer.disconnect();
                const existingItems = document.querySelectorAll('.AnswerItem, .CommentItem, .Pc-word-new, .AnswerTopCard, [class*="KfeCollection"]');
                log(`首次扫描发现 ${existingItems.length} 个待处理项。`);
                existingItems.forEach(processElement);
                observeNewContent(container);
            }
        });
        startupObserver.observe(document.body, { childList: true, subtree: true });
    };

    main();

})();