包子漫畫閱讀輔助,瀑布流閱讀連續載入圖片,在新分頁打開漫畫鏈接(自用)。
// ==UserScript== // @name 包子漫畫閱讀輔助 // @name:en Baozi Manga Read Helpr // @name:zh-CN 包子漫画阅读辅助 // @name:zh-TW 包子漫畫閱讀輔助 // @version 2.5.10 // @description 包子漫畫閱讀輔助,瀑布流閱讀連續載入圖片,在新分頁打開漫畫鏈接(自用)。 // @description:en read infinite scroll,manga link open in newtab // @description:zh-CN 包子漫画阅读辅助,瀑布流阅读连续载入图片,在新分页打开漫画链接(自用)。 // @description:zh-TW 包子漫畫閱讀輔助,瀑布流閱讀連續載入圖片,在新分頁打開漫畫鏈接(自用)。 // @author tony0809 // @match *://cn.baozimh.com/* // @match *://cn.webmota.com/* // @match *://tw.baozimh.com/* // @match *://tw.webmota.com/* // @match *://www.baozimh.com/* // @match *://www.webmota.com/* // @match *://cn.kukuc.co/* // @match *://tw.kukuc.co/* // @match *://www.kukuc.co/* // @match *://tw.czmanga.com/* // @match *://cn.czmanga.com/* // @match *://www.czmanga.com/* // @match *://tw.dzmanga.com/* // @match *://cn.dzmanga.com/* // @match *://www.dzmanga.com/* // @match *://tw.dociy.net/* // @match *://cn.dociy.net/* // @match *://www.dociy.net/* // @match *://www.twmanga.com/* // @match *://tw.twmanga.com/* // @match *://cn.twmanga.com/* // @match *://www.tbmanga.com/* // @match *://tw.tbmanga.com/* // @match *://cn.tbmanga.com/* // @match *://www.hcmanga.com/* // @match *://tw.hcmanga.com/* // @match *://cn.hcmanga.com/* // @icon https://www.baozimh.com/favicon.ico // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js // @license MIT // @namespace https://greasyfork.org/users/20361 // ==/UserScript== (() => { 'use strict'; const options = { //true 開啟,false 關閉 oint: true, //在新分頁打開漫畫鏈接。 aH: true, //載入下一話時添加瀏覽器歷史紀錄 aO: true, //目錄頁自動展開全部章節。 pln: true, //1頁1線程逐張預讀的圖片,可減少等待加載圖片的時間,如果滾動、滑動的閱讀速度大於預讀速度還是需要待圖片載入。 topBtn: false, //添加返回頂部按鈕 remove: [true, 4] //!!!不能小於2!!!閱讀載入超過n話時刪除前面話數的圖片。 }, ge = (selector, doc) => (doc || document).querySelector(selector), gae = (selector, doc) => (doc || document).querySelectorAll(selector), gx = (xpath, doc) => (doc || document).evaluate(xpath, (doc || document), null, XPathR###lt.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue, lp = location.pathname, home = /^\/$/.test(lp), classify = /^\/classify/.test(lp), list = /^\/list\/new/.test(lp), search = /^\/search\?/.test(lp), comic = /^\/comic\/[^.]+$/.test(lp), read = /^\/comic\/chapter\/[^.]+\.html$/.test(lp), loading_bak = 'data:image/png;base64,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', openInNewTab = () => gae('.comics-card a:not([target=_blank]),.bookshelf-items a:not(.remove-img):not([target=_blank])').forEach(a => { a.setAttribute('target', '_blank'); }), addGoBack = () => { let goback = document.createElement('div'); goback.className = 'goback'; goback.setAttribute('title', '返回頂部'); goback.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: "smooth" }); }); document.body.appendChild(goback); }, removeAd = () => { let loop = setInterval(() => { let ad = ge('#interstitial_fade'); if (ad) { clearInterval(loop); ad.remove(); } }, 100); setTimeout(() => { if (loop) clearInterval(loop); }, 1e4); gae('.mobadsq').forEach(e => { e.remove(); }); }, addHistory = (title, url) => { history.pushState(null, title, url); document.title = title; }, showElement = () => { let end = gx("//div[@class='next_chapter']/span[text()='这是本作品最后一话了' or text()='這是本作品最後一話了']"); if (end) { ge('.next_chapter+.l-content').style.display = 'block'; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { observer.unobserve(entry.target); let e = entry.target; setTimeout(() => { let noImg = e.querySelector('div.i-amphtml-svc'); if (noImg) { noImg.remove(); let img = new Image(); img.setAttribute('decoding', 'async'); img.setAttribute('alt', e.getAttribute('alt')); img.src = e.getAttribute('src'); img.className = 'i-amphtml-svc i-amphtml-loading-container i-amphtml-fill-content'; e.appendChild(img); } }, 200); } }); }); gae('.l-box a>amp-img').forEach(amp => { observer.observe(amp); }); } }, addLoad = () => { let cl = document.createElement('div'); cl.className = 'chapterLoading'; let li = new Image(); li.className = 'loadingImg'; li.src = '/_nuxt/img/loading.12fdcc4.gif'; li.style.width = '50px'; cl.appendChild(li); let lt = document.createElement('div'); lt.className = 'loadingText'; lt.innerText = 'Loading...'; cl.appendChild(lt); ge('.comic-contain').appendChild(cl); }, removeLoad = () => { ge('.chapterLoading').remove(); }, addTitle = title => { let t = document.createElement('div'); t.className = 'chapterTitle'; t.innerText = title; let load = ge('.chapterLoading'); load.parentNode.insertBefore(t, load); }, parseHTML = str => { var doc = null; try { doc = new DOMParser().parseFromString(str, 'text/html'); } catch (e) {} if (!doc) { doc = document.implementation.createHTMLDocument(''); doc.documentElement.innerHTML = str; } return doc; }, getNextLink = () => { let nextlink = null; let next = ge('#next-chapter'); if (next) { nextlink = next.href; //可能會遇到當前域名和下一頁鏈接的域名不同,導致發生跨域請求出錯的情況,需替換為當前域名。 const nh = next.host, lh = location.host; if (nh !== lh) { nextlink = nextlink.replace(nh, lh); } } return nextlink; }, picPreload = async (imgsArray, index, str) => { const loadImg = src => { return new Promise(resolve => { let num = src.match(/(\d+)\.[a-z]{3,5}$/i)[1]; let temp = new Image(); temp.src = src; temp.onload = () => { resolve(`${(str || '')}[Pic(${num})][Preload OK]\n${src}`); temp = null; }; temp.onerror = (e) => { resolve(`${(str || '')}[Pic(${num})][Preload ERROR]\n${src}`); setTimeout(() => { console.log(`Preload重新載入圖片:\n${src}\n`, loadImg(src)); }, 500); temp = null; }; }); }; for (let i = index; i < imgsArray.length; i++) { let msg = await loadImg(imgsArray[i].getAttribute('src')); console.log(msg); msg = null; } }, preloadNext = () => { let url = getNextLink(); if (url !== null) { fetch(url).then(res => res.text()).then(res => { var doc = null; doc = parseHTML(res); let imgs = gae('.comic-contain amp-img', doc); let title = ge('span.title', doc).innerText; let firstImgSrcNum = imgs[0].getAttribute('src').match(/(\d+)\.[a-z]{3,5}$/i)[1]; const num = (n) => Math.round(n / 50 + 1); picPreload(imgs, 0, `[${title} part${num(firstImgSrcNum)}]`); }); } }, fetchData = url => { fetch(url).then(res => res.text()).then(res => { let doc = parseHTML(res); insertData(doc, url); }).catch(error => { console.error(error); ge('.loadingImg').style.display = 'none'; ge('.loadingText').innerText = '連線出錯,請返回頂部重新載入。'; }); }, imagesObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { observer.unobserve(entry.target); let realSrc = entry.target.dataset.src, nE = entry.target.nextElementSibling; if (realSrc) { entry.target.src = realSrc; entry.target.onerror = (error) => { error.target.src = loading_bak; setTimeout(() => { console.log(`Observer重新載入圖片:\n${realSrc}`); error.target.src = realSrc; console.log(error.target); }, 500); }; } if (nE && nE.tagName == 'IMG' && nE.dataset.src) { nE.src = nE.dataset.src; } } }); }), nextObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { observer.unobserve(entry.target); let url = getNextLink(); if (url !== null) { console.log(`觸發載入下一頁\n${url}`); addLoad(); fetchData(url); } } }); }), insertData = (doc, url) => { let imgs = gae('.comic-contain amp-img', doc); let F = new DocumentFragment(); let n = 0; if (ge('.comic-contain>img')) { let currentLastImgSrc = [...gae('.comic-contain>img')].pop().src; let nextFirstImgSrc = imgs[0].dataset.src ? imgs[0].dataset.src : imgs[0].getAttribute('src'); //當目前最後一張圖片檔名是50的倍數和下一頁第一張圖片檔名尾數是7且尾數不是1時,則不插入下一頁的前4張圖,讓條漫整體圖片按正確順序銜接。 if (/\/(50|100|150|200|250|300)\.[a-z]{3,5}$/i.test(currentLastImgSrc) && /\/(\d+)?7\.[a-z]{3,5}$/i.test(nextFirstImgSrc) && !/\/(\d+)?1\.[a-z]{3,5}$/i.test(nextFirstImgSrc)) { n = 4; } } for (let i = n; i < imgs.length; i++) { let img = new Image(); img.className = 'comic-contain__item'; img.src = loading_bak; img.dataset.src = imgs[i].dataset.src ? imgs[i].dataset.src : imgs[i].getAttribute('src'); imagesObserver.observe(img); F.appendChild(img); } let load = ge('.chapterLoading'); if (load) { ['.comic-chapter>.next_chapter', '.bottom-bar', 'span.title'].forEach(e => { ge(e).outerHTML = ge(e, doc).outerHTML; //替換元素 }); showElement(); let title = ge('span.title', doc).innerText.replace(/\(\d\/\d+\)/, ""); if (!/\/\d+_\d+_\d+\.html$/.test(url)) { //是下一話才添加標題分隔條,下一頁則不添加。 let docTitle = doc.title; if (options.aH) { addHistory(docTitle, url); } addTitle(title); } if (options.remove[0] && options.remove[1] > 1) { removeOldChapter(); } setTimeout(() => { load.parentNode.insertBefore(F, load); removeLoad(); if (options.pln) { preloadNext(); } addNextObserver(); }, 300); } else { showElement(); let E = ge('.comic-contain'); E.innerHTML = ''; E.appendChild(F); } }, addNextObserver = () => { let lastImg = [...gae('.comic-contain img')].pop(); nextObserver.observe(lastImg); }, removeOldChapter = () => { let titles = gae('.chapterTitle'); if (titles.length > options.remove[1]) { titles[0].remove(); let removes = gae('.comic-contain>*'); for (let i in removes) { if (/chapterTitle/.test(removes[i].className)) { break; } removes[i].remove(); } } }, addGlobalStyle = css => { let style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; document.head.appendChild(style); }, readCss = ` .goback { background: #fff url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAgpJREFUSEvtlD2IE0EYht9vJBeRQxIU5AoPCwsFGwsRrAQRzztRRFeEa6LsfiyBgJ2FrYWdSDjITH4uhYK4Ih74g4qFjSAWFoJYWCgKIigbVCSYzYxsGCXJ5ZLlDq6QTDPs9/M+H+/MDmGdFq0TB2PQqp0eW0fMfAUAKaUuAjBJvUxsneM4G7LZbBnAOSu+GIahFwRBOwksESiXy21MpVI3iehEt6gxZqnVap2t1+vNUbCRoEKhsLnZbC4R0UEr9tvuE3Z/lk6njxeLxe/DYENBrutuE0I8BLDXivwEcIqIjDHmDoBJG3+ltT5aqVS+rARbEeT7/g6t9RMAO23zNwBzSqkX8Tcz7wdwH8AWm38nhDhcKpXeD4INBPm+v0dr/RjAlG36SEQzUso33SKu6+4WQjwCsN3GPwM4opR63Q9bBvI87wAR3QOQtcVv2+32TLVa/TBoUmaeBhDDdtl8aIw5Vi6Xn3fX94CYeQ7ALQCbbNFLALNKqa/DDpqZtwJ4AGCfrfsF4IxSKra2s/6BPM+bJ6JFACmbexpF0clarfZj1NWN8/l8fjKKorsADtn6FhGdl1Je7wEx81UAF+KgMeZ2o9GYD4Lg71VOwoLjOBOZTOYGEZ3uiBNdk1J2NPutuwRgOgzDfNI/vn8C+4IsENEnKeXlZdYlGnkNRSNfhjVo97SOQat28v+z7g/utJ8bMvScRQAAAABJRU5ErkJggg==) no-repeat; background-position:bottom 6px right 5px; opacity: 0.7; border-radius: 50%; position: fixed; z-index:999; bottom: 7px; left: 50%; margin-left: -16px; width: 36px; height: 36px; } .mobadsq { display: none !important } ul { margin-block-start: -2px !important; margin-block-end: 2px !important } .chapterLoading { font-size: 20px; height: 80px; line-height: 32px; text-align: center; margin-bottom: 20px; } .chapterTitle { width: auto; height: 30px; font-size: 20px; font-family: Arial,sans-serif!important; line-height: 32px; text-align: center; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; margin: 10px 5px; border: 1px solid #e0e0e0; background-color: #f0f0f0; background: -webkit-gradient(linear, 0 0, 0 100%, from(#f9f9f9), to(#f0f0f0)); background: -moz-linear-gradient(top, #f9f9f9, #f0f0f0); box-shadow: 0 0 5px rgba(0, 0, 0, 0.6); border-radius: 5px; } .next_chapter + .l-content { display: none; } `; /* if (home) { addGlobalStyle(`amp-addthis[data-widget-type=floating]{display:none !important}`); ge('amp-addthis[data-widget-type=floating]').remove(); } */ if (read) { document['onkeydown'] = null; removeAd(); addGlobalStyle(readCss); if (options.topBtn) addGoBack(); let imgs = [...gae('.comic-contain amp-img')]; let title = ge('span.title').innerText; if (imgs.length > 3 && options.pln) picPreload(imgs, 3, `[${title} part1]`); insertData(document); addNextObserver(); if (options.pln) preloadNext(); /* const hidetoolbar = () => { var e = e || window.event; if (e.wheelDelta < 0 || e.detail > 0) { $('div.header').attr('style', 'top: -44px;'); $('div.bottom-bar').attr('style', 'bottom: -50px;') } else { $('div.header').attr('style', 'transform: translateY(0%);'); $('div.bottom-bar').attr('style', 'transform: translateY(0%);') } }; $('body').on('wheel', hidetoolbar); $('body').on('DOMMouseScroll', hidetoolbar); const keyhidetoolbar = (e) => { let key = window.event ? e.keyCode : e.which; if (key == '34' || key == '32' || key == '40') { $('div.header').attr('style', 'top: -44px;'); $('div.bottom-bar').attr('style', 'bottom: -50px;') } else { $('div.header').attr('style', 'transform: translateY(0%);'); $('div.bottom-bar').attr('style', 'transform: translateY(0%);') } }; $('body').on('keydown', keyhidetoolbar); if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) { let startY, moveY, Y; $('body').on('touchstart', (e) => { startY = e.originalEvent.changedTouches[0].pageY; }); $('body').on('touchmove', (e) => { moveY = e.originalEvent.changedTouches[0].pageY; Y = moveY - startY; if (Y < 0) { $('div.header').attr('style', 'top: -44px;'); $('div.bottom-bar').attr('style', 'bottom: -50px;') } else if (Y > 0) { $('div.header').attr('style', 'transform: translateY(0%);'); $('div.bottom-bar').attr('style', 'transform: translateY(0%);') } }); } */ } if (options.oint && !comic && !read) { openInNewTab(); new MutationObserver(() => { openInNewTab(); }).observe(document.body, { childList: true, subtree: true }); } if (options.aO && comic) { let button = ge('#button_show_all_chatper'); new IntersectionObserver(entries => { if (entries[0].isIntersecting) { button.click(); } }).observe(button); } })();