MutationObserverを使用して低負荷でテキストを消去し、1行を維持する
// ==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();
})();