Greasy Fork is available in English.
Аутентичная кнопка перехода между сайтами lib-семейства
// ==UserScript==
// @name Lib Family Switcher
// @namespace http://tampermonkey.net/
// @version 2.2.0
// @description Аутентичная кнопка перехода между сайтами lib-семейства
// @author MayBeGod
// @match *://mangalib.me/*
// @match *://ranobelib.me/*
// @match *://hentailib.me/*
// @match *://v2.shlib.life/*
// @match *://v5.animelib.org/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const style = document.createElement('style');
style.innerHTML = `
.lib-switcher-container {
display: inline-flex !important;
align-items: center !important;
position: relative !important;
margin-left: 8px !important;
cursor: pointer !important;
z-index: 1000 !important;
vertical-align: middle;
}
.lib-switcher-icon {
width: 16px;
height: 16px;
color: #777;
transition: color 0.2s, transform 0.2s;
pointer-events: none;
}
.lib-switcher-container:hover .lib-switcher-icon {
color: #ff8e35;
}
.lib-switcher-container.active .lib-switcher-icon {
transform: rotate(180deg);
}
.lib-dropdown-menu {
display: none;
position: absolute;
top: calc(100% + 10px);
left: 0;
background: #232323;
border-radius: 8px;
padding: 8px 0;
min-width: 200px;
z-index: 9999999;
box-shadow: 0 10px 30px rgba(0,0,0,0.7);
border: 1px solid #333;
}
.lib-dropdown-menu.show {
display: block;
}
.lib-dropdown-item {
display: flex !important;
align-items: center !important;
padding: 12px 20px !important;
color: #eee !important;
text-decoration: none !important;
font-size: 14px !important;
font-family: sans-serif !important;
transition: background 0.15s;
}
.lib-dropdown-item:hover {
background: #303030 !important;
}
.lib-corner-icon {
width: 20px;
height: 20px;
margin-right: 15px;
flex-shrink: 0;
transition: opacity 0.2s;
}
.lib-dropdown-item:hover .lib-corner-icon {
opacity: 0.8;
}
.lib-dropdown-separator {
height: 1px;
background: #333;
margin: 4px 0;
}
`;
document.head.appendChild(style);
function makeIcon(rectColor, letterColor, letter) {
return `<svg class="lib-corner-icon" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0 H20 V20 H18 V2 Z M0 0 V20 H2 V2 Z" fill="${rectColor}"/>
<text x="50%" y="55%" dominant-baseline="middle" text-anchor="middle"
font-size="12" font-family="Arial, sans-serif" font-weight="bold" fill="${letterColor}">${letter}</text>
</svg>`;
}
// Основные сайты (порядок = порядок в меню)
const SITES = [
{
id: 'manga',
name: 'MangaLIB',
url: 'https://mangalib.me',
test: h => h === 'mangalib.me',
icon: makeIcon('#4caf50', '#fff', 'M'),
old: { name: 'MangaLIB Старая', url: 'https://old.mangalib.me/', icon: makeIcon('#ff9800', '#fff', 'M') }
},
{
id: 'slash',
name: 'SlashLIB',
url: 'https://v2.shlib.life/',
test: h => h.includes('shlib.life'),
icon: makeIcon('#e91e63', '#fff', 's')
},
{
id: 'ranobe',
name: 'RanobeLIB',
url: 'https://ranobelib.me',
test: h => h.includes('ranobelib.me'),
icon: makeIcon('#2196f3', '#fff', 'R')
},
{
id: 'hentai',
name: 'HentaiLIB',
url: 'https://hentailib.me',
test: h => h.includes('hentailib.me'),
icon: makeIcon('#f44336', '#fff', 'H')
},
{
id: 'anime',
name: 'AnimeLIB',
url: 'https://v5.animelib.org/',
test: h => h.includes('animelib.org') || (h.includes('animelib.me') && !h.startsWith('old.')),
icon: makeIcon('#9c27b0', '#fff', 'A'),
old: { name: 'AnimeLIB Старая', url: 'https://old.animelib.org/old', icon: makeIcon('#7b1fa2', '#fff', 'A') }
},
];
function getCurrentSite() {
const h = location.hostname;
return SITES.find(s => s.test(h)) || null;
}
// Расширенный список селекторов для поиска логотипа на разных сайтах
const LOGO_SELECTORS = [
'a[href="/ru"]',
'a[href="/"]',
'.header-logo',
'.header__logo',
'[class*="logo"] a',
'[class*="Logo"] a',
'header [class*="logo"]',
'header [class*="Logo"]',
'a.os_ag.lo_lq',
'header a[href="/ru"]',
'header a[href="/"]',
'nav a[href="/"]',
'nav a[href="/ru"]',
];
function findLogoLink() {
for (const sel of LOGO_SELECTORS) {
const el = document.querySelector(sel);
if (el) return el;
}
return null;
}
function buildMenuHTML(currentSite) {
const mainItems = SITES
.filter(s => s.id !== currentSite?.id)
.map(s => `<a href="${s.url}" class="lib-dropdown-item">${s.icon} ${s.name}</a>`)
.join('');
const oldItem = currentSite?.old
? `<div class="lib-dropdown-separator"></div>
<a href="${currentSite.old.url}" class="lib-dropdown-item">${currentSite.old.icon} ${currentSite.old.name}</a>`
: '';
return mainItems + oldItem;
}
function createSwitcher() {
if (document.getElementById('lib-family-switcher')) return;
const logoLink = findLogoLink();
if (!logoLink) return;
const currentSite = getCurrentSite();
const container = document.createElement('div');
container.id = 'lib-family-switcher';
container.className = 'lib-switcher-container';
container.innerHTML = `
<svg class="lib-switcher-icon" aria-hidden="true" focusable="false" role="img"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path fill="currentColor" d="M384 480c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0zM224 352c-6.7 0-13-2.8-17.6-7.7l-104-112c-6.5-7-8.2-17.2-4.4-25.9s12.5-14.4 22-14.4l208 0c9.5 0 18.2 5.7 22 14.4s2.1 18.9-4.4 25.9l-104 112c-4.5 4.9-10.9 7.7-17.6 7.7z"/>
</svg>
<div class="lib-dropdown-menu" id="switcher-menu">
${buildMenuHTML(currentSite)}
</div>
`;
container.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
const menu = document.getElementById('switcher-menu');
const isActive = menu.classList.toggle('show');
container.classList.toggle('active', isActive);
});
container.querySelectorAll('.lib-dropdown-item').forEach(item => {
item.addEventListener('click', e => e.stopPropagation());
});
document.addEventListener('click', () => {
const menu = document.getElementById('switcher-menu');
if (menu) {
menu.classList.remove('show');
container.classList.remove('active');
}
});
logoLink.style.display = 'inline-flex';
logoLink.style.alignItems = 'center';
logoLink.appendChild(container);
}
const observer = new MutationObserver(createSwitcher);
observer.observe(document.body, { childList: true, subtree: true });
createSwitcher();
})();