Hitomi Reader Optimized Slim Navbar

MutationObserverを使用して低負荷でテキストを消去し、1行を維持する

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Hitomi Reader Optimized Slim Navbar
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  MutationObserverを使用して低負荷でテキストを消去し、1行を維持する
// @author       Your Name
// @match        https://hitomi.la/reader/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 1. スタイル注入(メディアクエリ上書きと1行固定)
    const style = document.createElement('style');
    style.innerHTML = `
        /* 画面幅に関わらず強制表示 */
        @media (max-width: 979px) {
            .nav-collapse, .nav-collapse.collapse {
                display: flex !important;
                height: 24px !important;
                overflow: visible !important;
                visibility: visible !important;
            }
            .navbar .brand { display: block !important; }
        }

        /* ナビバー全体の高さを24pxに固定 */
        .navbar, .navbar-inner, .navbar-inner .container {
            min-height: 24px !important;
            height: 24px !important;
            display: flex !important;
            flex-direction: row !important;
            flex-wrap: nowrap !important;
            align-items: center !important;
            padding: 0 5px !important;
            margin: 0 !important;
        }

        .navbar .brand {
            padding: 0 8px 0 0 !important;
            margin: 0 !important;
            font-size: 12px !important;
            line-height: 24px !important;
            float: none !important;
        }

        .nav-collapse { display: flex !important; float: none !important; }
        .navbar-nav { display: flex !important; flex-direction: row !important; margin: 0 !important; }
        .navbar-nav > li { float: none !important; }

        /* テキストを見えなくする(CSS側でも念押し) */
        .navbar-nav > li > a {
            font-size: 0 !important;
            padding: 0 4px !important;
            height: 24px !important;
            display: flex !important;
            align-items: center !important;
            text-indent: -9999px; /* テキストを画面外へ */
        }
        .navbar-nav > li > a i {
            font-size: 12px !important;
            text-indent: 0; /* アイコンは戻す */
            display: inline-block !important;
        }

        .navbar-search.pull-right {
            margin-left: 5px !important;
            display: flex !important;
            align-items: center !important;
            float: none !important;
        }

        .input-medium, select#single-page-select {
            height: 19px !important;
            line-height: 1 !important;
            padding: 0 1px !important;
            font-size: 10px !important;
            width: auto !important;
            min-width: 45px !important;
            background-color: #222 !important;
            color: #ddd !important;
            border: 1px solid #444 !important;
        }

        .btn-navbar { display: none !important; }
    `;
    document.head.appendChild(style);

    // 2. テキストノードを消去する関数
    const cleanTextNodes = () => {
        const links = document.querySelectorAll('.navbar-nav > li > a');
        links.forEach(link => {
            for (let node of link.childNodes) {
                if (node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== "") {
                    node.textContent = "";
                }
            }
        });
    };

    // 3. MutationObserverによる低負荷な監視
    // サイトのJSがHTMLを書き換えたときだけ cleanTextNodes を実行する
    const observer = new MutationObserver(() => {
        observer.disconnect(); // ループ防止のため一時停止
        cleanTextNodes();
        observer.observe(document.querySelector('.navbar-inner'), { childList: true, subtree: true });
    });

    // 監視開始
    const target = document.querySelector('.navbar-inner');
    if (target) {
        observer.observe(target, { childList: true, subtree: true });
    }

    // 初回実行
    cleanTextNodes();
})();