Kemer 增强

美化界面和重新排版,包括移除广告和多余的横幅,修正画师名称和编辑相关的资讯保存,自动载入原始图像,菜单设置图像大小间距,快捷键触发自动滚动,解析文本中的链接并转换为可点击的链接,快速的页面切换和跳转功能,并重新定向到新分頁

// ==UserScript==
// @name         Kemer 增強
// @name:zh-TW   Kemer 增強
// @name:zh-CN   Kemer 增强
// @name:ja      Kemer 強化
// @name:en      Kemer Enhancement
// @version      0.0.49-Beta4
// @author       Canaan HS
// @description        美化介面和重新排版,包括移除廣告和多餘的橫幅,修正繪師名稱和編輯相關的資訊保存,自動載入原始圖像,菜單設置圖像大小間距,快捷鍵觸發自動滾動,解析文本中的連結並轉換為可點擊的連結,快速的頁面切換和跳轉功能,並重新定向到新分頁
// @description:zh-TW  美化介面和重新排版,包括移除廣告和多餘的橫幅,修正繪師名稱和編輯相關的資訊保存,自動載入原始圖像,菜單設置圖像大小間距,快捷鍵觸發自動滾動,解析文本中的連結並轉換為可點擊的連結,快速的頁面切換和跳轉功能,並重新定向到新分頁
// @description:zh-CN  美化界面和重新排版,包括移除广告和多余的横幅,修正画师名称和编辑相关的资讯保存,自动载入原始图像,菜单设置图像大小间距,快捷键触发自动滚动,解析文本中的链接并转换为可点击的链接,快速的页面切换和跳转功能,并重新定向到新分頁
// @description:ja     インターフェイスの美化と再配置、広告や余分なバナーの削除、イラストレーター名の修正と関連情報の保存の編集、オリジナル画像の自動読み込み、メニューでの画像のサイズと間隔の設定、ショートカットキーによる自動スクロールのトリガー、テキスト内のリンクの解析とクリック可能なリンクへの変換、高速なページ切り替えとジャンプ機能、新しいタブへのリダイレクト
// @description:en     Beautify the interface and re-layout, including removing ads and redundant banners, correcting artist names and editing related information retention, automatically loading original images, setting image size and spacing in the menu, triggering automatic scrolling with hotkeys, parsing links in the text and converting them to clickable links, fast page switching and jumping functions, and redirecting to a new tab

// @match        *://kemono.su/*
// @match        *://coomer.su/*
// @match        *://nekohouse.su/*
// @match        *://*.kemono.su/*
// @match        *://*.coomer.su/*
// @match        *://*.nekohouse.su/*

// @license      MIT
// @namespace    https://greasyfork.org/users/989635
// @icon         https://cdn-icons-png.flaticon.com/512/2566/2566449.png

// @connect      *
// @run-at       document-end
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_openInTab
// @grant        GM_addElement
// @grant        GM_deleteValue
// @grant        GM_getResourceURL
// @grant        GM_xmlhttpRequest
// @grant        GM_getResourceText
// @grant        GM_registerMenuCommand
// @grant        GM_addValueChangeListener

// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.14.0/jquery-ui.min.js
// @require      https://update.greasyfork.org/scripts/495339/1456526/ObjectSyntax_min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js

// @resource     loading https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.3/images/loading.gif
// @resource     font-awesome https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/svg-with-js.min.css
// ==/UserScript==

(async () => {
    /*! mode: 某些功能可以設置模式 (輸入數字), enable: 是否啟用該功能 (布林) !*/
    const User_Config = {
        Global: {
            BlockAds: {mode: 0, enable: true}, // 阻擋廣告
            BackToTop: {mode: 0, enable: true}, // 翻頁後回到頂部
            KeyScroll: {mode: 1, enable: true}, // 上下鍵觸發自動滾動 [mode: 1 = 動畫偵滾動, mode: 2 = 間隔滾動] (選擇對於自己較順暢的, coomer 無效他被阻止了)
            DeleteNotice: {mode: 0, enable: true}, // 刪除上方公告
            SidebarCollapse: {mode: 0, enable: true}, // 側邊攔摺疊
            FixArtist: { // 修復作者名稱
                mode: 0,
                enable: true,
                newtab: true, // 是否以新標籤開啟
                newtab_active: true, // 自動切換焦點到新標籤
                newtab_insert: true, // 新標籤插入到當前標籤的正後方
            },
            TextToLink: { // 連結的 (文本 -> 超連結)
                mode: 0,
                enable: true,
                newtab: true,
                newtab_active: false,
                newtab_insert: false,
            },
        },
        Preview: {
            CardZoom: {mode: 2, enable: true}, // 縮放預覽卡大小 [mode: 1 = 卡片放大 , 2 = 卡片放大 + 懸浮縮放]
            CardText: {mode: 2, enable: true}, // 預覽卡文字效果 [mode: 1 = 隱藏文字 , 2 = 淡化文字]
            QuickPostToggle: {mode: 0, enable: true}, // 快速切換帖子
            NewTabOpens: { // 預覽頁面的帖子都以新分頁開啟
                mode: 0,
                enable: true,
                newtab_active: false,
                newtab_insert: false,
            },
        },
        Content: {
            ExtraButton: {mode: 0, enable: true}, // 額外的下方按鈕
            LinkBeautify: {mode: 0, enable: true}, // 下載連結美化, 當出現 (browse »), 滑鼠懸浮會直接顯示內容, 並移除多餘的字串
            CommentFormat: {mode: 0, enable: true}, // 評論區重新排版
            VideoBeautify: {mode: 1, enable: true}, // 影片美化 [mode: 1 = 複製下載節點 , 2 = 移動下載節點] (有啟用 LinkBeautify, 會與原始狀態不同)
            OriginalImage: { // 自動原圖 [mode: 1 = 快速自動 , 2 = 慢速自動 , 3 = 觀察後觸發]
                mode: 1,
                enable: true,
                experiment: false, // 實驗性替換方式
            }
        }
    };
    const Url = Syn.Device.Url;
    const DLL = (() => {
        const Posts = /^(https?:\/\/)?(www\.)?.+\/posts\/?.*$/;
        const Search = /^(https?:\/\/)?(www\.)?.+\/artists\/?.*$/;
        const User = /^(https?:\/\/)?(www\.)?.+\/.+\/user\/[^\/]+(\?.*)?$/;
        const Content = /^(https?:\/\/)?(www\.)?.+\/.+\/user\/.+\/post\/.+$/;
        const Favor = /^(https?:\/\/)?(www\.)?.+\/favorites\?type=post\/?.*$/;
        const Link = /^(https?:\/\/)?(www\.)?.+\/.+\/user\/[^\/]+\/links\/?.*$/;
        const FavorArtist = /^(https?:\/\/)?(www\.)?.+\/favorites(?:\?(?!type=post).*)?$/;
        const Announcement = /^(https?:\/\/)?(www\.)?.+\/(dms|(?:.+\/user\/[^\/]+\/announcements))(\?.*)?$/;
        const Display_Lang = {
            Traditional: {},
            Simplified: {
                "📝 設置選單": "📝 设置菜单",
                "設置菜單": "设置菜单",
                "圖像設置": "图像设置",
                "讀取設定": "读取设置",
                "關閉離開": "关闭退出",
                "保存應用": "保存应用",
                "語言": "语言",
                "英文": "英文",
                "繁體": "繁体",
                "簡體": "简体",
                "日文": "日文",
                "圖片高度": "图片高度",
                "圖片寬度": "图片宽度",
                "圖片最大寬度": "图片最大宽度",
                "圖片間隔高度": "图片间隔高度"
            },
            Japan: {
                "📝 設置選單": "📝 設定メニュー",
                "設置菜單": "設定メニュー",
                "圖像設置": "画像設定",
                "讀取設定": "設定の読み込み",
                "關閉離開": "閉じて終了する",
                "保存應用": "保存して適用する",
                "語言": "言語",
                "英文": "英語",
                "繁體": "繁体字",
                "簡體": "簡体字",
                "日文": "日本語",
                "圖片高度": "画像の高さ",
                "圖片寬度": "画像の幅",
                "圖片最大寬度": "画像の最大幅",
                "圖片間隔高度": "画像の間隔の高さ"
            },
            English: {
                "📝 設置選單": "📝 Settings Menu",
                "設置菜單": "Settings Menu",
                "圖像設置": "Image Settings",
                "讀取設定": "Load Settings",
                "關閉離開": "Close and Exit",
                "保存應用": "Save and Apply",
                "語言": "Language",
                "英文": "English",
                "繁體": "Traditional Chinese",
                "簡體": "Simplified Chinese",
                "日文": "Japanese",
                "圖片高度": "Image Height",
                "圖片寬度": "Image Width",
                "圖片最大寬度": "Maximum Image Width",
                "圖片間隔高度": "Image Spacing Height"
            }
        }, Match = {
            "zh-TW": Display_Lang.Traditional,
            "zh-HK": Display_Lang.Traditional,
            "zh-MO": Display_Lang.Traditional,
            "zh-CN": Display_Lang.Simplified,
            "zh-SG": Display_Lang.Simplified,
            "en-US": Display_Lang.English,
            ja: Display_Lang.Japan
        };
        const Color = {
            kemono: "#e8a17d !important",
            coomer: "#99ddff !important",
            nekohouse: "#bb91ff !important"
        }[Syn.Device.Host.split(".")[0]];
        const SaveKey = {
            Img: "ImgStyle",
            Lang: "Language",
            Menu: "MenuPoint"
        };
        const UserSet = {
            MenuSet: () => {
                return Syn.Store("g", SaveKey.Menu) ?? {
                    Top: "10vh",
                    Left: "10vw"
                };
            },
            ImgSet: () => {
                return Syn.Store("g", SaveKey.Img) ?? {
                    Width: "auto",
                    Height: "auto",
                    Spacing: "0px",
                    MaxWidth: "100%"
                };
            }
        };
        let ImgRule, MenuRule;
        const ImportantStyle = async (element, property, value) => {
            requestAnimationFrame(() => {
                element.style.setProperty(property, value, "important");
            });
        };
        const NormalStyle = (element, property, value) => {
            requestAnimationFrame(() => {
                element.style[property] = value;
            });
        };
        const Style_Pointer = {
            Top: value => NormalStyle(MenuRule[1], "top", value),
            Left: value => NormalStyle(MenuRule[1], "left", value),
            Width: value => ImportantStyle(ImgRule[1], "width", value),
            Height: value => ImportantStyle(ImgRule[1], "height", value),
            MaxWidth: value => ImportantStyle(ImgRule[1], "max-width", value),
            Spacing: value => ImportantStyle(ImgRule[1], "margin", `${value} auto`)
        };
        const Style = {
            Global: async () => {
                Syn.AddStyle(`
                    /* 搜尋頁面的樣式 */
                    fix_tag:hover { color: ${Color}; }
                    .fancy-image__image, fix_name, fix_tag, fix_edit {
                        cursor: pointer;
                    }
                    .user-card__info {
                        display: flex;
                        flex-direction: column;
                        align-items: flex-start;
                    }
                    fix_name {
                        color: #fff;
                        font-size: 28px;
                        font-weight: 500;
                        max-width: 320px;
                        overflow: hidden;
                        padding: .25rem .1rem;
                        border-radius: .25rem;
                        white-space: nowrap;
                        text-overflow: ellipsis;
                    }
                    .edit_artist {
                        position: absolute;
                        top: 36%;
                        right: 8%;
                        color: #fff;
                        display: none;
                        font-size: 14px;
                        font-weight: 700;
                        background: #666;
                        white-space: nowrap;
                        padding: .25rem .5rem;
                        border-radius: .25rem;
                        transform: translateY(-100%);
                    }
                    .edit_textarea {
                        color: #fff;
                        display: block;
                        font-size: 30px;
                        padding: 6px 1px;
                        line-height: 5vh;
                        text-align: center;
                    }
                    .user-card:hover .edit_artist {
                        display: block;
                    }
                    .user-card:hover fix_name {
                        background-color: ${Color};
                    }
                    .edit_textarea ~ fix_name,
                    .edit_textarea ~ .edit_artist {
                        display: none !important;
                    }

                    /* 預覽頁面的樣式 */
                    fix_view {
                        display: flex;
                        flex-flow: wrap;
                        align-items: center;
                    }
                    fix_view fix_name {
                        font-size: 2rem;
                        font-weight: 700;
                        padding: .25rem 3rem;
                        border-radius: .25rem;
                        transition: background-color 0.3s ease;
                    }
                    fix_view .edit_artist {
                        top: 40%;
                        right: 5%;
                        transform: translateY(-80%);
                    }
                    fix_view:hover fix_name {
                        background-color: ${Color};
                    }
                    fix_view:hover .edit_artist {
                        display: block;
                    }

                    /* 內容頁面的樣式 */
                    fix_cont {
                        display: flex;
                        justify-content: space-around;
                    }
                    fix_cont fix_name {
                        color: ${Color};
                        font-size: 1.25em;
                        display: inline-block;
                    }
                    fix_cont .edit_artist {
                        top: 95%;
                        right: -10%;
                    }
                    fix_cont:hover fix_name {
                        background-color: #fff;
                    }
                    fix_cont:hover .edit_artist {
                        display: block;
                    }
                `, "Global-Effects", false);
            },
            Preview: async () => {
                Syn.AddStyle(`
                    .gif-overlay {
                        top: 45%;
                        left: 50%;
                        width: 60%;
                        height: 60%;
                        opacity: 0.5;
                        z-index: 9999;
                        position: absolute;
                        border-radius: 50%;
                        background-size: contain;
                        background-position: center;
                        background-repeat: no-repeat;
                        transform: translate(-50%, -50%);
                        background-image: url("${GM_getResourceURL("loading")}");
                    }
                    .card-list__items {
                        gap: 0.5em;
                        display: flex;
                        grid-gap: 0.5em;
                        position: relative;
                        align-items: var(--local-align);
                        flex-flow: var(--local-flex-flow);
                        justify-content: var(--local-justify);
                    }
                `, "Preview-Effects", false);
            },
            Postview: async () => {
                const set = UserSet.ImgSet();
                const width = Syn.Device.iW() / 2;
                Syn.AddStyle(`
                    .post__files > div,
                    .scrape__files > div {
                        position: relative;
                    }
                    .Image-style, figure img {
                        display: block;
                        width: ${set.Width} !important;
                        height: ${set.Height} !important;
                        margin: ${set.Spacing} auto !important;
                        max-width: ${set.MaxWidth} !important;
                    }
                    .Image-loading-indicator {
                        min-width: 50vW;
                        min-height: 50vh;
                        max-width: ${width}px;
                        max-height: ${width * 9 / 16}px;
                        border: 1px solid #fafafa;
                    }
                    .Image-loading-indicator-experiment {
                        border: 3px solid #00ff7e;
                    }
                    .Image-loading-indicator:hover {
                        cursor: pointer;
                    }
                    .progress-indicator {
                        top: 5px;
                        left: 5px;
                        colo: #fff;
                        font-size: 14px;
                        padding: 3px 6px;
                        position: absolute;
                        border-radius: 5px;
                        background-color: rgba(0, 0, 0, 0.3);
                    }
                `, "Image-Custom-Style", false);
                ImgRule = Syn.$$("#Image-Custom-Style")?.sheet.cssRules;
            },
            Awesome: async () => {
                Syn.AddStyle(`
                    ${GM_getResourceText("font-awesome")}
                    #next_box a {
                        cursor: pointer;
                    }
                    #next_box a:hover {
                        background-color: ${Color};
                    }
            `, "Font-awesome", false);
            },
            Menu: () => {
                const set = UserSet.MenuSet();
                Syn.AddScript(`
                    function check(value) {
                        return value.toString().length > 4 || value > 1000
                            ? 1000 : value < 0 ? "" : value;
                    }
                `, "Menu-Settings", false);
                Syn.AddStyle(`
                    .modal-background {
                        top: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;
                        display: flex;
                        z-index: 9999;
                        overflow: auto;
                        position: fixed;
                        pointer-events: none;
                    }
                    /* 模態介面 */
                    .modal-interface {
                        top: ${set.Top};
                        left: ${set.Left};
                        margin: 0;
                        display: flex;
                        overflow: auto;
                        position: fixed;
                        border-radius: 5px;
                        pointer-events: auto;
                        background-color: #2C2E3E;
                        border: 3px solid #EE2B47;
                    }
                    /* 模態內容盒 */
                    .modal-box {
                        padding: 0.5rem;
                        height: 50vh;
                        width: 32vw;
                    }
                    /* 菜單框架 */
                    .menu {
                        width: 5.5vw;
                        overflow: auto;
                        text-align: center;
                        vertical-align: top;
                        border-radius: 2px;
                        border: 2px solid #F6F6F6;
                    }
                    /* 菜單文字標題 */
                    .menu-text {
                        color: #EE2B47;
                        cursor: default;
                        padding: 0.2rem;
                        margin: 0.3rem;
                        margin-bottom: 1.5rem;
                        white-space: nowrap;
                        border-radius: 10px;
                        border: 4px solid #f05d73;
                        background-color: #1f202c;
                    }
                    /* 菜單選項按鈕 */
                    .menu-options {
                        cursor: pointer;
                        font-size: 1.4rem;
                        color: #F6F6F6;
                        font-weight: bold;
                        border-radius: 5px;
                        margin-bottom: 1.2rem;
                        border: 5px inset #EE2B47;
                        background-color: #6e7292;
                        transition: color 0.8s, background-color 0.8s;
                    }
                    .menu-options:hover {
                        color: #EE2B47;
                        background-color: #F6F6F6;
                    }
                    .menu-options:disabled {
                        color: #6e7292;
                        cursor: default;
                        background-color: #c5c5c5;
                        border: 5px inset #faa5b2;
                    }
                    /* 設置內容框架 */
                    .content {
                        height: 48vh;
                        width: 28vw;
                        overflow: auto;
                        padding: 0px 1rem;
                        border-radius: 2px;
                        vertical-align: top;
                        border-top: 2px solid #F6F6F6;
                        border-right: 2px solid #F6F6F6;
                    }
                    .narrative { color: #EE2B47; }
                    .Image-input-settings {
                        width: 8rem;
                        color: #F6F6F6;
                        text-align: center;
                        font-size: 1.5rem;
                        border-radius: 15px;
                        border: 3px inset #EE2B47;
                        background-color: #202127;
                    }
                    .Image-input-settings:disabled {
                        border: 3px inset #faa5b2;
                        background-color: #5a5a5a;
                    }
                    /* 底部按鈕框架 */
                    .button-area {
                        display: flex;
                        padding: 0.3rem;
                        border-left: none;
                        border-radius: 2px;
                        border: 2px solid #F6F6F6;
                        justify-content: space-between;
                    }
                    .button-area select {
                        color: #F6F6F6;
                        margin-right: 1.5rem;
                        border: 3px inset #EE2B47;
                        background-color: #6e7292;
                    }
                    /* 底部選項 */
                    .button-options {
                        color: #F6F6F6;
                        cursor: pointer;
                        font-size: 0.8rem;
                        font-weight: bold;
                        border-radius: 10px;
                        white-space: nowrap;
                        background-color: #6e7292;
                        border: 3px inset #EE2B47;
                        transition: color 0.5s, background-color 0.5s;
                    }
                    .button-options:hover {
                        color: #EE2B47;
                        background-color: #F6F6F6;
                    }
                    .button-space { margin: 0 0.6rem; }
                    .form-hidden {
                        width: 0;
                        height: 0;
                        opacity: 0;
                        padding: 10px;
                        overflow: hidden;
                        transition: opacity 0.8s, height 0.8s, width 0.8s;
                    }
                    .toggle-menu {
                        width: 0;
                        height: 0;
                        padding: 0;
                        margin: 0;
                    }
                    /* 整體框線 */
                    table, td {
                        margin: 0px;
                        padding: 0px;
                        overflow: auto;
                        border-spacing: 0px;
                    }
                    .modal-background p {
                        display: flex;
                        flex-wrap: nowrap;
                    }
                    option { color: #F6F6F6; }
                    ul {
                        list-style: none;
                        padding: 0px;
                        margin: 0px;
                    }
                `, "Menu-Custom-Style", false);
                MenuRule = Syn.$$("#Menu-Custom-Style")?.sheet.cssRules;
                Syn.StoreListen(Object.values(SaveKey), call => {
                    if (call.far) {
                        if (Syn.Type(call.nv) == "String") {
                            MenuTrigger();
                        } else {
                            for (const [key, value] of Object.entries(call.nv)) {
                                Style_Pointer[key](value);
                            }
                        }
                    }
                });
            }
        };
        return {
            IsContent: Content.test(Url),
            IsAnnouncement: Announcement.test(Url),
            IsSearch: Search.test(Url) || Link.test(Url) || FavorArtist.test(Url),
            IsAllPreview: Posts.test(Url) || User.test(Url) || Favor.test(Url),
            IsNeko: Syn.Device.Host.startsWith("nekohouse"),
            Language: () => {
                const Log = Syn.Store("g", SaveKey.Lang);
                const ML = Match[Log] ?? Match["en-US"];
                return {
                    Log: Log,
                    Transl: Str => ML[Str] ?? Str
                };
            },
            Rendering: ({
                content
            }) => React.createElement("div", {
                dangerouslySetInnerHTML: {
                    __html: content
                }
            }),
            ...UserSet,
            Style: Style,
            Color: Color,
            SaveKey: SaveKey,
            Style_Pointer: Style_Pointer,
            Link: Link,
            Posts: Posts,
            User: User,
            Favor: Favor,
            Search: Search,
            Content: Content,
            FavorArtist: FavorArtist,
            Announcement: Announcement
        };
    })();
    const Enhance = (() => {
        const Validate = (Bool, Num) => {
            return Bool && Syn.Type(Bool) == "Boolean" && Syn.Type(Num) == "Number" ? true : false;
        };
        const Order = {
            Global: ["SidebarCollapse", "DeleteNotice", "BlockAds", "TextToLink", "FixArtist", "BackToTop", "KeyScroll"],
            Preview: ["NewTabOpens", "QuickPostToggle", "CardZoom", "CardText"],
            Content: ["LinkBeautify", "VideoBeautify", "OriginalImage", "ExtraButton", "CommentFormat"]
        };
        const LoadFunc = {
            Global_Cache: undefined,
            Preview_Cache: undefined,
            Content_Cache: undefined,
            Global: function () {
                if (!this.Global_Cache) this.Global_Cache = Global_Function();
                return this.Global_Cache;
            },
            Preview: function () {
                if (!this.Preview_Cache) this.Preview_Cache = Preview_Function();
                return this.Preview_Cache;
            },
            Content: function () {
                if (!this.Content_Cache) this.Content_Cache = Content_Function();
                return this.Content_Cache;
            }
        };
        const Global_Initial = {
            FixArtist: {
                ...User_Config.Global.FixArtist
            },
            TextToLink: {
                ...User_Config.Global.TextToLink
            }
        };
        let Ord;
        async function Call(page, config = User_Config[page]) {
            const func = LoadFunc[page]();
            for (Ord of Order[page]) {
                const {
                    enable,
                    mode,
                    ...other
                } = config[Ord] ?? {};
                if (Validate(enable, mode)) {
                    func[Ord]?.({
                        mode: mode,
                        ...other
                    });
                }
            }
        }
        return {
            Run: async () => {
                Call("Global");
                if (DLL.IsAllPreview) Call("Preview"); else if (DLL.IsContent) {
                    DLL.Style.Postview();
                    Call("Content");
                    DLL.Style.Menu();
                    MenuTrigger();
                }
            },
            ExtraInitial: async () => {
                Call("Global", Global_Initial);
                Call("Content");
            }
        };
    })();
    Enhance.Run();
    function Global_Function() {
        const LoadFunc = {
            TextToLink_Cache: undefined,
            TextToLink_Dependent: function (Config) {
                if (!this.TextToLink_Cache) {
                    this.TextToLink_Cache = {
                        Protocol_F: /^(?!https?:\/\/)/,
                        Exclusion_F: /onfanbokkusuokibalab\.net/,
                        URL_F: /(?:https?:\/\/[^\s]+)|(?:[a-zA-Z0-9]+\.)?(?:[a-zA-Z0-9]+)\.[^\s]+\/[^\s]+/g,
                        ParseModify: async function (father, content) {
                            if (this.Exclusion_F.test(content)) return;
                            father.innerHTML = content.replace(this.URL_F, url => {
                                const decode = decodeURIComponent(url).trim();
                                return `<a href="${decode.replace(this.Protocol_F, "https://")}">${decode}</a>`;
                            });
                        },
                        Process: async function (pre) {
                            const Text = pre.textContent;
                            this.URL_F.test(Text) && this.ParseModify(pre, Text);
                        },
                        Multiprocessing: async function (root) {
                            if (DLL.IsNeko) {
                                const Text = root.textContent;
                                this.URL_F.test(Text) && this.ParseModify(root, Text);
                                return;
                            }
                            let p;
                            for (p of Syn.$$("p", {
                                all: true,
                                root: root
                            })) {
                                const Text = p.textContent;
                                this.URL_F.test(Text) && this.ParseModify(p, Text);
                            }
                            let a;
                            for (a of Syn.$$("a", {
                                all: true,
                                root: root
                            })) {
                                !a.href && this.ParseModify(a, a.textContent);
                            }
                        },
                        JumpTrigger: async root => {
                            const [Newtab, Active, Insert] = [Config.newtab ?? true, Config.newtab_active ?? false, Config.newtab_insert ?? false];
                            Syn.Listen(root, "click", event => {
                                const target = event.target.closest("a:not(.fileThumb)");
                                target && (event.preventDefault(), !Newtab ? location.assign(target.href) : GM_openInTab(target.href, {
                                    active: Active,
                                    insert: Insert
                                }));
                            }, {
                                capture: true
                            });
                        }
                    };
                }
                return this.TextToLink_Cache;
            },
            FixArtist_Cache: undefined,
            FixArtist_Dependent: function () {
                if (!this.FixArtist_Cache) {
                    const Fix_Requ = {
                        Record_Cache: undefined,
                        Fix_Cache: new Map(),
                        Get_Record: () => Syn.Storage("fix_record_v2", {
                            type: localStorage,
                            error: new Map()
                        }),
                        Save_Record: async function (save) {
                            await Syn.Storage("fix_record_v2", {
                                type: localStorage,
                                value: new Map([...this.Get_Record(), ...save])
                            });
                            this.Fix_Cache.clear();
                        },
                        Save_Work: (() => Syn.Debounce(() => Fix_Requ.Save_Record(Fix_Requ.Fix_Cache), 1e3))(),
                        Fix_Name_Support: new Set(["pixiv", "fanbox"]),
                        Fix_Tag_Support: {
                            ID: /Patreon|Fantia|Pixiv|Fanbox/gi,
                            Patreon: "https://www.patreon.com/user?u={id}",
                            Fantia: "https://fantia.jp/fanclubs/{id}/posts",
                            Pixiv: "https://www.pixiv.net/users/{id}/artworks",
                            Fanbox: "https://www.pixiv.net/fanbox/creator/{id}",
                            NAME: /Fansly|OnlyFans/gi,
                            OnlyFans: "https://onlyfans.com/{name}",
                            Fansly: "https://fansly.com/{name}/posts"
                        },
                        Fix_Request: async function (url, headers = {}) {
                            return new Promise(resolve => {
                                GM_xmlhttpRequest({
                                    method: "GET",
                                    url: url,
                                    headers: headers,
                                    onload: response => resolve(response),
                                    onerror: () => resolve(),
                                    ontimeout: () => resolve()
                                });
                            });
                        },
                        Get_Pixiv_Name: async function (id) {
                            const response = await this.Fix_Request(`https://www.pixiv.net/ajax/user/${id}?full=1&lang=ja`, {
                                referer: "https://www.pixiv.net/"
                            });
                            if (response.status === 200) {
                                const user = JSON.parse(response.responseText);
                                let user_name = user.body.name;
                                user_name = user_name.replace(/(c\d+)?([日月火水木金土]曜日?|[123123一二三]日目?)[東南西北]..?\d+\w?/i, "");
                                user_name = user_name.replace(/[@@]?(fanbox|fantia|skeb|ファンボ|リクエスト|お?仕事|新刊|単行本|同人誌)+(.*(更新|募集|公開|開設|開始|発売|販売|委託|休止|停止)+中?[!!]?$|$)/gi, "");
                                user_name = user_name.replace(/\(\)|()|「」|【】|[@@__]+$/g, "").trim();
                                return user_name;
                            } else return;
                        },
                        Fix_Url: function (url) {
                            url = url.match(/\/([^\/]+)\/([^\/]+)\/([^\/]+)$/) || url.match(/\/([^\/]+)\/([^\/]+)$/);
                            url = url.splice(1).map(url => url.replace(/\/?(www\.|\.com|\.jp|\.net|\.adult|user\?u=)/g, ""));
                            return url.length >= 3 ? [url[0], url[2]] : url;
                        },
                        Fix_Update_Ui: async function (href, id, name_onj, tag_obj, text) {
                            const edit = GM_addElement("fix_edit", {
                                id: id,
                                class: "edit_artist",
                                textContent: "Edit"
                            });
                            name_onj.parentNode.insertBefore(edit, name_onj);
                            name_onj.outerHTML = `<fix_name jump="${href}">${text.trim()}</fix_name>`;
                            const [tag_text, support_id, support_name] = [tag_obj.textContent, this.Fix_Tag_Support.ID, this.Fix_Tag_Support.NAME];
                            if (support_id.test(tag_text)) {
                                tag_obj.innerHTML = tag_text.replace(support_id, tag => {
                                    return `<fix_tag jump="${this.Fix_Tag_Support[tag].replace("{id}", id)}">${tag}</fix_tag>`;
                                });
                            } else if (support_name.test(tag_text)) {
                                tag_obj.innerHTML = tag_text.replace(support_name, tag => {
                                    return `<fix_tag jump="${this.Fix_Tag_Support[tag].replace("{name}", id)}">${tag}</fix_tag>`;
                                });
                            }
                        },
                        Fix_Trigger: async function (object) {
                            const {
                                Url,
                                TailId,
                                Website,
                                NameObject,
                                TagObject
                            } = object;
                            let Record = this.Record_Cache.get(TailId);
                            if (Record) {
                                this.Fix_Update_Ui(Url, TailId, NameObject, TagObject, Record);
                            } else {
                                if (this.Fix_Name_Support.has(Website)) {
                                    Record = await this.Get_Pixiv_Name(TailId) ?? NameObject.textContent;
                                    this.Fix_Update_Ui(Url, TailId, NameObject, TagObject, Record);
                                    this.Fix_Cache.set(TailId, Record);
                                    this.Save_Work();
                                } else {
                                    Record = NameObject.textContent;
                                    this.Fix_Update_Ui(Url, TailId, NameObject, TagObject, Record);
                                }
                            }
                        },
                        Search_Fix: async function (items) {
                            items.setAttribute("fix", true);
                            const url = items.href;
                            const img = Syn.$$("img", {
                                root: items
                            });
                            const parse = this.Fix_Url(url);
                            img.setAttribute("jump", url);
                            items.removeAttribute("href");
                            img.removeAttribute("src");
                            this.Fix_Trigger({
                                Url: url,
                                TailId: parse[1],
                                Website: parse[0],
                                NameObject: Syn.$$(".user-card__name", {
                                    root: items
                                }),
                                TagObject: Syn.$$(".user-card__service", {
                                    root: items
                                })
                            });
                        },
                        Other_Fix: async function (artist, tag = "", href = null, reTag = "<fix_view>") {
                            try {
                                const parent = artist.parentNode;
                                const url = href ?? parent.href;
                                const parse = this.Fix_Url(url);
                                await this.Fix_Trigger({
                                    Url: url,
                                    TailId: parse[1],
                                    Website: parse[0],
                                    NameObject: artist,
                                    TagObject: tag
                                });
                                $(parent).replaceWith(function () {
                                    return $(reTag, {
                                        html: $(this).html()
                                    });
                                });
                            } catch { }
                        },
                        Dynamic_Fix: async function (Listen, Operat, Config = null) {
                            let observer, options;
                            Syn.Observer(Listen, () => {
                                this.Record_Cache = this.Get_Record();
                                const wait = setInterval(() => {
                                    const operat = typeof Operat === "string" ? Syn.$$(Operat) : Operat;
                                    if (operat) {
                                        clearInterval(wait);
                                        switch (Config) {
                                            case 1:
                                                this.Other_Fix(operat);
                                                setTimeout(() => {
                                                    observer.disconnect();
                                                    observer.observe(Listen.children[0], options);
                                                }, 300);
                                                break;

                                            default:
                                                for (const items of Syn.$$("a", {
                                                    all: true,
                                                    root: operat
                                                })) {
                                                    !items.getAttribute("fix") && this.Search_Fix(items);
                                                }
                                        }
                                    }
                                });
                            }, {
                                subtree: false
                            }, back => {
                                observer = back.ob;
                                options = back.op;
                            });
                        }
                    };
                    this.FixArtist_Cache = Fix_Requ;
                }
                return this.FixArtist_Cache;
            }
        };
        return {
            SidebarCollapse: async Config => {
                if (Syn.Device.Type() === "Mobile") return;
                Syn.AddStyle(`
                    .global-sidebar {
                        opacity: 0;
                        height: 100%;
                        width: 10rem;
                        display: flex;
                        position: fixed;
                        padding: 0.5em 0;
                        transition: 0.8s;
                        background: #282a2e;
                        flex-direction: column;
                        transform: translateX(-9rem);
                    }
                    .global-sidebar:hover {opacity: 1; transform: translateX(0rem);}
                    .content-wrapper.shifted {transition: 0.7s; margin-left: 0rem;}
                    .global-sidebar:hover + .content-wrapper.shifted {margin-left: 10rem;}
                `, "Collapse_Effects", false);
            },
            DeleteNotice: async Config => {
                Syn.$$("body > div.content-wrapper.shifted > a")?.remove();
            },
            BlockAds: async Config => {
                Syn.AddStyle(`
                    .ipprtcnt, .root--ujvuu, .ad-container {display: none !important}
                `, "Ad-blocking-style", false);
                Syn.AddScript(`
                    const XMLRequest = XMLHttpRequest.prototype.open;
                    const Ad_observer = new MutationObserver(() => {
                        XMLHttpRequest.prototype.open = function(method, Url) {
                            if (Url.endsWith(".m3u8") || Url === "https://s.magsrv.com/v1/Syn.php") {return}
                            XMLRequest.apply(this, arguments);
                        };
                        document.querySelector("div.ex-over-btn")?.click();
                        document.querySelector(".root--ujvuu button")?.click();
                        document.querySelectorAll(".ad-container").forEach(ad => {ad.remove()});
                    });
                    Ad_observer.observe(document.head, {childList: true, subtree: true});
                `, "Ad-blocking-script", false);
            },
            TextToLink: async Config => {
                if (!DLL.IsContent && !DLL.IsAnnouncement) return;
                const Func = LoadFunc.TextToLink_Dependent(Config);
                if (DLL.IsContent) {
                    Syn.WaitElem(".post__body, .scrape__body", body => {
                        Func.JumpTrigger(body);
                        const [article, content] = [Syn.$$("article", {
                            root: body
                        }), Syn.$$(".post__content, .scrape__content", {
                            root: body
                        })];
                        if (article) {
                            let span;
                            for (span of Syn.$$("span.choice-text", {
                                all: true,
                                root: article
                            })) {
                                Func.ParseModify(span, span.textContent);
                            }
                        } else if (content) {
                            const pre = Syn.$$("pre", {
                                root: content
                            });
                            pre ? Func.Process(pre) : Func.Multiprocessing(content);
                        }
                    }, {
                        throttle: 600
                    });
                } else if (DLL.IsAnnouncement) {
                    Syn.WaitElem(".card-list__items pre", content => {
                        Func.JumpTrigger(Syn.$$(".card-list__items"));
                        let pre;
                        for (pre of content) {
                            pre.childNodes.length > 1 ? Func.Multiprocessing(pre) : Func.Process(pre);
                        }
                    }, {
                        raf: true,
                        all: true
                    });
                }
            },
            FixArtist: async Config => {
                DLL.Style.Global();
                const Func = LoadFunc.FixArtist_Dependent();
                const [Device, Newtab, Active, Insert] = [Syn.Device.Type(), Config.newtab ?? true, Config.newtab_active ?? false, Config.newtab_insert ?? false];
                Syn.AddListener(document.body, "click", event => {
                    const target = event.target;
                    if (target.matches("fix_edit")) {
                        const display = target.nextElementSibling;
                        const text = GM_addElement("textarea", {
                            class: "edit_textarea",
                            style: `height: ${display.scrollHeight + 10}px;`
                        });
                        const original_name = display.textContent;
                        text.value = original_name.trim();
                        display.parentNode.insertBefore(text, target);
                        text.scrollTop = 0;
                        setTimeout(() => {
                            text.focus();
                            setTimeout(() => {
                                Syn.Listen(text, "blur", () => {
                                    const change_name = text.value.trim();
                                    if (change_name != original_name) {
                                        display.textContent = change_name;
                                        Func.Save_Record(new Map([[target.id, change_name]]));
                                    }
                                    text.remove();
                                }, {
                                    once: true,
                                    passive: true
                                });
                            }, 50);
                        }, 300);
                    } else if (target.matches("fix_name") || target.matches("fix_tag") || target.matches("img")) {
                        const jump = target.getAttribute("jump");
                        if (!target.parentNode.matches("fix_cont") && jump) {
                            !Newtab || DLL.IsSearch && Device == "Mobile" ? location.assign(jump) : GM_openInTab(jump, {
                                active: Active,
                                insert: Insert
                            });
                        } else if (jump) {
                            location.assign(jump);
                        }
                    }
                }, {
                    capture: true,
                    passive: true,
                    mark: "FixArtist"
                });
                Func.Record_Cache = Func.Get_Record();
                if (DLL.IsSearch) {
                    const card_items = Syn.$$(".card-list__items");
                    if (DLL.Link.test(Url)) {
                        const artist = Syn.$$("span[itemprop='name']");
                        artist && Func.Other_Fix(artist);
                        for (const items of Syn.$$("a", {
                            all: true,
                            root: card_items
                        })) {
                            Func.Search_Fix(items);
                        }
                        Url.endsWith("new") && Func.Dynamic_Fix(card_items, card_items);
                    } else {
                        Func.Dynamic_Fix(card_items, card_items);
                        GM_addElement(card_items, "fix-trigger", {
                            style: "display: none;"
                        });
                    }
                } else if (DLL.IsContent) {
                    const [artist, title] = [Syn.$$(".post__user-name, .scrape__user-name"), Syn.$$("h1 span:nth-child(2)")];
                    Func.Other_Fix(artist, title, artist.href, "<fix_cont>");
                } else {
                    const artist = Syn.$$("span[itemprop='name']");
                    if (artist) {
                        Func.Other_Fix(artist);
                        if (User_Config.Preview.QuickPostToggle.enable) {
                            setTimeout(() => {
                                Func.Dynamic_Fix(Syn.$$("section"), "span[itemprop='name']", 1);
                            }, 300);
                        }
                    }
                }
            },
            BackToTop: async Config => {
                Syn.AddListener(document.body, "pointerup", event => {
                    event.target.closest("#paginator-bottom") && Syn.$$("#paginator-top").scrollIntoView();
                }, {
                    capture: true,
                    passive: true,
                    mark: "BackToTop"
                });
            },
            KeyScroll: async Config => {
                if (Syn.Device.Type() === "Mobile") return;
                const Scroll_Requ = {
                    Scroll_Pixels: 2,
                    Scroll_Interval: 800
                };
                const UP_ScrollSpeed = Scroll_Requ.Scroll_Pixels * -1;
                let Scroll, Up_scroll = false, Down_scroll = false;
                const [TopDetected, BottomDetected] = [Syn.Throttle(() => {
                    Up_scroll = Syn.Device.sY() == 0 ? false : true;
                }, 600), Syn.Throttle(() => {
                    Down_scroll = Syn.Device.sY() + Syn.Device.iH() >= document.documentElement.scrollHeight ? false : true;
                }, 600)];
                switch (Config.mode) {
                    case 2:
                        Scroll = Move => {
                            const Interval = setInterval(() => {
                                if (!Up_scroll && !Down_scroll) {
                                    clearInterval(Interval);
                                }
                                if (Up_scroll && Move < 0) {
                                    window.scrollBy(0, Move);
                                    TopDetected();
                                } else if (Down_scroll && Move > 0) {
                                    window.scrollBy(0, Move);
                                    BottomDetected();
                                }
                            }, Scroll_Requ.Scroll_Interval);
                        };

                    default:
                        Scroll = Move => {
                            if (Up_scroll && Move < 0) {
                                window.scrollBy(0, Move);
                                TopDetected();
                                requestAnimationFrame(() => Scroll(Move));
                            } else if (Down_scroll && Move > 0) {
                                window.scrollBy(0, Move);
                                BottomDetected();
                                requestAnimationFrame(() => Scroll(Move));
                            }
                        };
                }
                Syn.Listen(window, "keydown", Syn.Throttle(event => {
                    const key = event.key;
                    if (key == "ArrowUp") {
                        event.stopImmediatePropagation();
                        event.preventDefault();
                        if (Up_scroll) {
                            Up_scroll = false;
                        } else if (!Up_scroll || Down_scroll) {
                            Down_scroll = false;
                            Up_scroll = true;
                            Scroll(UP_ScrollSpeed);
                        }
                    } else if (key == "ArrowDown") {
                        event.stopImmediatePropagation();
                        event.preventDefault();
                        if (Down_scroll) {
                            Down_scroll = false;
                        } else if (Up_scroll || !Down_scroll) {
                            Up_scroll = false;
                            Down_scroll = true;
                            Scroll(Scroll_Requ.Scroll_Pixels);
                        }
                    }
                }, 100), {
                    capture: true
                });
            }
        };
    }
    function Preview_Function() {
        return {
            NewTabOpens: async Config => {
                const [Newtab, Active, Insert] = [Config.newtab ?? true, Config.newtab_active ?? false, Config.newtab_insert ?? false];
                Syn.AddListener(document.body, "click", event => {
                    const target = event.target.closest("article a");
                    target && (event.preventDefault(), !Newtab ? location.assign(target.href) : GM_openInTab(target.href, {
                        active: Active,
                        insert: Insert
                    }));
                }, {
                    capture: true,
                    mark: "NewTabOpens"
                });
            },
            QuickPostToggle: async Config => {
                DLL.Style.Preview();
                Syn.AddListener(document.body, "click", event => {
                    const target = event.target.closest("menu a");
                    target && (event.preventDefault(), GetNextPage(target.href));
                }, {
                    capture: true,
                    mark: "QuickPostToggle"
                });
                async function GetNextPage(link) {
                    const old_section = Syn.$$("section");
                    const items = Syn.$$(".card-list__items");
                    requestAnimationFrame(() => {
                        GM_addElement(items, "img", {
                            class: "gif-overlay"
                        });
                    });
                    GM_xmlhttpRequest({
                        method: "GET",
                        url: link,
                        nocache: false,
                        onload: response => {
                            const Section = Syn.$$("section", {
                                root: response.responseXML
                            });
                            ReactDOM.render(React.createElement(DLL.Rendering, {
                                content: Section.innerHTML
                            }), old_section);
                            history.pushState(null, null, link);
                        },
                        onerror: error => {
                            GetNextPage(link);
                        }
                    });
                }
            },
            CardZoom: async Config => {
                switch (Config.mode) {
                    case 2:
                        Syn.AddStyle(`
                            .post-card a:hover {
                                overflow: auto;
                                z-index: 99999;
                                background: #000;
                                border: 1px solid #fff6;
                                transform: scale(1.6, 1.5);
                            }
                            .post-card a::-webkit-scrollbar {
                                width: 0;
                                height: 0;
                            }
                            .post-card a:hover .post-card__image-container {
                                position: relative;
                            }
                        `, "CardZoom_Effects_2", false);

                    default:
                        Syn.AddStyle(`
                            * { --card-size: 13vw; }
                            .post-card { margin: .3vw; }
                            .post-card a img { border-radius: 8px; }
                            .post-card a {
                                border-radius: 8px;
                                border: 3px solid #fff6;
                                transition: transform 0.4s;
                            }
                        `, "CardZoom_Effects", false);
                }
            },
            CardText: async Config => {
                if (Syn.Device.Type() === "Mobile") return;
                switch (Config.mode) {
                    case 2:
                        Syn.AddStyle(`
                            .post-card__header, .post-card__footer {
                                opacity: 0.4;
                                transition: opacity 0.3s;
                            }
                            a:hover .post-card__header,
                            a:hover .post-card__footer {
                                opacity: 1;
                            }
                        `, "CardText_Effects_2", false);
                        break;

                    default:
                        Syn.AddStyle(`
                            .post-card__header {
                                opacity: 0;
                                z-index: 1;
                                padding: 5px;
                                pointer-events: none;
                                transform: translateY(-6vh);
                            }
                            .post-card__footer {
                                opacity: 0;
                                z-index: 1;
                                padding: 5px;
                                pointer-events: none;
                                transform: translateY(6vh);
                            }
                            a:hover .post-card__header,
                            a:hover .post-card__footer {
                                opacity: 1;
                                pointer-events: auto;
                                transform: translateY(0vh);
                                transition: transform 0.4s, opacity 0.6s;
                            }
                        `, "CardText_Effects", false);
                }
            }
        };
    }
    function Content_Function() {
        const LoadFunc = {
            LinkBeautify_Cache: undefined,
            LinkBeautify_Dependent: function () {
                if (!this.LinkBeautify_Cache) {
                    this.LinkBeautify_Cache = async function ShowBrowse(Browse) {
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: Browse.href,
                            onload: response => {
                                const Main = Syn.$$("main", {
                                    root: response.responseXML
                                });
                                const View = GM_addElement("View", {
                                    class: "View"
                                });
                                const Buffer = document.createDocumentFragment();
                                for (const br of Syn.$$("br", {
                                    all: true,
                                    root: Main
                                })) {
                                    Buffer.append(document.createTextNode(br.previousSibling.textContent.trim()), br);
                                }
                                View.appendChild(Buffer);
                                Browse.appendChild(View);
                            },
                            onerror: error => {
                                ShowBrowse(Browse);
                            }
                        });
                    };
                }
                return this.LinkBeautify_Cache;
            },
            VideoBeautify_Cache: undefined,
            VideoBeautify_Dependent: function () {
                if (!this.VideoBeautify_Cache) {
                    this.VideoBeautify_Cache = function VideoRendering({
                        stream
                    }) {
                        return React.createElement("summary", {
                            className: "video-title"
                        }, React.createElement("video", {
                            key: "video",
                            controls: true,
                            preload: "auto",
                            "data-setup": JSON.stringify({}),
                            className: "post-video"
                        }, React.createElement("source", {
                            key: "source",
                            src: stream.src,
                            type: stream.type
                        })));
                    };
                }
                return this.VideoBeautify_Cache;
            },
            ExtraButton_Cache: undefined,
            ExtraButton_Dependent: function () {
                if (!this.ExtraButton_Cache) {
                    this.ExtraButton_Cache = async function GetNextPage(url, old_main) {
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: url,
                            nocache: false,
                            onload: response => {
                                const XML = response.responseXML;
                                const Main = Syn.$$("main", {
                                    root: XML
                                });
                                ReactDOM.render(React.createElement(DLL.Rendering, {
                                    content: Main.innerHTML
                                }), old_main);
                                const Title = Syn.$$("title", {
                                    root: XML
                                })?.textContent;
                                history.pushState(null, null, url);
                                Title && (document.title = Title);
                                setTimeout(() => {
                                    Enhance.ExtraInitial();
                                    Syn.WaitElem(".post__content, .scrape__content", post => {
                                        Syn.$$("p", {
                                            all: true,
                                            root: post
                                        }).forEach(p => {
                                            p.childNodes.forEach(node => {
                                                node.nodeName == "BR" && node.parentNode.remove();
                                            });
                                        });
                                        Syn.$$("a", {
                                            all: true,
                                            root: post
                                        }).forEach(a => {
                                            /\.(jpg|jpeg|png|gif)$/i.test(a.href) && a.remove();
                                        });
                                    }, {
                                        throttle: 300
                                    });
                                    Syn.$$(".post__title, .scrape__title").scrollIntoView();
                                }, 300);
                            },
                            onerror: error => {
                                GetNextPage(url, old_main);
                            }
                        });
                    };
                }
                return this.ExtraButton_Cache;
            }
        };
        return {
            LinkBeautify: async function (Config) {
                Syn.AddStyle(`
                    .View {
                        top: -10px;
                        padding: 10%;
                        display: none;
                        overflow: auto;
                        color: #f2f2f2;
                        font-size: 14px;
                        font-weight: 600;
                        position: absolute;
                        white-space: nowrap;
                        border-radius: .5rem;
                        left: calc(100% + 10px);
                        border: 1px solid #737373;
                        background-color: #3b3e44;
                    }
                    a:hover .View { display: block }
                `, "Link_Effects", false);
                Syn.WaitElem(".post__attachment-link, .scrape__attachment-link", post => {
                    const ShowBrowse = LoadFunc.LinkBeautify_Dependent();
                    for (const link of post) {
                        link.setAttribute("download", "");
                        link.href = decodeURIComponent(link.href);
                        link.textContent = link.textContent.replace("Download", "").trim();
                        const Browse = link.nextElementSibling;
                        if (!Browse) continue;
                        Browse.style.position = "relative";
                        ShowBrowse(Browse);
                    }
                }, {
                    all: true,
                    throttle: 600
                });
            },
            VideoBeautify: async function (Config) {
                Syn.AddStyle(`
                    .video-title {margin-top: 0.5rem;}
                    .post-video {height: 50%; width: 60%;}
                `, "Video_Effects", false);
                Syn.WaitElem("ul[style*='text-align: center;list-style-type: none;'] li:not([id])", parents => {
                    Syn.WaitElem(".post__attachment-link, .scrape__attachment-link", post => {
                        const VideoRendering = LoadFunc.VideoBeautify_Dependent();
                        let li;
                        for (li of parents) {
                            let [node, title, stream] = [undefined, Syn.$$("summary", {
                                root: li
                            }), Syn.$$("source", {
                                root: li
                            })];
                            if (!title || !stream) continue;
                            if (title.previousElementSibling) continue;
                            let link;
                            for (link of post) {
                                if (link.textContent.includes(title.textContent)) {
                                    switch (Config.mode) {
                                        case 2:
                                            link.parentNode.remove();

                                        default:
                                            node = link.cloneNode(true);
                                    }
                                }
                            }
                            ReactDOM.render(React.createElement(VideoRendering, {
                                stream: stream
                            }), li);
                            li.insertBefore(node, Syn.$$("summary", {
                                root: li
                            }));
                        }
                    }, {
                        all: true,
                        throttle: 300
                    });
                }, {
                    all: true,
                    throttle: 600
                });
            },
            OriginalImage: async function (Config) {
                Syn.WaitElem(".post__thumbnail, .scrape__thumbnail", thumbnail => {
                    const LinkObj = DLL.IsNeko ? "div" : "a";
                    const HrefParse = element => {
                        const Uri = element.href || element.getAttribute("href");
                        return Uri.startsWith("http") ? Uri : `${Syn.Device.Orig}${Uri}`;
                    };
                    const Origina_Requ = {
                        Reload: async (Img, Retry) => {
                            if (Retry > 0) {
                                setTimeout(() => {
                                    const src = Img.src;
                                    Img.src = "";
                                    Object.assign(Img, {
                                        src: src,
                                        alt: "Loading Failed"
                                    });
                                    Img.onload = function () {
                                        Img.classList.remove("Image-loading-indicator");
                                    };
                                    Img.onerror = function () {
                                        Origina_Requ.Reload(Img, Retry - 1);
                                    };
                                }, 1e3);
                            }
                        },
                        FailedClick: async () => {
                            Syn.Listen(Syn.$$(".post__files, .scrape__files"), "click", event => {
                                const target = event.target.matches(".Image-link img");
                                if (target && target.alt == "Loading Failed") {
                                    const src = img.src;
                                    img.src = "";
                                    img.src = src;
                                }
                            }, {
                                capture: true,
                                passive: true
                            });
                        },
                        ImgRendering: ({
                            ID,
                            Ourl = null,
                            Nurl
                        }) => {
                            return React.createElement(Ourl ? "rc" : "div", {
                                id: ID,
                                src: Ourl,
                                className: "Image-link"
                            }, React.createElement("img", {
                                key: "img",
                                src: Nurl,
                                className: "Image-loading-indicator Image-style",
                                onLoad: function () {
                                    Syn.$$(`#${ID} img`).classList.remove("Image-loading-indicator");
                                },
                                onError: function () {
                                    Origina_Requ.Reload(Syn.$$(`#${ID} img`), 10);
                                }
                            }));
                        },
                        Request: async function (Container, Url, Result) {
                            const progressLabel = document.createElement("div");
                            progressLabel.className = "progress-indicator";
                            progressLabel.textContent = "0%";
                            Container.appendChild(progressLabel);
                            GM_xmlhttpRequest({
                                url: Url,
                                method: "GET",
                                responseType: "blob",
                                onprogress: progress => {
                                    const done = (progress.done / progress.total * 100).toFixed(1);
                                    progressLabel.textContent = `${done}%`;
                                },
                                onload: response => {
                                    const blob = response.response;
                                    blob instanceof Blob && blob.size > 0 ? Result(URL.createObjectURL(blob)) : Result(Url);
                                },
                                onerror: () => Result(Url)
                            });
                        },
                        FastAuto: async function () {
                            this.FailedClick();
                            thumbnail.forEach((object, index) => {
                                setTimeout(() => {
                                    object.removeAttribute("class");
                                    const a = Syn.$$(LinkObj, {
                                        root: object
                                    });
                                    const hrefP = HrefParse(a);
                                    if (Config.experiment) {
                                        Syn.$$("img", {
                                            root: a
                                        }).classList.add("Image-loading-indicator-experiment");
                                        this.Request(object, hrefP, href => {
                                            ReactDOM.render(React.createElement(this.ImgRendering, {
                                                ID: `IMG-${index}`,
                                                Ourl: hrefP,
                                                Nurl: href
                                            }), object);
                                        });
                                    } else {
                                        ReactDOM.render(React.createElement(this.ImgRendering, {
                                            ID: `IMG-${index}`,
                                            Nurl: hrefP
                                        }), object);
                                    }
                                }, index * 300);
                            });
                        },
                        SlowAuto: async function (index) {
                            if (index == thumbnail.length) return;
                            const object = thumbnail[index];
                            object.removeAttribute("class");
                            const a = Syn.$$(LinkObj, {
                                root: object
                            });
                            const hrefP = HrefParse(a);
                            const img = Syn.$$("img", {
                                root: a
                            });
                            const replace_core = (Nurl, Ourl = null) => {
                                const container = document.createElement(Ourl ? "rc" : "div");
                                Ourl && container.setAttribute("src", Ourl);
                                Object.assign(container, {
                                    id: `IMG-${index}`,
                                    className: "Image-link"
                                });
                                const img = document.createElement("img");
                                Object.assign(img, {
                                    src: Nurl,
                                    className: "Image-loading-indicator Image-style"
                                });
                                img.onload = function () {
                                    img.classList.remove("Image-loading-indicator");
                                    Origina_Requ.SlowAuto(++index);
                                };
                                object.innerHTML = "";
                                container.appendChild(img);
                                object.appendChild(container);
                            };
                            if (Config.experiment) {
                                img.classList.add("Image-loading-indicator-experiment");
                                this.Request(object, hrefP, href => replace_core(href, hrefP));
                            } else {
                                replace_core(hrefP);
                            }
                        },
                        ObserveTrigger: function () {
                            this.FailedClick();
                            return new IntersectionObserver(observed => {
                                observed.forEach(entry => {
                                    if (entry.isIntersecting) {
                                        const object = entry.target;
                                        observer.unobserve(object);
                                        object.removeAttribute("class");
                                        const a = Syn.$$(LinkObj, {
                                            root: object
                                        });
                                        const hrefP = HrefParse(a);
                                        if (Config.experiment) {
                                            Syn.$$("img", {
                                                root: a
                                            }).classList.add("Image-loading-indicator-experiment");
                                            this.Request(object, hrefP, href => {
                                                ReactDOM.render(React.createElement(this.ImgRendering, {
                                                    ID: object.alt,
                                                    Ourl: hrefP,
                                                    Nurl: href
                                                }), object);
                                            });
                                        } else {
                                            ReactDOM.render(React.createElement(this.ImgRendering, {
                                                ID: object.alt,
                                                Nurl: hrefP
                                            }), object);
                                        }
                                    }
                                });
                            }, {
                                threshold: .3
                            });
                        }
                    };
                    let observer;
                    switch (Config.mode) {
                        case 2:
                            Origina_Requ.SlowAuto(0);
                            break;

                        case 3:
                            observer = Origina_Requ.ObserveTrigger();
                            thumbnail.forEach((object, index) => {
                                object.alt = `IMG-${index}`;
                                observer.observe(object);
                            });
                            break;

                        default:
                            if (document.visibilityState === "hidden") {
                                Syn.Listen(document, "visibilitychange", () => {
                                    document.visibilityState === "visible" && Origina_Requ.FastAuto();
                                }, {
                                    once: true
                                });
                            } else Origina_Requ.FastAuto();
                    }
                }, {
                    all: true,
                    throttle: 600
                });
            },
            ExtraButton: async function (Config) {
                DLL.Style.Awesome();
                const GetNextPage = LoadFunc.ExtraButton_Dependent();
                Syn.WaitElem("h2.site-section__subheading", comments => {
                    const [Prev, Next, Svg, Span, Buffer] = [Syn.$$(".post__nav-link.prev, .scrape__nav-link.prev"), Syn.$$(".post__nav-link.next, .scrape__nav-link.next"), document.createElement("svg"), document.createElement("span"), document.createDocumentFragment()];
                    Svg.innerHTML = `
                        <svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512" style="margin-left: 10px;cursor: pointer;">
                            <style>svg{fill: ${DLL.Color}}</style>
                            <path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM135.1 217.4l107.1-99.9c3.8-3.5 8.7-5.5 13.8-5.5s10.1 2 13.8 5.5l107.1 99.9c4.5 4.2 7.1 10.1 7.1 16.3c0 12.3-10 22.3-22.3 22.3H304v96c0 17.7-14.3 32-32 32H240c-17.7 0-32-14.3-32-32V256H150.3C138 256 128 246 128 233.7c0-6.2 2.6-12.1 7.1-16.3z"></path>
                        </svg>
                    `;
                    Span.id = "next_box";
                    Span.style = "float: right";
                    const Next_btn = Next.cloneNode(true);
                    Next_btn.setAttribute("jump", Next_btn.href);
                    Next_btn.removeAttribute("href");
                    Syn.Listen(Svg, "click", () => {
                        Syn.$$("header").scrollIntoView();
                    }, {
                        capture: true,
                        passive: true
                    });
                    Syn.Listen(Next_btn, "click", () => {
                        GetNextPage(Next_btn.getAttribute("jump"), Syn.$$("main"));
                    }, {
                        capture: true,
                        once: true
                    });
                    Span.appendChild(Next_btn);
                    Buffer.append(Svg, Span);
                    comments.appendChild(Buffer);
                }, {
                    throttle: 600
                });
            },
            CommentFormat: async function (Config) {
                Syn.AddStyle(`
                    .post__comments,
                    .scrape__comments {
                        display: flex;
                        flex-wrap: wrap;
                    }
                    .post__comments > *:last-child,
                    .scrape__comments > *:last-child {
                        margin-bottom: 0.5rem;
                    }
                    .comment {
                        margin: 0.5rem;
                        max-width: 25rem;
                        border-radius: 10px;
                        flex-basis: calc(35%);
                        word-break: break-all;
                        border: 0.125em solid var(--colour1-secondary);
                    }
                `, "Comment_Effects", false);
            }
        };
    }
    async function $on(element, type, listener) {
        $(element).on(type, listener);
    }
    async function MenuTrigger(callback = null) {
        const {
            Log,
            Transl
        } = DLL.Language();
        callback && callback({
            Log: Log,
            Transl: Transl
        });
        Syn.Menu({
            [Transl("📝 設置選單")]: {
                func: () => Create_Menu(Log, Transl)
            }
        });
    }
    function Create_Menu(Log, Transl) {
        if (Syn.$$(".modal-background")) return;
        const set = DLL.ImgSet();
        const img_data = [set.Height, set.Width, set.MaxWidth, set.Spacing];
        let analyze, parent, child, img_set, img_input, img_select, set_value, save_cache = {};
        const shadow = document.createElement("div");
        const shadowRoot = shadow.attachShadow({
            mode: "open"
        });
        const script = GM_addElement("script", {
            id: "Img-Script",
            textContent: Syn.$$("#Menu-Settings").textContent
        });
        shadowRoot.appendChild(script);
        const style = GM_addElement("style", {
            id: "Menu-Style",
            textContent: Syn.$$("#Menu-Custom-Style").textContent
        });
        shadowRoot.appendChild(style);
        const UnitOptions = `
            <select class="Image-input-settings" style="margin-left: 1rem;">
                <option value="px" selected>px</option>
                <option value="%">%</option>
                <option value="rem">rem</option>
                <option value="vh">vh</option>
                <option value="vw">vw</option>
                <option value="auto">auto</option>
            </select>
        `;
        shadowRoot.innerHTML += `
            <div class="modal-background">
                <div class="modal-interface">
                    <table class="modal-box">
                        <tr>
                            <td class="menu">
                                <h2 class="menu-text">${Transl("設置菜單")}</h2>
                                <ul>
                                    <li>
                                        <a class="toggle-menu" href="#image-settings-show">
                                            <button class="menu-options" id="image-settings">${Transl("圖像設置")}</button>
                                        </a>
                                    <li>
                                    <li>
                                        <a class="toggle-menu" href="#">
                                            <button class="menu-options" disabled>null</button>
                                        </a>
                                    <li>
                                </ul>
                            </td>
                            <td>
                                <table>
                                    <tr>
                                        <td class="content" id="set-content">
                                            <div id="image-settings-show" class="form-hidden">
                                                <div>
                                                    <h2 class="narrative">${Transl("圖片高度")}:</h2>
                                                    <p><input type="number" id="Height" class="Image-input-settings" oninput="value = check(value)"></p>
                                                </div>
                                                <div>
                                                    <h2 class="narrative">${Transl("圖片寬度")}:</h2>
                                                    <p><input type="number" id="Width" class="Image-input-settings" oninput="value = check(value)"></p>
                                                </div>
                                                <div>
                                                    <h2 class="narrative">${Transl("圖片最大寬度")}:</h2>
                                                    <p><input type="number" id="MaxWidth" class="Image-input-settings" oninput="value = check(value)"></p>
                                                </div>
                                                <div>
                                                    <h2 class="narrative">${Transl("圖片間隔高度")}:</h2>
                                                    <p><input type="number" id="Spacing" class="Image-input-settings" oninput="value = check(value)"></p>
                                                </div>
                                            </div>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td class="button-area">
                                            <select id="language">
                                                <option value="" disabled selected>${Transl("語言")}</option>
                                                <option value="en-US">${Transl("英文")}</option>
                                                <option value="zh-TW">${Transl("繁體")}</option>
                                                <option value="zh-CN">${Transl("簡體")}</option>
                                                <option value="ja">${Transl("日文")}</option>
                                            </select>
                                            <button id="readsettings" class="button-options" disabled>${Transl("讀取設定")}</button>
                                            <span class="button-space"></span>
                                            <button id="closure" class="button-options">${Transl("關閉離開")}</button>
                                            <span class="button-space"></span>
                                            <button id="application" class="button-options">${Transl("保存應用")}</button>
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>
                    </table>
                </div>
            </div>
        `;
        $(document.body).append(shadow);
        const $language = $(shadowRoot).find("#language");
        const $readset = $(shadowRoot).find("#readsettings");
        const $interface = $(shadowRoot).find(".modal-interface");
        const $background = $(shadowRoot).find(".modal-background");
        const $imageSet = $(shadowRoot).find("#image-settings-show");
        $language.val(Log ?? "en-US");
        $interface.draggable({
            cursor: "grabbing"
        });
        const Menu_Requ = {
            Menu_Close: () => {
                $background?.off();
                shadow.remove();
            },
            Menu_Save: () => {
                const top = $interface.css("top");
                const left = $interface.css("left");
                Syn.Store("s", DLL.SaveKey.Menu, {
                    Top: top,
                    Left: left
                });
                DLL.Style_Pointer.Top(top);
                DLL.Style_Pointer.Left(left);
            },
            Img_Save: () => {
                img_set = $imageSet.find("p");
                img_data.forEach((read, index) => {
                    img_input = img_set.eq(index).find("input");
                    img_select = img_set.eq(index).find("select");
                    if (img_select.val() == "auto") {
                        set_value = "auto";
                    } else if (img_input.val() == "") {
                        set_value = read;
                    } else {
                        set_value = `${img_input.val()}${img_select.val()}`;
                    }
                    save_cache[img_input.attr("id")] = set_value;
                });
                Syn.Store("s", DLL.SaveKey.Img, save_cache);
            },
            ImageSettings: async () => {
                $on($(shadowRoot).find(".Image-input-settings"), "input change", function (event) {
                    event.stopPropagation();
                    const target = $(this), value = target.val(), id = target.attr("id");
                    parent = target.closest("div");
                    if (isNaN(value)) {
                        child = parent.find("input");
                        if (value === "auto") {
                            child.prop("disabled", true);
                            DLL.Style_Pointer[child.attr("id")](value);
                        } else {
                            child.prop("disabled", false);
                            DLL.Style_Pointer[child.attr("id")](`${child.val()}${value}`);
                        }
                    } else {
                        child = parent.find("select");
                        DLL.Style_Pointer[id](`${value}${child.val()}`);
                    }
                });
            }
        };
        $on($language, "input change", function (event) {
            event.stopPropagation();
            $language.off("input change");
            const value = $(this).val();
            Syn.Store("s", DLL.SaveKey.Lang, value);
            Menu_Requ.Menu_Save();
            Menu_Requ.Menu_Close();
            MenuTrigger(Updata => {
                Create_Menu(Updata.Log, Updata.Transl);
            });
        });
        $on($interface, "click", function (event) {
            const id = $(event.target).attr("id");
            if (id == "image-settings") {
                img_set = $imageSet;
                if (img_set.css("opacity") === "0") {
                    img_set.find("p").each(function () {
                        $(this).append(UnitOptions);
                    });
                    img_set.css({
                        height: "auto",
                        width: "auto",
                        opacity: 1
                    });
                    $readset.prop("disabled", false);
                    Menu_Requ.ImageSettings();
                }
            } else if (id == "readsettings") {
                img_set = $imageSet.find("p");
                img_data.forEach((read, index) => {
                    img_input = img_set.eq(index).find("input");
                    img_select = img_set.eq(index).find("select");
                    if (read == "auto") {
                        img_input.prop("disabled", true);
                        img_select.val(read);
                    } else {
                        analyze = read.match(/^(\d+)(\D+)$/);
                        img_input.val(analyze[1]);
                        img_select.val(analyze[2]);
                    }
                });
            } else if (id == "application") {
                Menu_Requ.Img_Save();
                Menu_Requ.Menu_Save();
                Menu_Requ.Menu_Close();
            } else if (id == "closure") {
                Menu_Requ.Menu_Close();
            }
        });
    }
})();