Greasy Fork

Greasy Fork is available in English.

小说页面伪装|小说页面精简|起点页面伪装|番茄页面伪装|笔趣阁页面伪装

将小说页面伪装成一个Word文档或Excel表格,同时净化小说页面,去除不必要的元素。适用于起点、番茄、笔趣阁、晋江、飞卢、69书吧、部分轻小说站等

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         小说页面伪装|小说页面精简|起点页面伪装|番茄页面伪装|笔趣阁页面伪装
// @namespace    https://github.com/NiaoBlush/novel-disguise
// @version      2.9.0
// @description  将小说页面伪装成一个Word文档或Excel表格,同时净化小说页面,去除不必要的元素。适用于起点、番茄、笔趣阁、晋江、飞卢、69书吧、部分轻小说站等
// @author       NiaoBlush
// @license      MIT
// @run-at       document-end
// @homepageURL  https://github.com/NiaoBlush/novel-disguise
// @supportURL   https://github.com/NiaoBlush/novel-disguise/issues
// @icon64       https://s21.ax1x.com/2024/08/06/pkxPf0S.png
// @match        https://www.qidian.com/chapter/*
// @match        https://fanqienovel.com/reader/*
// @match        *://www.biquge.net/*/*/*.html
// @match        *://www.xbiqugu.net/*/*/*.html
// @match        *://www.biquge.co/*/*.html
// @match        *://www.52wx.com/*/*.html
// @match        https://www.3bqg.cc/book/*/*.html
// @match        https://www.bigee.cc/book/*/*.html
// @match        https://www.beqege.cc/*/*.html
// @match        https://www.biqukun.com/*/*/*.html
// @match        https://www.biquge.tw/book/*/*.html
// @match        https://www.wenku8.net/novel/*/*/*.htm
// @exclude      https://www.wenku8.net/novel/*/*/index.htm
// @match        https://www.linovelib.com/novel/*/*.html
// @match        https://www.bilinovel.com/novel/*/*.html
// @match        https://www.qimao.com/shuku/*-*
// @match        https://www.jjwxc.net/onebook.php?novelid=*&chapterid=*
// @match        https://my.jjwxc.net/onebook_vip.php?novelid=*&chapterid=*
// @match        https://my.jjwxc.net/backend/buynovel.php?novelid=*&chapterid=*
// @match        https://www.lightnovel.us/cn/detail/*
// @match        https://b.faloo.com/*_*.html
// @match        https://b.faloo.com/vip/*/*.html
// @match        https://69shuba.cx/txt/*/*
// @match        https://www.69shuba.com/txt/*/*
// @match        https://www.owlook.com.cn/owllook_content*
// @match        https://owlook.com.cn/owllook_content*
// @match        https://www.ciweimao.com/chapter/*
// @match        https://www.v2ex.com/
// @match        https://www.v2ex.com/?*
// @match        https://www.v2ex.com/go/*
// @match        https://www.v2ex.com/t/*
// @match        https://www.v2ex.com/recent*
// @match        https://www.kelexs.com/book/*-*.html
// @match        http://www.xbiqugu.la/*/*/*.html
// @match        https://reader.z-library.ec/read/*
// @match        https://reader.z-library.sk/read/*
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @require      https://update.greasyfork.icu/scripts/547816/1651807/novel-disguise-jquery.js?v=2.0.3
// @require      https://update.greasyfork.icu/scripts/547815/1651802/novel-disguise-resource.js?v=0.0.1
// ==/UserScript==

(function () {
    'use strict';
    printLog("novel-disguise 开始初始化");

    typeof jQuery !== "undefined" ? printLog("jQuery 版本: " + jQuery.fn.jquery) : printLog("error", "jQuery 未载入!");
    const $ = jQuery.noConflict(true);

    typeof NovelDisguiseResource !== "undefined" ? printLog("资源已载入", NovelDisguiseResource) : printLog("error", "资源未载入");

    const screenInfo = getScreenInfo();
    let disguised_header_img = null;
    let disguised_body_img = null;
    let disguised_footer_img = null;
    let disguised_icon_img = null;
    let headerHeight = null;
    let footerHeight = null;
    let readerHeight = null;

    const originalTitle = document.title;

    const link_text_color = "rgba(0,0,0,.7)";
    const link_bg_color = "#f6f6f6";
    const link_front_color = "rgba(0,0,0,.7)";

    const DICT = {
        MODE: {
            WORD: 'mode_word',
            EXCEL: 'mode_excel',
            ORIGINAL: 'mode_original'
        },
        THEME: {
            OFFICE: 'theme_office',
            WPS: 'theme_wps'
        },
        MARGIN_TYPE: {
            NORMAL: 'normal_margin',
            NONE: 'no_margin'
        }
    };

    const KEY_CONFIG = "KEY_CONFIG";

    function printLog(...args) {
        let level = 'info';

        // 判断第一个参数是否为 level
        if (typeof args[0] === 'string' && ['info', 'warn', 'error'].includes(args[0])) {
            level = args.shift(); // 取出 level
        }

        let levelStyle = '';
        switch (level) {
            case 'info':
                levelStyle = 'color:#00BFFF;font-weight:bold;';
                break;
            case 'warn':
                levelStyle = 'color:#FFA500;font-weight:bold;';
                break;
            case 'error':
                levelStyle = 'color:#FF4500;font-weight:bold;';
                break;
            default:
                levelStyle = 'color:#000;';
        }

        const prefix = `%c🎭novel-disguise%c [${level.toUpperCase()}]`;

        console.log(
            prefix,
            'background:#222;color:#FFD700;font-weight:bold;padding:2px 4px;border-radius:4px;',
            'background:none;' + levelStyle,
            ...args
        );
    }

    function readConfig() {

        const defaultConfig = {
            mode: DICT.MODE.WORD,
            lastVisibleMode: DICT.MODE.WORD,
            theme: DICT.THEME.OFFICE,
            marginType: DICT.MARGIN_TYPE.NORMAL,
            hideImage: true,

            emptyCols: 20,
            enableExcelRandomPopulate: true,
            maxExcelRandomPopulateCol: 9
        };
        const stored = GM_getValue(KEY_CONFIG, {});
        const config = Object.assign({}, defaultConfig, stored);
        if (config.mode !== DICT.MODE.ORIGINAL) {
            config.lastVisibleMode = config.mode;
        }
        printLog("config loaded", config);
        return config;
    }

    const config = readConfig();

    function writeConfig() {
        GM_setValue(KEY_CONFIG, config);
    }

    function applyMode(mode) {
        printLog('准备切换到模式[${mode}]...');
        config.mode = mode;
        writeConfig();
        location.reload();
    }

    function settings() {
        const $settings = $(`
            <form class="nd-settings-form">
                <div class="nd-settings-form-group">
                    <label>模式: </label>
                    <select name="settings-mode">
                        <option value="${DICT.MODE.WORD}">Word</option>
                        <option value="${DICT.MODE.EXCEL}">Excel</option>
                    </select>
                </div>
                <div class="nd-settings-form-group">
                    <label for="settings-mode">主题: </label>
                    <select id="settings-theme" name="settings-theme">
                        <option value="${DICT.THEME.OFFICE}">Office</option>
                        <option value="${DICT.THEME.WPS}">Wps</option>
                    </select>
                </div>
                <div class="nd-settings-form-group">
                    <label title="word半屏时采用无边距会看起来更加自然">Word页边距: </label>
                    <label style="width: 30%;"><input type="radio" name="margin-type" value="${DICT.MARGIN_TYPE.NORMAL}">正常</label>
                    <label style="width: 30%;"><input type="radio" name="margin-type" value="${DICT.MARGIN_TYPE.NONE}">无边距</label>
                </div>
                <div class="nd-settings-form-group">
                    <label>隐藏图片: </label>
                    <label style="width: 30%;"><input type="radio" name="settings-hide-image" value="true">是</label>
                    <label style="width: 30%;"><input type="radio" name="settings-hide-image" value="false">否</label>
                </div>
                
                <div class="nd-settings-form-group" style="margin-top: 20px;">
                    <div class="nd-settings-btn-wrapper">
                        <button type="button" name="tip">好活,当赏❤️</button>
                        <button type="submit">保存设置</button>
                    </div>
                    
                </div>
            </form>
           
        `);

        //default
        $settings.find("select[name=settings-mode]").val(config.mode);
        $settings.find("select[name=settings-theme]").val(config.theme);
        $settings.find(`input[name=margin-type][value='${config.marginType}']`).prop('checked', true);
        $settings.find(`input[name=settings-hide-image][value='${String(config.hideImage)}']`).prop('checked', true);

        const $modal = showModal($settings, {
            title: "设置"
        });

        //submit
        $settings.on('submit', function (event) {
            event.preventDefault();

            const formDataObj = new FormData(this);

            config.mode = formDataObj.get('settings-mode');
            config.theme = formDataObj.get('settings-theme');
            config.marginType = formDataObj.get('margin-type');
            config.hideImage = formDataObj.get('settings-hide-image') === 'true';
            writeConfig();


            popMsg("设置已保存,刷新页面后生效");
            $modal.remove();
        });

        //tip
        $settings.find("button[name=tip]").on("click", function () {
            const $tipContent = $(`
                <div class="nd-tip-content">
                    <div class="nd-tip-text">
                        <p>感谢使用,如果觉得这个脚本用起来还算愉快,请随意打赏,一切随缘~</p>
                        <br>
                        <p style="font-size: 1.5em;"><b>祝各位摸鱼快乐~</b></p>
                    </div>
                    <div class="nd-tip-img-wrapper">
                        <img src="${NovelDisguiseResource.OTHER_IMAGES.tip_wechat.base64}" alt="微信">
                    </div>
                </div>
            `);

            showModal($tipContent, {
                title: "打赏",
                width: 600
            });
        });
    }

    function setResource() {

        function getActualHeight(originalHeight) {
            return originalHeight / screenInfo.devicePixelRatio;
        }

        printLog('screenInfo', screenInfo);

        function getHeaderResource(currentMode, currentTheme, physicalWidth) {
            const wThreshold2k = 2560;
            const wThreshold4k = 3840;

            let size;
            if (physicalWidth >= wThreshold4k) {
                size = "4k";
            } else if (physicalWidth >= wThreshold2k) {
                size = "2k";
            } else {
                size = "1k";
            }

            const header = NovelDisguiseResource.getDisguisedImage({
                app: config.mode,
                theme: config.theme,
                size: size,
                scheme: "light",
                part: "header"
            });
            printLog('header', header);
            return header;
        }

        const src = getHeaderResource(config.mode, config.theme, screenInfo.physicalWidth);
        disguised_header_img = src.url || src.base64;
        headerHeight = getActualHeight(screenInfo.physicalWidth * src.height / src.width);

        const disguised_footer_resource = NovelDisguiseResource.getDisguisedImage({
            app: config.mode,
            theme: DICT.THEME.OFFICE,
            size: "1k",
            scheme: "light",
            part: "footer"
        });
        disguised_footer_img = disguised_footer_resource.base64;
        footerHeight = disguised_footer_resource.height;
        disguised_icon_img = NovelDisguiseResource.getDisguisedImage({
            app: config.mode,
            theme: DICT.THEME.OFFICE,
            size: "1k",
            scheme: "light",
            part: "icon"
        }).base64;

        if (config.mode === DICT.MODE.WORD) {
            disguised_body_img = NovelDisguiseResource.getDisguisedImage({
                app: DICT.MODE.WORD,
                theme: DICT.THEME.OFFICE,
                size: "1k",
                scheme: "light",
                part: "body"
            }).base64;
        }

        readerHeight = window.innerHeight - headerHeight - footerHeight;
    }

    /**
     * 将页面中的图片替换成indicator
     * 受`config.hideImage`控制
     *
     * @param selector css选择器
     * @param replaceParent 是否替换img的父元素(有些img会被a标签包裹)
     * @param indicatorText 占位文字
     */
    function hideImages({selector, replaceParent = false, indicatorText = '点击显示图片'}) {
        if (!config.hideImage) {
            return;
        }

        $(selector).each(function () {
            const imgSrc = $(this).attr('src');
            const span = $('<span class="disguised-img-indicator"></span>')
                .attr('data-src', imgSrc)
                .text(indicatorText);
            if (replaceParent) {
                $(this).parent().replaceWith(span);
            } else {
                $(this).replaceWith(span);
            }

        });
    }

    function registerImageIndicators() {
        $(".disguised-img-indicator").on('click', function () {
            const src = $(this).attr('data-src');
            const $newImg = $('<img>').attr('src', src);
            const $modal = showModal($newImg);
            $modal.find("img").css({
                "max-width": "80vw",
                "max-height": "80vh"
            });
            $newImg.on('click', function () {
                $modal.remove();
            });
        });
    }

    function common() {

        setResource();

        //公共样式
        GM_addStyle(`
        .img-fill-in {
            background-repeat: no-repeat;
            background-size: 100% 100%;
        }
        
        html {
            overflow-y: hidden;
            color-scheme: normal !important;
        }
        
        #disguised-page {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
        }
        
        #disguised-header {
            width: 100%;
            aspect-ratio: ${screenInfo.screenWidth / headerHeight};
            background-image: url(${disguised_header_img});
        }
        
        #disguised-title {
            position: fixed;
            top: 5px;
            left: 0;
            width: 100%;
            z-index: 9999;
            text-align: center;
            color: ${config.theme === DICT.THEME.OFFICE ? '#edffff' : '#232323'};
            font-size: 12px;
            line-height: 22px;
            user-select: none;
        }
        
        #disguised-footer {
            height: ${footerHeight}px;
            line-height: ${footerHeight}px;
            width: 100%;
            background-image: url(${disguised_footer_img});
            font-size: 13px;
            color: #262626;
            
            box-sizing: border-box;
            position: relative;
        }
        
        #footer-content {
            position: absolute;
            left: 0;
            bottom: 0;
            height: ${footerHeight}px;
            line-height: ${footerHeight}px;
            width: 100%;
            flex-direction: row;
            flex-wrap: nowrap;
            align-content: center;
            justify-content: flex-start;
            align-items: center;
            box-sizing: border-box;
            padding-left: 20px;
        }
        
        #footer-content > * {
            height: 100%;
            line-height: 100%;
            margin-right: 10px;
            font-size: 13px;
        }
        
        #disguised-body {
            flex: 1;
            padding-left: ${config.marginType === DICT.MARGIN_TYPE.NORMAL ? '25%' : '0'};
            padding-right: ${config.marginType === DICT.MARGIN_TYPE.NORMAL ? '25%' : '0'};
            background-image: url(${disguised_body_img}) !important;
            background-repeat: repeat-y;
            background-size: 100% auto;
            overflow-y: scroll;
            width: 100%;
            box-sizing: border-box;
        }
        
        #disguised-content {
            background-color: #FFF;
            border-left-color: #c6c6c6;
            border-right-color: #c6c6c6;
            border-left-width: 1px;
            border-right-width: 1px;
            min-height: 100%;
            width: 100%;
            box-sizing: border-box;
        }
        
        #disguised-content > * {
            width: 100%;
            margin: unset;
            box-sizing: border-box;
        }
        
        #disguised-content p {
            color: black;
        }
        
        #disguised-content div {
            background-color: #FFF !important;
        }
        
        #disguised-right-content {
            display: none;
            position: fixed;
            right: 0;
            top: ${headerHeight}px;
            height: ${readerHeight}px;
            width: 400px;
            z-index: 99999;
        }
        
        .disguised-link, .disguised-img-indicator {
            color: ${link_text_color};
            text-decoration: underline;
            cursor: pointer;
            margin-right: 5px;
        }
        
        .disguised-modal-wrapper {
            position: fixed;
            z-index: 99999;
            top: 50%;
            left: 50%;
            max-height: 100%;
            max-width: 100%;
            transform: translate(-50%, -50%);
            border: 1px solid #707070;
            background-color: #F0F0F0;
        }
        
        .disguised-modal-header {
            background-color: #FFF;
            min-width: 200px;
            height: 32px;
            display: flex;
        }
        
        .disguised-modal-title {
            flex: 1;
            user-select: none;
            padding-left: 10px;
            color: black;
            display: flex;
            align-items: center;
        }
        
        .disguised-modal-header-close {
            position: relative;
            background-color: transparent;
            border: none;
            cursor: pointer;
            padding: 0;
            width: 36px;
            height: 32px;
            font-size: 1em;
        }
        .disguised-modal-header-close:hover {
            background-color: #E81023;
        }
        .disguised-modal-header-close::before,
        .disguised-modal-header-close::after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 15px;
            height: 1px;
            background-color: black;
            transform-origin: center;
        }
        .disguised-modal-header-close:hover::before,
        .disguised-modal-header-close:hover::after {
            background-color: #FFF;
        }
        .disguised-modal-header-close::before {
            transform: translate(-50%, -50%) rotate(45deg);
        }
        .disguised-modal-header-close::after {
            transform: translate(-50%, -50%) rotate(-45deg);
        }
        
        .disguised-modal-body {
            padding: 10px;
            background-color: #F0F0F0;
            min-height: 32px;
            max-height: calc(100vh - 32px);
            font-size: 1em;
            line-height: normal;
            overflow-y: auto;
        }
        
        .disguised-modal-wrapper * {
            margin: unset;
        }
        
        .nd-settings-form {
            font-family: 'Microsoft YaHei', sans-serif;
            width: 300px;
            box-shadow: none;
        }
        
        .nd-settings-form-group:not(:last-child) {
            margin-bottom: 15px;
        }
        
        .nd-settings-form-group label {
            display: inline-block;
            font-size: 13px;
            color: #000;
            margin-bottom: 5px;
        }
        
        .nd-settings-form-group select,
        .nd-settings-form-group input[type="radio"] {
            font-size: 13px;
            padding: 2px;
            border: 1px solid #c0c0c0;
            background-color: white;
            width: auto;
        }
        
        .nd-settings-form-group input[type="radio"] {
            width: auto;
            margin-right: 5px;
        }
        
        .nd-settings-form-group button {
            font-size: 13px;
            padding: 5px 10px;
            margin-right: 5px;
            border: 1px solid #c0c0c0;
            border-radius: 2px;
            background-color: #e0e0e0;
            cursor: pointer;
        }
        
        .nd-settings-form-group button[type="submit"] {
            background-color: #dcdcdc;
        }
        
        .nd-settings-form-group button:hover {
            background-color: #c0c0c0;
        }
        
        .nd-settings-form-group button:active {
            background-color: #a0a0a0;
        }
        
        .nd-settings-form-group button:focus {
            outline: 1px solid #606060;
        }
        
        .nd-settings-form-group select {
            margin-right: 5px;
            width: 180px;
        }
        
        .nd-settings-form-group select:focus-visible {
            outline: none;
        }
        
        .nd-settings-form-group label:first-child {
            width: 100px;
        }
        
        .nd-settings-form p {
            margin-bottom: 10px;
        }

        .nd-settings-btn-wrapper {
            display: flex;
            justify-content: space-between;
        }

        
        .nd-tip-content {
            font-size: 1.3em;
            display: flex;
        }
        
        .nd-tip-text {
            width: 50%;
            padding: 100px 5px;
        }
        
        .nd-tip-img-wrapper {
            width: 50%;
            display: flex;
            justify-content: space-between;
        }
        
        .nd-tip-img-wrapper img {
            width: 100%;
        }
        
        .nd_msg{display:none;position:fixed;top:10px;left:50%;transform:translateX(-50%);color:#fff;text-align:center;z-index:99996;padding:10px 30px;font-size:16px;border-radius:10px;background-size:25px;background-repeat:no-repeat;background-position:15px}
        .nd_msg a{color:#fff;text-decoration: underline;}
        .nd_msg-ok{background:#4bcc4b}
        .nd_msg-err{background:#c33}
        .nd_msg-warn{background:#FF9900}
        `);

        // 图标
        var link = $('<link rel="icon" type="image/x-icon">').attr('href', disguised_icon_img);
        $('link[rel*="icon"]').remove();
        $('head').append(link);

        $('body').children().hide();

        $(`<div id='disguised-page'>
                <div id='disguised-title'></div>
                <div id='disguised-header' class='img-fill-in'></div>
                <div id='disguised-body'>
                    <div id='disguised-content'></div> 
                    <div id='disguised-right-content'></div>
                </div>
                <div id='disguised-footer' class='img-fill-in'>
                    <div id="footer-content">
                        <span>简体中文(中国大陆)</span><span>辅助功能:一切就绪</span>
                    </div>
                </div>
           </div>`).appendTo("body");

        overridePageTitle();
        if (config.mode === DICT.MODE.WORD) {
            GM_addStyle(`
            #disguised-content {
                padding: 10px 30px;
            }
            `);
        } else {
            GM_addStyle(`
            #footer-content {
                height: 45%;
                line-height: 45%;
            }
            #disguised-body {
                padding-left: 0;
                padding-right: 0;
                overflow-y: hidden;
            }
            #disguised-content {
                height: 100%;
                overflow-x: hidden;
                overflow-y: scroll;
            }
            
            table {
                margin: 0;
            }
            .excel-table,
            .excel-table th,
            .excel-table td,
            .excel-table thead,
            .excel-table tbody {
                border-spacing: 0;
            }
            .excel-table {
                border-collapse: collapse;
            }
            
            .excel-table > thead {
                background-color: ${config.theme === DICT.THEME.OFFICE ? '#E6E6E6' : '#EEEEEE'};
            }
            
            .excel-table > thead > tr > th {
                font-weight: normal;
                font-size: 14px;
                color: black !important;
                background-color: ${config.theme === DICT.THEME.OFFICE ? '#E6E6E6' : '#EEEEEE'};
                position: sticky;
                top: 0;
                outline: 1px solid;
                outline-color: #A0A0A0;
                text-align: center;
                font-family: "SimSun", sans-serif;
                padding: 0;
                line-height: normal;
                z-index: 9999;
            }
            
            .excel-table th {
                min-width: 71px;
            }
            .excel-table th:nth-child(1) {
                width: auto;
                min-width: 20px;
            }
            .excel-table th:nth-child(2) {
                min-width: 50vw;
            }
            .excel-table tbody {
            }
            .excel-table > tbody > tr > td:nth-child(1) {
                text-align: center;
                background-color: #E6E6E6;
                padding-left: 5px;
                padding-right: 5px;
                user-select: none;
            }
            .excel-table tbody td:not(:nth-child(1)):not(:nth-child(2)) {
                white-space: nowrap;
                text-align: center;
            }
            .excel-table > tbody > tr > td {
                border: 1px solid #DDDDDD;
                padding: 3px 10px;
                line-height: normal;
            }
            .excel-table > tbody > tr > td ,
            .excel-table tbody td p {
                font-size: 12px;
                font-weight: normal;
                color: black !important;
                font-family: "Microsoft YaHei", "SimSun", sans-serif;
            }
            .excel-table > tbody > tr:first-child > td {
                border-top: none;
            }
            .excel-table tbody td > div {
                margin: 0;
                padding: 0;
                text-align: unset;
            }
            `);

            //构建表格
            const $table = $('<table class="excel-table"></table>');
            const extraThead = (function () {
                let output = '';
                for (let i = 1; i <= config.emptyCols; i++) {
                    const char = String.fromCharCode(64 + i);
                    output += `<th>${char}</th>`;
                }
                return output;
            })();
            const $thead = $(`<thead><tr><th></th>${extraThead}</tr></thead>`);
            const $tbody = $('<tbody></tbody>');
            // 添加表头
            $table.append($thead);
            $table.append($tbody);
            $("#disguised-content").append($table);

            //占位行
            padExcelBlankLines();
        }
    }

    function overridePageTitle() {
        if (config.mode === DICT.MODE.WORD) {
            document.title = "文档1";
        } else {
            document.title = "工作簿1";
        }
    }

    function setWordContent($contentEl) {
        if (config.mode !== DICT.MODE.WORD) {
            return;
        }
        $contentEl.show().appendTo("#disguised-content");
    }

    function clearExcelContent() {
        if (config.mode === DICT.MODE.EXCEL) {
            $(".excel-table tbody").empty();
        }
    }

    function getExcelLastIndex() {
        const $cell = $(".excel-table > tbody > tr:last-child > td:first-child");
        const indexCellText = $.trim($cell.text());
        return indexCellText ? parseInt(indexCellText) : 0;
    }

    /**
     * 空行补齐
     */
    function padExcelBlankLines(max = 50) {
        const lastIndex = getExcelLastIndex();
        const emptyLines = [];
        for (let i = lastIndex + 1; i <= max; i++) {
            emptyLines.push("\u200B");
        }
        setExcelLines(emptyLines, true);
    }

    function setExcelLines(lines, append = false, rowHandler) {
        if (config.mode !== DICT.MODE.EXCEL) {
            return;
        }

        let lastIndex;
        if (append) {
            lastIndex = getExcelLastIndex();
        } else {
            clearExcelContent();
            lastIndex = 0;
        }
        const $tbody = $(".excel-table > tbody");
        lines.forEach(function (line, index) {
            if (typeof line === 'string') {
                line = line.replace(/&nbsp;/g, '').trim();
            }

            if (line === '') return;
            if (line instanceof $ && line.length === 0) return;

            const $td2 = $('<td></td>');
            if (typeof rowHandler === 'function') {
                line = rowHandler(line, index, $td2);
            }

            const $tr = $('<tr></tr>');
            const $td1 = $('<td></td>').text(++lastIndex);
            $td2.html(line);
            $tr.append($td1);
            $tr.append($td2);
            for (let i = 0; i < config.emptyCols; i++) {
                let tdContent = "";
                if (config.enableExcelRandomPopulate && i < config.maxExcelRandomPopulateCol) {
                    tdContent = generateRandomContent(i);
                }
                $tr.append($(`<td>${tdContent}</td>`));
            }
            $tbody.append($tr);


        });
    }

    function setExcelContent($contentEl, type = 'br', clone = false, rowHandler) {
        if (config.mode !== DICT.MODE.EXCEL) {
            return;
        }

        if (type === 'br') {
            const lines = $contentEl.html().split('<br>');
            setExcelLines(lines);
        } else if (type === 'p') {
            let pList;
            if (clone) {
                pList = $contentEl.children('p').clone().toArray();
            } else {
                pList = $contentEl.children('p').toArray();
            }
            //去除空的p标签
            pList = pList.filter(function (p) {
                return $(p).text().trim() !== '';
            });
            setExcelLines(pList);
        }

    }

    function addEmptyExcelLines(num = 1) {
        setExcelLines(new Array(num).fill("\u200B"), true);
    }

    function addGlobalStyle(styleText) {
        GM_addStyle(styleText);
    }

    function addWordStyle(styleText) {
        if (config.mode === DICT.MODE.WORD) {
            GM_addStyle(styleText);
        }
    }

    function addExcelStyle(styleText) {
        if (config.mode === DICT.MODE.EXCEL) {
            GM_addStyle(styleText);
        }
    }

    function excelUnsupported() {
        if (config.mode === DICT.MODE.EXCEL) {
            alert("本站部分或全部章节不支持Excel模式,将切换到Word模式");
            applyMode(DICT.MODE.WORD);
        }
    }

    function clearWordContent() {
        if (config.mode === DICT.MODE.WORD) {
            $('#disguised-content').empty();
        }

    }

    function setDisguisedTitle(titleStr) {
        $('#disguised-title').text(titleStr);
    }

    function setWordDetail(detail) {
        const $footerEl = $('#footer-content');
        $footerEl.text("");
        if (typeof detail === "string") {
            $footerEl.text(detail);
        } else {
            detail.appendTo($footerEl);
        }

    }

    function setWordRightContent($contentEl) {
        $contentEl.appendTo($("#disguised-right-content"));
    }

    function getScreenInfo() {
        const screenWidth = window.screen.width;
        const screenHeight = window.screen.height;
        const devicePixelRatio = window.devicePixelRatio || 1;
        const physicalWidth = screenWidth * devicePixelRatio;
        return {screenWidth, screenHeight, devicePixelRatio, physicalWidth};
    }

    function generateRandomContent(type = 1) {
        type = (type % 6) + 1;

        function generateRandomLetters(n, isUpperCase) {
            const letters = isUpperCase ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' : 'abcdefghijklmnopqrstuvwxyz';
            let result = '';
            for (let i = 0; i < n; i++) {
                result += letters.charAt(Math.floor(Math.random() * letters.length));
            }
            return result;
        }

        function getRandomInt(a, b) {
            return Math.floor(Math.random() * (b - a + 1)) + a;
        }

        function getRandomPaddedInt(n) {
            // 生成 n 位数范围内的随机数
            const max = Math.pow(10, n) - 1;
            const min = Math.pow(10, n - 1);
            const randomInt = Math.floor(Math.random() * (max - min + 1)) + min;

            // 返回左侧填充0的字符串
            return randomInt.toString().padStart(n, '0');
        }

        function getRandomItem(list) {
            return list[Math.floor(Math.random() * list.length)];
        }

        function getRandomChineseName() {
            const surnames = ["赵", "钱", "孙", "李", "周", "刘", "王"];
            const commonGivenChars = [
                "伟", "秀", "敏", "静", "丽", "强", "磊", "军", "洋", "杰", "婷", "浩", "婷", "欣",
                "佳", "琪", "婧", "思", "鑫", "博", "宇", "轩", "涵", "宁", "瑶", "晨", "泽", "瑞"
            ];

            const surname = getRandomItem(surnames);
            const len = Math.random() < 0.5 ? 1 : 2;   // 50% 概率取单名或双名
            let given = "";
            for (let i = 0; i < len; i++) {
                given += getRandomItem(commonGivenChars);
            }
            return surname + given;
        }

        function getRandomDateUsingRandomNumbers() {
            const year = Math.floor(Math.random() * (2024 - 2020 + 1)) + 2020;
            const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0');
            const day = String(Math.floor(Math.random() * 28) + 1).padStart(2, '0'); // 简单处理,每月最多28天
            return `${year}-${month}-${day}`;
        }

        function getYesNo() {
            return Math.random() < 0.5 ? '是' : '否';
        }

        switch (type) {
            case 1:
                //编码
                return `${generateRandomLetters(2, true)}-${generateRandomLetters(2, true)}-${generateRandomLetters(2, true)}${getRandomPaddedInt(6)}`;
            case 2:
                //人名
                return getRandomChineseName();
            case 3:
                //日期
                return getRandomDateUsingRandomNumbers();
            case 4:
                //随机数
                return getRandomInt(1, 9999);
            case 5:
                //字母
                return generateRandomLetters(1, true);
            case 6:
                //是否
                return getYesNo();
        }
    }

    function showModal(content, modalConfig = {}) {
        const $modal = $(`
        <div class="disguised-modal-wrapper">
            <div class="disguised-modal-header">
                <div class="disguised-modal-title">${modalConfig.title || ""}</div>
                
            </div>
            <div class="disguised-modal-body"></div>
        </div>
        `);

        const $headerClose = $(`<div class="disguised-modal-header-close"></div>`);
        $headerClose.on("click", function () {
            $modal.remove();
        });
        $modal.find(".disguised-modal-header").append($headerClose);

        if (modalConfig.width && typeof modalConfig.width === "number") {
            $modal.css("width", `${modalConfig.width}px`);
        }

        if (typeof content === "string") {
            $modal.find(".disguised-modal-body").text(content);
        } else {
            content.appendTo($modal.find(".disguised-modal-body"));
        }

        $("#disguised-page").append($modal);
        return $modal;
    }

    /**
     * 消息弹框
     *
     * 使用了HLD大佬的代码
     *
     * @see http://greasyfork.icu/zh-CN/scripts/393991-nga%E4%BC%98%E5%8C%96%E6%91%B8%E9%B1%BC%E4%BD%93%E9%AA%8C/code
     * @method popMsg
     * @param {String} msg 消息内容
     * @param {String} type 消息类型 [ok, err, warn]
     */
    function popMsg(msg, type = 'ok') {
        $('.nd_msg').length > 0 && $('.nd_msg').remove();
        let $msg = $(`<div class="nd_msg nd_msg-${type}">${msg}</div>`);
        $('body').append($msg);
        $msg.slideDown(200);
        setTimeout(() => {
            $msg.fadeOut(500);
        }, type == 'ok' ? 2000 : 5000);
        setTimeout(() => {
            $msg.remove();
        }, type == 'ok' ? 2500 : 5500);
    }

    /**
     * 获取指定的cookie值
     */
    function getCookie(name) {
        let cookieArr = document.cookie.split(";");

        for (let i = 0; i < cookieArr.length; i++) {
            let cookiePair = cookieArr[i].split("=");

            // 取出cookie名称时去除前后空格
            if (name === cookiePair[0].trim()) {
                return decodeURIComponent(cookiePair[1]);
            }
        }
        return null;
    }

    /**
     * 设置cookie的值
     */
    function setCookie(name, value, days, domain = null) {
        let expires = "";
        if (days) {
            let expireDate = new Date();
            expireDate.setDate(expireDate.getDate() + days);
            expires = "; expires=" + expireDate.toUTCString();
        }

        let domainStr = "";
        if (domain) {
            domainStr = "; domain=" + domain;
        }
        document.cookie = name + "=" + (value || "") + expires + domainStr + "; path=/";
    }

    /**
     * 把 target 的滚动“伪装”为 source 的滚动:镜像事件 + jQuery 取值映射(可选)
     * 单向桥接,避免回弹
     * @param {Element|string} source 站内监听用的容器(如 #idrviewer)
     * @param {Element|string} target 实际滚动容器(如 #disguised-body)
     * @param {Object} [opts]
     * @param {boolean} [opts.twoWay=false]  是否反向同步(一般不要开,开了可能回弹)
     * @param {boolean} [opts.patchJQuery=true] 是否打 jQuery 补丁(映射 $(source).scrollTop/height & .on)
     * @param {boolean} [opts.mirrorGlobal=false] 是否同时触发 window/document 的 scroll
     * @param {boolean} [opts.syncNative=false] 是否把 source.scrollTop 原生属性也设置为 target 的值(可能引发回弹,默认关)
     * @returns {{teardown: Function}}
     */
    function bridgeScrollContainers(source, target, opts = {}) {
        const {
            twoWay = false,
            patchJQuery = true,
            mirrorGlobal = false,
            syncNative = false, // 关键:默认不改原生 scrollTop
        } = opts;

        const src = (typeof source === 'string') ? document.querySelector(source) : source;
        const tgt = (typeof target === 'string') ? document.querySelector(target) : target;
        if (!src || !tgt) {
            printLog('warn', '滚动桥接容器错误', {source, target});
            return {
                teardown: () => {
                }
            };
        }

        // 幂等
        if (src.__bridge_to === tgt && tgt.__bridge_from === src) return {
            teardown: () => {
            }
        };
        src.__bridge_to = tgt;
        tgt.__bridge_from = src;

        // 确保 target 可滚动
        const cs = getComputedStyle(tgt);
        if (!/(auto|scroll|overlay)/.test(cs.overflowY)) tgt.style.overflowY = 'auto';

        let rafTickA = false;
        let rafTickB = false;

        // target -> source:镜像 scroll 事件(必要时同步原生 scrollTop,默认不做)
        const onTargetScroll = () => {
            if (rafTickA) return;
            rafTickA = true;
            requestAnimationFrame(() => {
                rafTickA = false;
                if (syncNative) {
                    try {
                        src.scrollTop = tgt.scrollTop;
                    } catch (e) {
                    }
                }
                // 触发 source 上的 scroll 监听器
                src.dispatchEvent(new Event('scroll', {bubbles: false}));
                if (mirrorGlobal) {
                    window.dispatchEvent(new Event('scroll'));
                    document.dispatchEvent(new Event('scroll'));
                }
            });
        };
        tgt.addEventListener('scroll', onTargetScroll, {passive: true});

        // source -> target:反向同步(默认关闭;只有你非常确定站内不会写回 0 时才打开)
        const onSourceScroll = () => {
            if (!twoWay) return;
            if (rafTickB) return;
            rafTickB = true;
            requestAnimationFrame(() => {
                rafTickB = false;
                try {
                    tgt.scrollTop = src.scrollTop;
                } catch (e) {
                }
                // 让依赖 target 的监听器也感知
                tgt.dispatchEvent(new Event('scroll', {bubbles: false}));
            });
        };
        if (twoWay) src.addEventListener('scroll', onSourceScroll, {passive: true});

        // jQuery 兼容:把 $(source).scrollTop()/height() 映射到 target,并镜像后续 .on('scroll')
        let unpatchJQ = () => {
        };
        if (patchJQuery && window.jQuery) {
            const $ = window.jQuery;
            const _scrollTop = $.fn.scrollTop;
            const _height = $.fn.height;
            const _on = $.fn.on;

            $.fn.scrollTop = function (val) {
                const el = this[0];
                if (el === src) {
                    if (val === undefined) return $(tgt).scrollTop();
                    $(tgt).scrollTop(val);
                    return this;
                }
                return _scrollTop.apply(this, arguments);
            };
            $.fn.height = function () {
                const el = this[0];
                if (el === src) return tgt.clientHeight;
                return _height.apply(this, arguments);
            };
            $.fn.on = function (types, selector, data, fn) {
                const res = _on.apply(this, arguments);
                try {
                    const el = this[0];
                    if (el === src && typeof types === 'string' && /\bscroll\b/.test(types)) {
                        const handler = fn || data || selector;
                        if (typeof handler === 'function') $(tgt).on(types + '.mirror', handler);
                    }
                } catch (e) {
                }
                return res;
            };

            unpatchJQ = () => {
                $.fn.scrollTop = _scrollTop;
                $.fn.height = _height;
                $.fn.on = _on;
            };
        }

        // 初始化:触发一次站内 scroll 检查
        src.dispatchEvent(new Event('scroll', {bubbles: false}));
        window.dispatchEvent(new Event('resize'));

        return {
            teardown() {
                try {
                    tgt.removeEventListener('scroll', onTargetScroll);
                    if (twoWay) src.removeEventListener('scroll', onSourceScroll);
                    unpatchJQ();
                } catch (e) {
                }
                delete src.__bridge_to;
                delete tgt.__bridge_from;
            }
        };
    }

    /**
     * 把 source 的原生滚动 API 代理到 target:
     * - source.scrollTop 读/写  -> target.scrollTop
     * - source.scrollTo / scrollBy -> 调用 target 对应方法
     * 注意:只代理这个实例,不会全局污染。
     */
    function patchNativeScrollProxy(source, target) {
        const src = (typeof source === 'string') ? document.querySelector(source) : source;
        const tgt = (typeof target === 'string') ? document.querySelector(target) : target;
        if (!src || !tgt) return;

        // 幂等
        if (src.__nativeScrollProxiedTo === tgt) return;
        src.__nativeScrollProxiedTo = tgt;

        try {
            // 代理 scrollTop getter/setter
            const desc = Object.getOwnPropertyDescriptor(Element.prototype, 'scrollTop');
            // 某些浏览器把 scrollTop 定义在 HTMLElement.prototype 上
            const proto = desc ? Element.prototype : HTMLElement.prototype;
            const current = Object.getOwnPropertyDescriptor(proto, 'scrollTop');

            Object.defineProperty(src, 'scrollTop', {
                configurable: true,
                get() {
                    return tgt.scrollTop;
                },
                set(v) {
                    tgt.scrollTop = v;
                },
            });
        } catch (e) {
            // 某些环境不允许覆盖;忽略即可(scrollTo/By 仍然能代理)
        }

        // 代理 scrollTo
        const origScrollTo = src.scrollTo?.bind(src);
        src.scrollTo = function (a, b) {
            if (typeof a === 'object' && a) {
                // scrollTo({ top, left, behavior })
                const top = 'top' in a ? a.top : tgt.scrollTop;
                const left = 'left' in a ? a.left : tgt.scrollLeft;
                tgt.scrollTo({top, left, behavior: a.behavior});
            } else {
                // scrollTo(x, y)
                tgt.scrollTo(a || 0, b || 0);
            }
        };

        // 代理 scrollBy
        const origScrollBy = src.scrollBy?.bind(src);
        src.scrollBy = function (a, b) {
            if (typeof a === 'object' && a) {
                const top = 'top' in a ? a.top : 0;
                const left = 'left' in a ? a.left : 0;
                tgt.scrollBy({top, left, behavior: a.behavior});
            } else {
                tgt.scrollBy(a || 0, b || 0);
            }
        };
    }


/////////////////////////////针对站点

    /**
     * 起点
     */
    function qidian() {

        GM_addStyle(`
        #right-container {
            position: unset;
            height: 100%;
        }
        .chapter-end-qrcode {
          display: none;
        }
        .review-icon {
          background: var(--surface-gray-100) !important;
        }
        .review-count {
          color: var(--surface-gray-200) !important;
        }
        .tooltip-wrapper {
            display: none;
        }
        #side-sheet div, #side-sheet section {
            background-color: #FFF;
        }
        .chapter-date {
            background: unset !important;
        }
        button {
            background-color: ${link_bg_color} !important;
            color: ${link_text_color} !important;
        }
        button > span {
            color: ${link_text_color} !important;
        }
        #page-ops {
            // display: none !important;
        }
        
        .excel-table tbody td, .excel-table tbody td p {
            font-family: unset;
        }
        .excel-table tbody td p {
            margin-top: 0 !important;
        }
      
        `);

        const $mainContent = $("main.content");
        const contentId = $mainContent.attr('id');
        const dataType = $mainContent.attr('data-type');
        const $tbody = $(".excel-table tbody");

        //内容
        const scriptContent = $('#vite-plugin-ssr_pageContext').html();
        if (scriptContent && scriptContent.includes('"freeStatus":0')) {
            //免费
            setWordContent($(".chapter-wrapper"));
            setExcelContent($("main.content"), 'p', true);
            setTimeout(function () {
                clearWordContent();
                setWordContent($(".chapter-wrapper"));
                setWordRightContent($("#right-container"));
                setExcelContent($("main.content"), 'p');
                setExcelLines([$(".nav-btn-group")], true);
                observeComments();
                setInfo();
            }, 2000);
        } else {
            if (!$('main.content').hasClass('lock-mask')) {
                //收费
                const targetNode = document.querySelector('main.content');
                const config = {childList: true};
                const callback = function (mutationsList, observer) {
                    for (let mutation of mutationsList) {
                        if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                            setWordContent($(".chapter-wrapper"));
                            setWordRightContent($("#right-container"));
                            $tbody.attr("id", contentId);
                            $tbody.attr("data-type", dataType);
                            $tbody.addClass("content");
                            setExcelContent($("main.content"), 'p', true);
                            setTimeout(function () {
                                setExcelContent($("main.content"), 'p');
                                setExcelLines([$(".nav-btn-group")], true);
                            }, 2000);
                            observeComments();
                            setInfo();
                            observer.disconnect();
                            break;
                        }
                    }
                };
                const observer = new MutationObserver(callback);
                observer.observe(targetNode, config);
            } else {
                //未解锁
                setWordContent($(".chapter-wrapper"));
                setExcelLines($(".chapter-wrapper section:not(#r-recommends) > div:not(.download)").toArray());

                // const $loginButton = $("button:contains('登录')");
                // if ($loginButton.length > 0) {
                //     setExcelLines([$loginButton], true);
                // }
            }
        }
        setInfo();

        addExcelStyle(`
             #disguised-page #disguised-body table.excel-table tbody:not(thead) tr .nav-btn-group a {
                font-family: "Microsoft YaHei", "SimSun", sans-serif !important;
            }
            #disguised-page #disguised-body table.excel-table tbody td:not(:nth-child(1)):not(:nth-child(2)) {
                font-family: "Microsoft YaHei", "SimSun", sans-serif !important;
            }
            .nav-btn {
                padding: 0;
            }
            .excel-table button {
                padding: 0;
                font-size: unset;
                line-height: unset;
                height: 20px;
            }
            
        `);

        function observeComments() {
            //本章说
            const targetNode2 = document.querySelector('#side-sheet');
            const callback2 = function (mutationsList, observer) {
                for (let mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        if (mutation.addedNodes.length > 0) {
                            $("#disguised-right-content").show();
                        }
                        if (mutation.removedNodes.length > 0) {
                            $("#disguised-right-content").hide();
                        }
                    }
                }
            };
            const observer2 = new MutationObserver(callback2);
            observer2.observe(targetNode2, {childList: true});
        }

        function setInfo() {
            const titleEl = $('.chapter-wrapper h1.title');
            setDisguisedTitle(titleEl.children().remove().end().text());
            titleEl.hide();

            const infoEl = titleEl.next();
            setWordDetail(infoEl.children());
            infoEl.hide();

            const downloadEl = $('#r-authorSay :contains("下载App")');
            downloadEl.hide();
        }


        setTimeout(function () {
            // 打赏按钮
            const admireBtnEl = $('._admireBtn_131ir_200');
            admireBtnEl.hide();

            $('body').attr('data-theme', 'beige');
        }, 2000);

    }

    /**
     * 番茄
     * e.g. 免费章节 https://fanqienovel.com/reader/7159891022602830375?enter_from=reader
     * e.g. vip章节 https://fanqienovel.com/reader/7226402549753250363?enter_from=reader
     */
    function fanqie() {
        GM_addStyle(`
        .muye-reader-nav {
            display: none !important;
        }
        
        .byte-btn {
            background: ${link_bg_color} !important;
            color: ${link_front_color} !important;
        }
        
        .reader-toolbar {
            display: none;
        }
        
        .muye-reader-box {
            padding-top: 50px;
        }
        
        .excel-table tbody td, .excel-table tbody td p {
            font-family: unset;
        }
        
        p {
            margin: 0;
        }
        
        `);

        setWordContent($(".muye-reader-inner"));
        const titleEl = $('h1.muye-reader-title');
        setDisguisedTitle(titleEl.text());
        titleEl.remove();

        const infoEl = $('.muye-reader-subtitle');
        setWordDetail(infoEl.children());
        infoEl.hide();

        const $readerBox = $('.muye-reader-box');
        const className = $readerBox.attr('class').split(' ').filter(function (cls) {
            return cls.indexOf('font-') === 0;
        })[0];
        let styleAttr = $readerBox.attr('style');
        addExcelStyle(`
        .excel-table tbody td p {
            ${styleAttr}
        }
        `);

        setExcelLines($(".muye-reader-content>div>p").toArray());
        setExcelLines([$(".muye-reader-btns")], true);
        addExcelStyle(`
            .muye-reader-btns button {
                height: 20px !important;
                line-height: 20px !important;
            }
        `);
        $(".muye-reader-btns button").on("click", function () {
            setTimeout(function () {
                location.reload();
            }, 200);
        });

        $(".arco-tooltip").remove();
    }

    /**
     * 笔趣阁
     * biquge.net
     */
    function biquge_net() {

        GM_addStyle(`
        #read_tj {
            display: none;
        }
        
        .section-opt {
            border-top: none !important;
            border-bottom: none !important;
            color: ${link_text_color};
        }
        
        .section-opt a {
            color: ${link_text_color} !important;
        }
        
        .reader-main > a {
            display: none;
        }
        
        `);

        setWordContent($(".reader-main"));
        setDisguisedTitle($(".title").text());
        setExcelContent($("#content"), "p");
        setExcelLines([$(".section-opt").first()], true);
    }

    /**
     * 书香小说
     * xbiqugu.net
     */
    function xbiqugu_net() {
        GM_addStyle(`
        body {
            background-color: #FFF;
        }
        .con_top, #listtj, #content_tip, .bookname>h1, #bdshare, #content>p {
            display: none;
        }
        
        .box_con {
            border: none;
        }
        
        .bookname {
            border-bottom: none;
            color: ${link_text_color};
        }
        
        .bottem2 {
            border-top: none;
            color: ${link_text_color};
            text-align: unset;
            width: unset;
            margin: 0;
            padding: 0;
        }
        
        .bottem1>a, .bottem2>a {
            color: ${link_text_color};
        }
        
        .box_con > table {
            display: none !important;
        }
        
        `);

        $("#content>p").remove();
        setWordContent($(".box_con"));
        setExcelContent($("#content"));
        setExcelLines([$(".bottem2")], true);
        setDisguisedTitle($(".bookname h1").text());
    }

    /**
     * 笔趣阁
     * biquge.co
     */
    function biquge_co() {
        xbiqugu_net();
        GM_addStyle(`
        .lm {
            display: none;
        }
        `);
    }

    /**
     * 笔趣阁
     * www.52wx.com
     */
    function www_52wx_com() {
        GM_addStyle(`
        .hotcmd-box {
            display: none !important;
        }
        #content {
            color: black !important;
        }
        `);
        biquge_net();
        setExcelContent($("#content"));
        setExcelLines([$(".section-opt").first()], true);
    }

    /**
     * 笔趣阁
     * www.3bqg.cc
     */
    function www_3bqg_cc() {
        GM_addStyle(`
        #chaptercontent {
            border-top: none !important;
            border-bottom: none !important;
        }
        
        .content > h1, .content > .link, .readinline {
            display: none !important;
        }
        
        .Readpage a{
            color: ${link_text_color} !important;
            text-shadow: none !important;
        }
        `);
        addExcelStyle(`
            .pagedown {
                padding: 0;
                margin-bottom: 0;
                height: unset;
                line-height: unset;
                text-align: unset;
            }
        `);
        $(".readinline").remove();
        setWordContent($(".content"));
        setDisguisedTitle($(".content>h1").text());
        setExcelContent($("#chaptercontent"));
        setExcelLines([$(".pagedown")], true);
    }

    /**
     * 笔趣阁
     * www.bigee.cc
     */
    function www_bigee_cc() {
        www_3bqg_cc();
    }

    /**
     * 笔趣阁
     * beqege.cc
     */
    function www_beqege_cc() {
        GM_addStyle(`
        .box_con {
            border: none !important;
        }
        
        .read-novel-link, #device, .con_top, .bookname>h1, #test1{
            display: none !important;
        }
        
        .bottem1, .bottem2 {
            border-top: none !important;
            border-bottom: none !important;
        }
        
        .bottem1 a, .bottem2 a {
            color: ${link_text_color} !important;
        }
        `);
        addExcelStyle(`
            .bottem1 {
                text-align: unset;
                margin: 0;
                padding-bottom: 0;
            }
        `);
        setWordContent($(".box_con"));
        setDisguisedTitle($(".bookname>h1").text());
        setExcelContent($("#content"), "p");
        setExcelLines([$(".bottem1")], true);
    }

    /**
     * 笔书网
     * biqukun.com
     */
    function www_biqukun_com() {
        www_beqege_cc();
        GM_addStyle(`
        .lm {
            display: none !important;
        }
        
        .bookname {
            border-bottom: none !important;
        }
        
        .box_con > table {
            display: none !important;
        }
        `);
        setExcelContent($("#content"));
        setExcelLines([$(".bottem2")], true);
    }

    /**
     * 笔趣阁
     * biquge.tw
     */
    function www_biquge_tw() {
        GM_addStyle(`
        #readSet, .book>h1, .chase-book-btn {
            display: none !important;
        }
        
        .read-page, .read-page a {
            border-top: none !important;
            border-bottom: none !important;
            border-left: none !important;
            border-right: none !important;
        }
        
        @media (min-width: 768px) {
            .book {
                padding: unset;
            }
        }
        `);

        setDisguisedTitle($(".book>h1").text());
        setWordContent($(".book"));
        setExcelContent($("#chaptercontent"), "p");
        setExcelLines([$(".read-page").first()], true);
    }

    /**
     * 轻小说文库
     * wenku8.net
     */

    function www_wenku8_net() {
        GM_addStyle(`
        #content {
            padding: 20px;
        }
        
        #foottext {
            text-align: center;
        }
        
        #foottext a {
            color: ${link_text_color};
        }
        `);

        $('#foottext a[href^="http"]').remove();
        $("ul[id='contentdp']").remove();
        setWordContent($("#content"));
        setWordContent($("#foottext"));
        setDisguisedTitle($("#title").text());
        setExcelContent($("#content"));
        setExcelLines([$("#foottext").first()], true);
        addExcelStyle(`
            #foottext {
                text-align: unset;
            }
        `);
    }

    /**
     * 哔哩轻小说
     * www.bilinovel.com
     * 小说阅读页面会跳转到 www.linovelib.com
     * https://www.linovelib.com/novel/4666/275666_2.html, https://www.linovelib.com/novel/2025/251952_2.html 存在部分字体加密
     */
    function linovelib_com() {
        GM_addStyle(`
        .mlfy_page {
            width: 100%;
            background: none !important;
        }
        `);

        $("#mlfy_main_text>h1").hide();
        setWordContent($("#mlfy_main_text"));
        setDisguisedTitle($("#mlfy_main_text>h1").text());
        setWordContent($(".mlfy_page"));
        setExcelContent($("#TextContent"), "p");
        setExcelLines([$(".mlfy_page")], true);
        addExcelStyle(`
        .mlfy_page {
            display: block !important;
            height: unset !important;
            line-height: unset !important;
        }
        .mlfy_page > a {
            line-height: unset !important;
            font-size: 12px;
            width: 80px;
        }
        .mlfy_page > a:hover {
            color: unset !important;
        }
        `);

        // 处理字体加密
        if (config.mode === DICT.MODE.EXCEL) {
            window.addEventListener('load', () => {
                // 如果浏览器支持 adoptedStyleSheets,就优先用它
                const sheets = document.adoptedStyleSheets || [];
                for (const sheet of sheets) {
                    for (const rule of Array.from(sheet.cssRules)) {
                        if (rule.style && rule.style.fontFamily && rule.style.fontFamily.includes('read')) {
                            printLog('找到规则:', rule.selectorText);
                            // 姑且先按 #TextContent p:nth-last-of-type(2) 的形式处理
                            const encryptedIndex = ((sel) => {
                                if (!sel) return null;
                                const m = sel.match(/nth-last-of-type\((\d+)\)/);
                                return m ? +m[1] : null;
                            })(rule.selectorText);
                            printLog('encryptedIndex', encryptedIndex);
                            if (encryptedIndex) {
                                addExcelStyle(`
                                .excel-table tbody tr:nth-last-of-type(${encryptedIndex}) td:nth-child(2) p {
                                    font-family: "read" !important;
                                }
                                `);
                            }

                        }
                    }
                }
            });
        }
    }

    /**
     * bilinovel原站, mac不会跳转linovelib.com
     * 存在字体加密 https://www.bilinovel.com/novel/2025/72668_2.html
     */
    function biilinovel_com() {
        addGlobalStyle(`
        html ins {
            display: none !important;
        }
        `);
        addExcelStyle(`
         table {
            table-layout: auto !important;
            word-break: normal !important;
         }
         table th {
            border-bottom: none !important;
         }
         table tr {
            border-top: none !important;
         }
         .footlink {
            border-top: none !important;
            line-height: unset !important;
            font-size: unset !important;
         }
         .footlink a {
            display: unset !important;
            margin-bottom: unset !important;
            width: unset !important;
            padding: unset !important;
            margin: unset !important;
            margin-right: 10px !important;
            float: unset !important;
        }
        `);

        const $content = $("#acontent");
        const $footLink = $("#footlink");
        setDisguisedTitle($("#atitle").text());
        setWordDetail($(".atitle h3").text());

        setWordContent($content);
        setWordContent($footLink);

        $footLink.css("display", "block");
        setExcelContent($content, "p");
        setExcelLines([$footLink], true);

        // 处理字体加密
        if (config.mode === DICT.MODE.EXCEL) {
            window.addEventListener('load', () => {
                // 如果浏览器支持 adoptedStyleSheets,就优先用它
                const sheets = document.styleSheets || [];
                printLog('sheets', sheets);
                for (const sheet of sheets) {
                    for (const rule of Array.from(sheet.cssRules)) {
                        if (rule.style && rule.style.fontFamily && rule.style.fontFamily.includes('read')) {

                            if (!rule.selectorText || rule.selectorText.includes(".excel-table")) continue;
                            printLog('找到规则:', rule.selectorText);

                            // 姑且先按 #TextContent p:nth-last-of-type(2) 的形式处理
                            const encryptedIndex = ((sel) => {
                                if (!sel) return null;
                                const m = sel.match(/nth-last-of-type\((\d+)\)/);
                                return m ? +m[1] : null;
                            })(rule.selectorText);

                            if (encryptedIndex) {
                                printLog('encryptedIndex', encryptedIndex);
                                addExcelStyle(`
                                .excel-table tbody tr:nth-last-of-type(${encryptedIndex}) td:nth-child(2) p {
                                    font-family: "read" !important;
                                }
                                `);
                            }

                            //如果有 p:last-of-type
                            const isEncryptedLast = ((sel) => {
                                if (!sel) return false;
                                return /p:last-of-type/.test(sel);
                            })(rule.selectorText);
                            if (isEncryptedLast) {
                                addExcelStyle(`
                                .excel-table tbody tr:nth-last-of-type(2) td:nth-child(2) p {
                                    font-family: "read" !important;
                                }
                                `);
                            }
                        }
                    }
                }
            });
        }
    }

    /**
     * 七猫
     * www.qimao.com
     */
    function qimao_com() {
        GM_addStyle(`
        .chapter-tips {
            display: flex;
        }
        .chapter-tips dd, .chapter-tips dt {
            display: flex;
            align-items: center;
        }
        .chapter-tips dd {
            margin-right: 10px;
        }
        .reader-footer {
            padding: 0 !important;
        }
        .qm-btn {
            background-image: none !important;
            border: none !important;
            font-weight: normal !important;
        }
        `);
        setDisguisedTitle($(".chapter-title").text());
        setWordDetail($(".chapter-tips"));
        setWordContent($(".chapter-detail-wrap-content"));
        excelUnsupported();
    }

    /**
     * 晋江
     * www.jjwxc.net
     */
    function jinjiang() {

        GM_addStyle(`
        .novel-pager {
            border: none !important;
            padding: 0 !important;
        }
        h2 {
            display: none;
        }
        #note_danmu_wrapper {
            display: none;
        }
        div[align='right'] {
            display: none;
        }
        `);

        const novelTitle = $("h1 span").text();
        const chapterTitle = $("h2").text();
        setDisguisedTitle(`${novelTitle} ${chapterTitle}`);

        let $content = $(".novelbody").first().children("div");
        const $pager = $(".noveltitle").eq(1).addClass("novel-pager");
        setWordContent($pager.clone());
        setWordContent($content);
        setWordContent($pager.clone());
        setWordDetail(originalTitle);
        $content.children("div").first().remove();
        $content.children("div").last().remove();

        if (config.mode === DICT.MODE.EXCEL) {
            $("h2").remove();
            $("#note_danmu_wrapper").remove();
            $("div[align='right']").remove();

            if ($('.noveltext').length > 0) {
                const fontFamily = $('.noveltext').css('font-family');
                addExcelStyle(`
                    .excel-table tbody td {
                        font-family: ${fontFamily}
                    }
                `);
            }

        } else {
            //这些文字删掉之后又会自动加回来。。
            setTimeout(function () {
                $content.html($content.html().replace(/@无限好文,尽在晋江文学城/g, ''));
            }, 4000);
        }

        setExcelContent($content);
        setExcelLines([$pager], true);
    }

    /**
     * 晋江
     * 购买页面 及付费章节页面
     * e.g. https://my.jjwxc.net/backend/buynovel.php?novelid=4104036&chapterid=21
     * e.g. https://my.jjwxc.net/onebook_vip.php?novelid=4104036&chapterid=21
     */
    function jinjiangBuy() {
        if (window.location.pathname.includes('/backend/buynovel')) {
            const content = '关闭脚本以完成购买';
            setDisguisedTitle(content);
            setWordContent($(`
                <div style="text-align: center;">${content}</div>
            `));
            setExcelLines([content]);
        } else if (window.location.pathname.includes('/onebook_vip.php')) {
            jinjiang();
        }


    }

    /**
     * 轻之国度
     * lightnovel.us
     */
    function lightnovel_us() {

        GM_addStyle(`
        #footer-content>:not(span) {
            display: none;
        }
        #footer-content {
            display: flex;
            align-items: center;
        }
        #footer-content span {
            vertical-align: unset;
            display: flex;
            align-items: center;
        }
        #article-main-contents {
            padding: 15px;
        }
        `);

        hideImages({selector: '#article-main-contents img'});
        registerImageIndicators();

        setWordContent($(".article-content"));
        setExcelContent($("#article-main-contents"));
        setDisguisedTitle($(".article-title").text());
        setWordDetail($(".article-infos").children());
    }

    /**
     * 飞卢小说
     * faloo.com
     */
    function faloo_com() {
        GM_addStyle(`
        .noveContent {
            padding: 15px;
        }
        #footer-content {
            display: flex;
        }
        #footer-content span,  #footer-content a {
            display: flex;
            align-items: center;
        }
        #footer-content img {
            display: none;
        }
        #footer-content div {
            display: none;
        }
        #pageHtml {
            display: flex;
            font-size: 14px !important;
        }
        .next_page_btn {
            font-size: 14px !important;
        }
        #pageHtml img {
            display: none;
        }
        div.noveContent .con_img div:nth-child(2) {
            width: 100% !important;
        }
        .con_img > div {
            width: 100% !important;
        }
        `);
        excelUnsupported();
        setWordContent($(".noveContent"));
        setWordContent($("#pageHtml"));
        setDisguisedTitle($(".c_l_title").text());
        setWordDetail($(".c_l_info").children());
    }

    /**
     * 69书吧
     * 69shuba.cx
     * e.g. https://69shuba.cx/txt/56042/39089569
     */
    function _69shuba_cx() {
        GM_addStyle(`
        .page1 a{
            line-height: normal;
        }
        `);

        setDisguisedTitle($("h1").text());
        setWordDetail($(".txtinfo").text());

        $("h1").remove();
        $(".txtinfo").remove();
        const $txt = $(".txtnav");
        setWordContent($txt);
        setWordContent($(".page1"));
        $txt.find("script").remove();
        setExcelContent($txt);
        setExcelLines([$(".page1")], true);
    }

    /**
     * owlook
     * 基于开源项目owllook搭建的
     * e.g. https://www.owlook.com.cn/owllook_content?url=https://www.bq99.cc/book/141046/42.html&name=%E7%AC%AC%E5%9B%9B%E5%8D%81%E4%B8%80%E7%AB%A0%20%E7%AD%91%E5%9F%BA%E5%8A%9F%E6%B3%95&chapter_url=https://www.bq99.cc/book/141046/&novels_name=%E4%BF%AE%E7%9C%9F%E8%81%8A%E5%A4%A9%E7%BE%A4
     *
     */
    function www_owlook_com_cn() {
        addGlobalStyle(`
            .nd_owllook_pager a {
                color: black;
            }
        `);
        addWordStyle(`
            .nd_owllook_pager {
                text-align: center;
            }
        `);

        $(".readinline").remove();
        setDisguisedTitle($("#content_name").text());
        setWordContent($(".show-content"));
        setExcelContent($(".show-content"));
        const $originalPager = $(".pre_next");
        const $pager = $(`
            <div class="nd_owllook_pager">
                <a href="${$originalPager.children().first().attr('href')}">上一章</a>
                <a href="${$('.left-bar-list > div:first-child>a').attr('href')}">目录</a>
                <a href="${$originalPager.children().last().attr('href')}">下一章</a>
            </div>
        `);
        setWordContent($pager);
        setExcelLines([$pager], true);
    }

    /**
     * 刺猬猫阅读
     * e.g. free https://www.ciweimao.com/chapter/112168341
     * e.g. vip https://www.ciweimao.com/chapter/112171956
     */
    function ciweimao_com() {
        excelUnsupported();

        addGlobalStyle(`
            #footer-content > p {
                display: flex;
                align-items: center;
            }
            #footer-content > p > span {
                margin-right: 10px;
            }
            .book-read-page a {
                background-color: unset;
                border: none;
            }
            .book-read-page a:hover {
                background-color: unset;
                border: none;
            }
        `);

        setTimeout(function () {

            // 读取 bookReadTheme 的值
            const cookieKey = 'bookReadTheme';
            let bookReadTheme = getCookie(cookieKey);
            if (!bookReadTheme) {
                setCookie(cookieKey, 'white%2C3%2C18%2Cundefined%2Ctsu-right%2C0', 365, "." + window.location.hostname);
                location.reload();
            } else if (!bookReadTheme.startsWith('white')) {
                let commaIndex = bookReadTheme.indexOf(',');
                if (commaIndex !== -1) {
                    //改为白色主题
                    let newBookReadTheme = 'white' + bookReadTheme.substring(commaIndex);
                    // 更新cookie并重新加载页面
                    setCookie(cookieKey, newBookReadTheme, 365, "." + window.location.hostname);
                    location.reload();
                }
            }

            setDisguisedTitle($("h1.chapter").text());
            setWordDetail($(".read-hd>p"));
            $("#J_BookRead_WaterMark").remove();
            $("#J_BookRead p span, #J_BookRead p i").remove();
            $("#J_ImgRead i").remove();
            setWordContent($("#J_BookRead"));
            setWordContent($("#J_ImgRead"));
            setWordContent($(".book-read-page"));
        }, 500);


    }

    /**
     * v站 主题
     * e.g. https://www.v2ex.com/t/1142285
     * e.g. https://www.v2ex.com/t/1143210
     * e.g. https://www.v2ex.com/t/803669?p=2
     */
    function v2exThread() {
        setDisguisedTitle($("h1").text());
        setWordDetail($("small"));
        setWordContent($("#Main"));

        hideImages({selector: ".topic_content img.embedded_image"});
        hideImages({selector: ".reply_content img.embedded_image", replaceParent: true});

        if (config.mode === DICT.MODE.EXCEL) {
            const $outdated = $(".outdated");
            let outdatedText = $outdated.text();
            if ($outdated.length > 0) {
                outdatedText = `[ ${outdatedText} ]`;
            }
            setExcelLines([outdatedText], false);

            const $markdownBody = $(".markdown_body");
            if ($markdownBody.length > 0) {
                setExcelLines(
                    $markdownBody
                        .children()
                        .toArray()
                        .flatMap(el => {
                            // https://www.v2ex.com/t/803669
                            const $kids = $markdownBody.children();
                            if ($kids.length === 1 && $kids.eq(0).is('div')) {
                                return $(el).children().get();
                            } else {
                                return [el];
                            }
                        })
                        .flatMap(el => (el.tagName === 'UL' || el.tagName === 'OL' ? [...el.children] : [el]))
                        .flatMap(el =>
                            $(el).html()
                                .split(/<br\s*\/?>/i)
                                .map(s => s.trim())
                        ), true);
            } else {
                setExcelLines(
                    $(".topic_content")
                        .toArray()
                        .flatMap(el =>
                            $(el).html()
                                .split(/<br\s*\/?>/i)
                                .map(s => s.trim())
                        ), true);
            }
            setExcelLines(
                $(".subtle")
                    .toArray()
                    .flatMap(el => {
                            const arr = $(el).find(".topic_content").html()
                                .split(/<br\s*\/?>/i);
                            arr.unshift($(el).children().first().text());
                            return arr;
                        }
                    ), true);
            setExcelLines([$(".topic_buttons")], true);

            const $replyArea = $("#Main :nth-child(2 of .box)");
            const $paginator = $replyArea.find(".ps_container").first();
            addEmptyExcelLines();
            setExcelLines([$replyArea.children().first(), $paginator], true);
            setExcelLines($("div[id^='r_']")
                .toArray()
                .flatMap(el => {
                        const $reply = $(el).find("td").eq(2);
                        const $name = $reply.find("strong");
                        const $badges = $reply.find(".badges");
                        const $ago = $reply.find("span.ago");
                        const $thanks = $reply.children('span').eq(1);
                        const $feedback = $reply.find(".fr").first();
                        $name.css("margin-right", "10px");
                        $badges.css("margin-right", "10px");
                        $ago.css("margin-right", "10px");
                        const $sender = $name.add($ago).add($feedback).add($badges).add($thanks).wrapAll("<span/>");
                        const content = $reply.find(".reply_content").html().split(/<br\s*\/?>/i);
                        return [$sender, ...content];
                    }
                ), true);
            setExcelLines([$paginator.clone()], true);

            const $replyBox = $("#reply-box");
            $replyBox.hide();
            setExcelLines([$replyBox], true);
            const $showReplyBox = $('<span class="disguised-link">显示回复框</span>');
            $showReplyBox.click(function () {
                $replyBox.show();
                $(this).hide();
            });
            $replyBox.before($showReplyBox);

            padExcelBlankLines();
        }

        registerImageIndicators();

        if (config.mode === DICT.MODE.WORD) {
            $("div.header").remove();
            $("div[id^='r_'] tr td:first-child").remove();
        }

        addGlobalStyle(`
        .topic_buttons {
            background: none;
        }
        a.tag:link {
            background-color: unset;
        }
        div.cell {
            border-bottom: none;
        }
        div.ps_container {
            background: none;
        }
        .button {
            background-image: none !important;
        }
        .page_normal:active, .page_normal:link, .page_normal:visited, .page_current {
            box-shadow: none;
            border: none;
        }
        .page_input {
            box-shadow: none;
            border: 1px solid #f1f1f1;
        }
        img[alt='Reply'] {
            filter: brightness(140%) contrast(90%);
        }
        img[alt='❤️'] {
            opacity: 0.2;
        }
        small, small a:link, small a:visited {
            color: black !important;
        }
        .badge {
            color: #a0d9ff !important;
            border-color: #a0d9ff !important;
        }
        .box {
            box-shadow: none;
            border-bottom: 1px solid #F1F1F1 !important;
        }
        `);
        addWordStyle(`
        div.subtle, div.outdated {
           border-left: none;
           border-bottom: none;
        }
        .button {
            padding: 1px !important;
        }
        `);
        addExcelStyle(`
        p {
            margin-block-start: 0;
            margin-block-end: 0;
        }
        .ps_container .page_input {
            padding: 0;
        }
        .button {
            padding: 0 !important;
        }
        `);

    }

    /**
     * v站-列表
     *
     * e.g. https://www.v2ex.com/recent?p=1
     * e.g. https://www.v2ex.com/?tab=creative
     * e.g. https://www.v2ex.com/
     * e.g. https://www.v2ex.com/go/ipad?p=1
     */
    function v2exList() {
        setDisguisedTitle(originalTitle);
        setWordContent($("#Main"));

        setExcelLines([
            $(".node-breadcrumb"),
            $(".topic-count"),
            $(".intro"),
            $(".header"),
            $(".cell_ops"),
            $(".ps_container").first(),
            $("#Tabs"),
            $("#SecondaryTabs")
        ]);
        setExcelLines($(".cell.item").get(), true);
        setExcelLines($("#TopicsNode").children().get(), true);
        setExcelLines([
            $(".ps_container").first(),
            $("#Main").children(".box").eq(0).children().last().filter(".inner"),
            $("#Main .cell.flex-one-row"),
            $(".cell>form"),
        ], true);
        setExcelLines($("strong:contains('V2EX')").parent().parent().parent().children().get(), true);


        $("div.cell.item tr td:nth-child(-n+2)").remove();
        $("div[class*=' t_'] tr td:nth-child(-n+2)").remove();


        addGlobalStyle(`
        div.cell {
            border-bottom: none;
        }
        div.ps_container {
            background: none;
        }
        .button {
            background-image: none !important;
        }
        .page_normal:active, .page_normal:link, .page_normal:visited, .page_current {
            box-shadow: none;
            border: none;
        }
        .page_input {
            box-shadow: none;
            border: 1px solid #f1f1f1;
        }
        .badge {
            color: #a0d9ff !important;
            border-color: #a0d9ff !important;
        }
        .box {
            box-shadow: none;
            border-bottom: 1px solid #F1F1F1 !important;
        }
        .cell_ops {
            box-shadow: none;
        }
        a.count_livid:link {
            background-color: #e5e5e5;
        }
        .page-content-header > img {
            display: none;
        }
        div.intro {
            color: black;
        }
        `);
        addWordStyle(`
        .button {
            padding: 1px !important;
        }
        `);
        addExcelStyle(`
        .ps_container .page_input {
            padding: 0;
        }
        .node-breadcrumb a {
            color: black;
        }
        .header {
            overflow: hidden;
            border: none;
        }
        #SecondaryTabs {
            padding: 0;
        }
        .button {
            padding: 0 !important;
        }
        `);
    }

    /**
     * 可乐小说
     * e.g. https://www.kelexs.com/book/DBIFGD-15.html
     */
    function www_kelexs_com() {
        $("#ad-container").remove();
        addGlobalStyle(`
        html, body {
            text-align: unset;
        }
        .btnW .btnBlack {
            display: unset;
            border: none;
            background-color: ${link_bg_color};
            color: ${link_text_color};
        }
        `);
        addWordStyle(`
        p {
            margin: 16px;
        }
        `);
        addExcelStyle(`
        .btnBlack {
            line-height: unset;
        }
        `);
        setDisguisedTitle($("h1.title").text());
        setWordDetail($("div.about").text());
        setWordContent($("div.content"));
        setWordContent($(".conBox .btnW"));
        setExcelContent($("div.content"), "p");
        setExcelLines([$(".conBox .btnW")], true);
    }

    /**
     * e.g. #contentContainer, svg: https://z-library.ec/book/88886268/431cbe
     * e.g. #innerWrapper, p:  https://z-library.ec/book/29358009/64db39
     */
    function z_library() {

        excelUnsupported();

        addGlobalStyle(`
        #contentContainer > .page {
            width: unset !important;
            box-shadow: none !important;
        }
        .control-cell_big {
            justify-content: unset;
        }
        #pageControls {
            margin-top: 1px;
        }
        #disguised-content div {
            background-color: rgba(0, 0, 0, 0) !important;
        }
        `);

        const observer = new MutationObserver((mutationsList) => {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => {
                        if (node.id === 'container') {
                            observer.disconnect();
                            setWordContent($("#innerWrapper"));
                            zLibraryCommon();
                        } else if (node.id === 'viewer-wrapper') {
                            observer.disconnect();
                            setWordContent($("#contentContainer"));
                            zLibraryCommon();
                        }
                    });
                }
            }
        });
        observer.observe($("#idrviewer").get(0), {childList: true, subtree: false});

        const titleObserver = new MutationObserver(function (mutationsList) {
            mutationsList.forEach(function (mutation) {
                if (mutation.type === 'childList' || mutation.type === 'characterData') {
                    titleObserver.disconnect();
                    setDisguisedTitle($("#bookTitle").text());
                    overridePageTitle();
                }
            });
        });
        titleObserver.observe($("#bookTitle").get(0), {childList: true, characterData: true, subtree: true});

        function zLibraryCommon() {
            setWordDetail($("#pageControls"));
            const {teardown} = bridgeScrollContainers('#idrviewer', '#disguised-body', {
                twoWay: false,
                patchJQuery: true,
                mirrorGlobal: false,
                syncNative: false
            });
            patchNativeScrollProxy('#idrviewer', '#disguised-body');
        }

    }

///////////////////////////// 站点结束

    // 切换原版界面
    document.addEventListener('keydown', function (event) {
        // 判断是否按下 E 键
        if (event.key === 'e' && !event.ctrlKey && !event.altKey && !event.metaKey) {
            if (config.mode === DICT.MODE.ORIGINAL) {
                applyMode(config.lastVisibleMode);
            } else {
                applyMode(DICT.MODE.ORIGINAL);

            }
        }
    });

    //如果是原始模式
    if (config.mode === DICT.MODE.ORIGINAL) {
        addGlobalStyle(`
        .nd-switch-indicator {
            position: fixed;
            top: 10px;
            right: 10px;
            display: flex;
            flex-direction: row;
            align-items: center;
            height: auto;
            padding: 2rem;
            border-radius: 1rem;
            background: rgba(255, 255, 255, 0.6);
            -webkit-backdrop-filter: blur(10px);
            backdrop-filter: blur(10px);
            color: black;
            font-size: 14px;
        }
        
        .nd-switch-key {
            border: solid 1px black;
            border-radius: 8px;
            width: 1.5rem;
            height: 1.5rem;
            display: flex;
            justify-content: center;
            align-items: center;
            margin: 0 5px;
        }
        `);
        const $indicator = $(`<div class="nd-switch-indicator">按<div class="nd-switch-key">E</div>键开启伪装</div>`);
        $indicator.appendTo(document.body);
        return;
    }

    // main
    common();
    const currentHost = window.location.host;
    const currentPathName = window.location.pathname;
    printLog('currentHost', currentHost);

    switch (currentHost) {
        case 'www.qidian.com':
            qidian();
            break;
        case 'fanqienovel.com':
            fanqie();
            break;
        case `www.biquge.net`:
            biquge_net();
            break;
        case 'www.xbiqugu.net':
        case 'www.xbiqugu.la':
            xbiqugu_net();
            break;
        case 'www.biquge.co':
            biquge_co();
            break;
        case 'www.52wx.com':
            www_52wx_com();
            break;
        case 'www.3bqg.cc':
            www_3bqg_cc();
            break;
        case 'www.bigee.cc':
            www_bigee_cc();
            break;
        case 'www.beqege.cc':
            www_beqege_cc();
            break;
        case 'www.biqukun.com':
            www_biqukun_com();
            break;
        case 'www.biquge.tw':
            www_biquge_tw();
            break;
        case 'www.wenku8.net':
            www_wenku8_net();
            break;
        case 'www.linovelib.com':
            linovelib_com();
            break;
        case 'www.bilinovel.com':
            biilinovel_com();
            break;
        case 'www.qimao.com':
            qimao_com();
            break;
        case 'www.jjwxc.net':
            jinjiang();
            break;
        case 'my.jjwxc.net':
            jinjiangBuy();
            break;
        case 'www.lightnovel.us':
            lightnovel_us();
            break;
        case 'b.faloo.com':
            faloo_com();
            break;
        case '69shuba.cx':
        case 'www.69shuba.com':
            _69shuba_cx();
            break;
        case 'www.owlook.com.cn':
        case 'owlook.com.cn':
            www_owlook_com_cn();
            break;
        case 'www.ciweimao.com':
            ciweimao_com();
            break;
        case 'www.v2ex.com':
            if (currentPathName.startsWith('/t/')) {
                v2exThread();
            } else if (currentPathName.startsWith('/go/') || currentPathName.startsWith('/recent') || currentPathName === '/') {
                v2exList();
            }
            break;
        case 'www.kelexs.com':
            www_kelexs_com();
            break;
        case 'reader.z-library.ec':
        case 'reader.z-library.sk':
            z_library();
            break;
        default:
            printLog("error", "当前站点未适配");

    }

    GM_registerMenuCommand("设置", settings);

    printLog("novel-disguise 载入完成");
})
();