您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Converts sidebar sections to rows.
// ==UserScript== // @name Convert Comick Sidebar to Rows // @namespace https://github.com/GooglyBlox // @version 1.0 // @description Converts sidebar sections to rows. // @author GooglyBlox // @match https://comick.io/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; function injectGlobalCss() { const styleId = 'comick-sidebar-fix'; if (document.getElementById(styleId)) return; const css = ` body > #__next > div > div.float-right { display: none !important; } main[id="main"].md\\:w-8\\/12 { width: 100% !important; max-width: none !important; float: none !important; } main[id="main"] > div { width: 100% !important; max-width: none !important; } `; const style = document.createElement('style'); style.id = styleId; style.textContent = css; document.head.appendChild(style); } async function convertSidebarContent() { const mainElement = document.querySelector('main[id="main"]'); const sidebarDiv = document.querySelector('div.float-right.w-4\\/12.xl\\:w-3\\/12'); if (!mainElement || !sidebarDiv) return; const animeSection = findAnimeSectionContainer(); if (!animeSection) return; const seeMoreButtons = Array.from(sidebarDiv.querySelectorAll('div')).filter(div => { const textElement = div.querySelector('.flex-grow.font-semibold'); return textElement && textElement.textContent.trim() === 'See More' && !div.closest('a[href]'); }); seeMoreButtons.forEach(button => button.click()); await new Promise(resolve => setTimeout(resolve, 500)); let convertedSections = []; const sidebarSections = sidebarDiv.querySelectorAll('#ranking'); for (let sectionIndex = 0; sectionIndex < sidebarSections.length; sectionIndex++) { const section = sidebarSections[sectionIndex]; const header = section.querySelector('.flex.items-center.justify-between'); const content = section.querySelector('.space-y-2.pb-5.mt-4'); if (!header || !content) continue; const titleElements = header.querySelectorAll('h2'); if (titleElements.length > 1) { const recentlyAddedItems = content.querySelectorAll('a[href^="/comic/"]:not(.hidden)'); if (recentlyAddedItems.length > 0) { convertedSections.push(createRowSection('Recently Added', recentlyAddedItems, convertedSections.length, false, '/search')); } const completeSeriesButton = Array.from(titleElements).find(el => el.textContent.trim() === 'Complete Series'); if (completeSeriesButton) { completeSeriesButton.click(); await new Promise(resolve => setTimeout(resolve, 300)); const completeSeriesItems = content.querySelectorAll('a[href^="/comic/"]:not(.hidden)'); if (completeSeriesItems.length > 0) { convertedSections.push(createRowSection('Complete Series', completeSeriesItems, convertedSections.length, false, '/search?status=2')); } const recentlyAddedButton = Array.from(titleElements).find(el => el.textContent.trim() === 'Recently Added'); if (recentlyAddedButton) recentlyAddedButton.click(); } } } if (convertedSections.length === 0) return; let insertAfter = animeSection; convertedSections.forEach(section => { insertAfter.insertAdjacentElement('afterend', section); insertAfter = section; }); sidebarDiv.remove(); } function findAnimeSectionContainer() { const animeHeaders = Array.from(document.querySelectorAll('h2')).filter(h2 => h2.textContent.trim() === 'Adapted to Anime'); if (animeHeaders.length === 0) return null; let container = animeHeaders[0]; while (container && container.parentElement) { if (container.classList.contains('mt-3') || container.parentElement === document.querySelector('main[id="main"]')) break; container = container.parentElement; } return container; } function createRowSection(title, items, sectionIndex, includeRankings = false, viewAllUrl = '/search') { const section = document.createElement('div'); section.className = 'mt-8'; section.setAttribute('data-section-title', title); const header = document.createElement('div'); header.className = 'flex justify-between items-center flex-nowrap mb-4 md:mb-6'; const headerLeft = document.createElement('div'); headerLeft.className = 'flex items-center'; const titleElement = document.createElement('h2'); const gradients = [{ light: 'rgb(209, 138, 255)', dark: 'rgb(128, 45, 217)' }, { light: 'rgb(146, 195, 255)', dark: 'rgb(56, 125, 220)' }, { light: 'rgb(74, 227, 134)', dark: 'rgb(14, 157, 64)' }, { light: 'rgb(253, 186, 100)', dark: 'rgb(221, 116, 30)' }]; const gradient = gradients[sectionIndex % gradients.length]; titleElement.className = 'md:font-bold line-clamp-1'; titleElement.textContent = title; titleElement.style.background = `linear-gradient(to right, ${gradient.light}, ${gradient.dark})`; titleElement.style.webkitBackgroundClip = 'text'; titleElement.style.backgroundClip = 'text'; titleElement.style.color = 'transparent'; headerLeft.appendChild(titleElement); const headerRight = document.createElement('div'); headerRight.className = 'flex items-center'; const viewAllLink = document.createElement('a'); viewAllLink.href = viewAllUrl; viewAllLink.className = 'hover:cursor-pointer rounded-full text-xs mr-2 text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200 hover:underline'; viewAllLink.textContent = 'View all'; headerRight.appendChild(viewAllLink); headerRight.appendChild(createMenuContainer(section, title)); header.appendChild(headerLeft); header.appendChild(headerRight); section.appendChild(header); section.appendChild(createSectionContent(items, includeRankings)); return section; } function createMenuContainer(section, title) { const menuContainer = document.createElement('div'); menuContainer.className = 'hover:cursor-pointer rounded-full'; const menuButton = document.createElement('div'); menuButton.className = 'relative inline-block text-left top-0.5'; const button = document.createElement('button'); button.type = 'button'; button.setAttribute('aria-haspopup', 'menu'); button.setAttribute('aria-expanded', 'false'); button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" class="w-5 h-5 md:w-6 md:h-6 lg:w-7 lg:h-7 text-gray-500 hover:dark:text-gray-400 hover:text-gray-600 z-10 stroke-2"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 12.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 18.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z"></path></svg>`; const menu = document.createElement('div'); menu.className = 'absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-white dark:bg-gray-750 dark:text-gray-200 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none shadow-gray-500 dark:shadow-gray-900 hidden'; menu.innerHTML = `<div role="none"><span class="block px-4 py-2 text-sm cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-600" role="menuitem">Minimize</span></div>`; let menuOpen = false; button.addEventListener('click', (e) => { e.stopPropagation(); menuOpen = !menuOpen; menu.classList.toggle('hidden', !menuOpen); button.setAttribute('aria-expanded', menuOpen.toString()); }); document.addEventListener('click', () => { if (menuOpen) { menu.classList.add('hidden'); button.setAttribute('aria-expanded', 'false'); menuOpen = false; } }); menu.querySelector('span[role="menuitem"]').addEventListener('click', () => { minimizeSection(section, title); menu.classList.add('hidden'); button.setAttribute('aria-expanded', 'false'); menuOpen = false; }); menuButton.appendChild(button); menuButton.appendChild(menu); menuContainer.appendChild(menuButton); return menuContainer; } function createSectionContent(items, includeRankings) { const navigationWrapper = document.createElement('div'); navigationWrapper.className = 'navigation-wrapper relative'; const scrollContainer = document.createElement('div'); scrollContainer.className = 'flex overflow-x-scroll hide-scroll-bar h-32 md:h-36 lg:h-48 xl:h-56'; const innerContainer = document.createElement('div'); innerContainer.style.width = `${Math.min(items.length * 184, 18400)}px`; innerContainer.style.height = '100%'; innerContainer.style.position = 'relative'; Array.from(items).slice(0, 100).forEach((item, itemIndex) => { innerContainer.appendChild(createHorizontalCard(item, itemIndex, includeRankings)); }); scrollContainer.appendChild(innerContainer); const leftArrow = document.createElement('div'); leftArrow.className = 'absolute top-0 left-0 z-10 bg-opacity-80 h-full w-8 lg:w-10 xl:w-14 rounded arrow arrow--left select-none dark:hover:bg-gray-500/30 hover:bg-gray-100/30 bg-opacity-60 cursor-pointer hidden'; leftArrow.innerHTML = `<div class="top-1/2 -translate-y-1/2 absolute left-1 dark:bg-gray-600 bg-white dark:hover:bg-gray-500 hover:bg-gray-100 rounded-full p-2 md:p-3 flex items-center opacity-80"><svg class=" w-3 h-3 lg:w-4 lg:h-4 fill-current text-gray-500 dark:text-gray-200 bg-opacity-60" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M16.67 0l2.83 2.829-9.339 9.175 9.339 9.167-2.83 2.829-12.17-11.996z"></path></svg></div>`; const rightArrow = document.createElement('div'); rightArrow.className = 'absolute top-0 right-0 z-10 bg-opacity-80 h-full w-8 lg:w-10 xl:w-14 rounded arrow select-none arrow--right dark:hover:bg-gray-500/30 hover:bg-gray-100/30 bg-opacity-60 cursor-pointer'; rightArrow.innerHTML = `<div class="top-1/2 -translate-y-1/2 absolute right-1 dark:bg-gray-600 bg-white dark:hover:bg-gray-500 hover:bg-gray-100 rounded-full flex items-center opacity-80 p-2 md:p-3"><svg class="w-3 h-3 lg:w-4 lg:h-4 fill-current text-gray-500 dark:text-gray-200 hover:brightness-125 bg-opacity-60" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M5 3l3.057-3 11.943 12-11.943 12-3.057-3 9-9z"></path></svg></div>`; leftArrow.addEventListener('click', () => scrollContainer.scrollBy({ left: -920, behavior: 'smooth' })); rightArrow.addEventListener('click', () => scrollContainer.scrollBy({ left: 920, behavior: 'smooth' })); scrollContainer.addEventListener('scroll', () => { const { scrollLeft, scrollWidth, clientWidth } = scrollContainer; leftArrow.classList.toggle('hidden', scrollLeft <= 0); const atEnd = scrollLeft + clientWidth >= scrollWidth - 10; rightArrow.style.opacity = atEnd ? '0.5' : '1'; rightArrow.style.pointerEvents = atEnd ? 'none' : 'auto'; }); navigationWrapper.appendChild(scrollContainer); navigationWrapper.appendChild(leftArrow); navigationWrapper.appendChild(rightArrow); return navigationWrapper; } function minimizeSection(section, title) { const content = section.querySelector('.navigation-wrapper'); const header = section.querySelector('.flex.justify-between'); if (!content || !header) return; content.style.display = 'none'; header.style.display = 'none'; const minimizedView = document.createElement('div'); minimizedView.className = 'relative mb-4'; minimizedView.innerHTML = `<div class="absolute inset-0 flex items-center" aria-hidden="true"><div class="w-full border-t border-gray-300 dark:border-gray-600"></div></div><div class="relative flex justify-center"><button type="button" class="inline-flex items-center gap-x-1.5 rounded-full bg-white px-3 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:text-gray-300 dark:ring-gray-600 dark:bg-gray-700"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="-ml-1 -mr-0.5 h-5 w-5 text-gray-400"><path d="M10.75 4.75a.75.75 0 0 0-1.5 0v4.5h-4.5a.75.75 0 0 0 0 1.5h4.5v4.5a.75.75 0 0 0 1.5 0v-4.5h4.5a.75.75 0 0 0 0-1.5h-4.5v-4.5Z"></path></svg>${title}</button></div>`; minimizedView.querySelector('button').addEventListener('click', () => { content.style.display = ''; header.style.display = ''; minimizedView.remove(); }); section.appendChild(minimizedView); } function createHorizontalCard(originalItem, index, includeRankings = false) { const card = document.createElement('div'); card.className = 'w-24 h-32 md:w-28 md:h-36 lg:w-36 lg:h-48 xl:w-44 xl:h-56 overflow-hidden'; card.style.cssText = `position: absolute; top: 0px; left: 0px; height: 100%; width: 184px; transform: translateX(${index * 184}px);`; const link = document.createElement('a'); link.href = originalItem.href; link.title = originalItem.title || ''; link.style.overflow = 'visible'; const cardInner = document.createElement('div'); cardInner.className = 'relative w-24 h-32 md:w-28 md:h-36 lg:w-36 lg:h-48 xl:w-44 xl:h-56 overflow-hidden'; const originalImg = originalItem.querySelector('img'); if (originalImg) { const img = originalImg.cloneNode(true); img.className = 'select-none rounded object-cover object-top w-24 md:w-28 lg:w-36 xl:w-44 h-32 md:h-36 lg:h-48 xl:h-56 active:brightness-75'; cardInner.appendChild(img); } const titleText = originalItem.querySelector('.text-ellipsis')?.textContent?.trim() || link.title; if (titleText) { const overlay = document.createElement('div'); overlay.className = 'h-12 bottom-0 absolute overlay font-semibold text-gray-200 w-full text-xs md:text-xs lg:text-sm px-1 md:px-2 pt-5 text-center truncate'; overlay.textContent = titleText; cardInner.appendChild(overlay); } if (includeRankings) { const ranking = document.createElement('div'); const rankingColors = ['bg-red-500/90', 'bg-orange-500/90', 'bg-yellow-500/90']; ranking.className = `absolute top-0 left-0 flex items-center justify-center text-xl md:text-2xl font-semibold z-10 text-white w-6 h-6 md:w-8 md:h-8 rounded-tl rounded-br ${index < 3 ? rankingColors[index] : 'bg-gray-500/90'}`; ranking.textContent = (index + 1).toString(); cardInner.appendChild(ranking); } link.appendChild(cardInner); card.appendChild(link); return card; } let isRunning = false; async function runConversion() { if (isRunning || document.querySelector('[data-section-title]')) { return; } isRunning = true; try { const sidebar = document.querySelector('div.float-right.w-4\\/12.xl\\:w-3\\/12'); if (sidebar) { await convertSidebarContent(); } } finally { isRunning = false; } } const handlePageChange = () => { injectGlobalCss(); runConversion(); }; const observer = new MutationObserver(handlePageChange); handlePageChange(); observer.observe(document.body, { childList: true, subtree: true }); })();