Greasy Fork

Greasy Fork is available in English.

包子漫画阅读辅助

包子漫画阅读辅助,瀑布流阅读连续载入图片,在新分页打开漫画链接(自用)。

当前为 2023-03-31 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name               包子漫畫閱讀輔助
// @name:en            Baozi Manga Read Helpr
// @name:zh-CN         包子漫画阅读辅助
// @name:zh-TW         包子漫畫閱讀輔助
// @version            2.4.2
// @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/*
// @icon               https://www.baozimh.com/favicon.ico
// @grant              none
// @license            MIT
// @namespace          http://greasyfork.icu/users/20361
// ==/UserScript==

(() => {
    'use strict';
    const options = { //true 開啟,false 關閉
        oint: true, //在新分頁打開漫畫鏈接。
        aH: true, //載入下一話時添加瀏覽器歷史紀錄
        aO: true, //目錄頁自動展開全部章節。
        pln: true, //預讀下一頁的圖片,減少等待加載圖片渲染頁面的時間。
        remove: [true, 4] //!!!不能小於2!!!閱讀載入超過n話時刪除前面話數的圖片。
    },
          ge = e => document.querySelector(e),
          gae = e => document.querySelectorAll(e),
          gx = x => document.evaluate(x, document, null, XPathResult.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),
          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;
}
.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;
}
          `,
          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) => {
              if (index >= imgsArray.length) {
                  imgsArray = null;
                  return;
              }
              let text = str || '';
              const loadImg = src => {
                  return new Promise(resolve => {
                      let temp = new Image();
                      temp.src = src;
                      temp.onload = () => {
                          resolve(`${text}[Pic(${src.match(/\/([-_\w]+)\.[a-z]{3,5}$/i)[1]})][Preload OK]\n${src}`);
                          temp = null;
                      };
                      temp.onerror = (e) => {
                          resolve(`${text}[Pic(${src.match(/\/([-_\w]+)\.[a-z]{3,5}$/i)[1]})][Preload ERROR]\n${src}`);
                          temp = null;
                      };
                  });
              };
              let e = imgsArray[index];
              let _src;
              if (e.tagName == 'IMG' && e.dataset.src) {
                  _src = e.dataset.src;
              } else if (e.getAttribute('src')) {
                  _src = e.getAttribute('src');
              } else {
                  _src = e;
              }
              let msg = await loadImg(_src);
              console.log(msg);
              msg = null;
              index++;
              picPreload(imgsArray, index, text);
          },
          preloadNext = () => {
              let url = getNextLink();
              if (url !== null) {
                  fetch(url).then(res => res.text()).then(res => {
                      var doc = null,
                          imgs = null;
                      doc = parseHTML(res);
                      imgs = doc.querySelectorAll('.comic-contain amp-img');
                      picPreload(imgs, 0, '[NextPage]');
                  });
              }
          },
          fetchData = url => {
              fetch(url).then(res => res.text()).then(res => {
                  let doc = parseHTML(res);
                  insertData(doc, url);
                  setTimeout(() => {
                      addNextObserver();
                  }, 1300);
              }).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.removeAttribute('data-src');
                      }
                      if (nE && nE.tagName == 'IMG' && nE.dataset.src) {
                          nE.src = nE.dataset.src;
                          nE.removeAttribute('data-src');
                      }
                  }
              });
          }),
          nextObserver = new IntersectionObserver((entries, observer) => {
              entries.forEach(entry => {
                  if (entry.isIntersecting) {
                      observer.unobserve(entry.target);
                      let url = getNextLink();
                      if (url !== null) {
                          console.log('觸發載入下一頁');
                          addLoad();
                          fetchData(url);
                      }
                  }
              });
          }),
          insertData = (d, url) => {
              let imgs = d.querySelectorAll('.comic-contain amp-img');
              let F = new DocumentFragment();
              let n = 0;
              if (ge('.comic-contain>img')) {
                  let currentLastImg = [...gae('.comic-contain>img')].pop();
                  let nextFirstImg = imgs[0];
                  //當目前最後一張圖片檔名是50的倍數時,和下一頁第一張圖片檔名不是1,則不插入下一頁的前4張圖,讓條漫整體圖片按正確順序銜接。
                  if (/\/(50|100|150|200|250|300)\.[a-z]{3,5}$/i.test(currentLastImg.src) && !/\/1\.[a-z]{3,5}$/i.test(nextFirstImg.getAttribute('src'))) {
                      n = 4;
                  }
              }
              for (let i = n; i < imgs.length; i++) {
                  let img = new Image();
                  img.className = 'comic-contain__item';
                  img.src = 'data:image/png;base64,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';
                  img.dataset.src = imgs[i].getAttribute('src');
                  imagesObserver.observe(img);
                  F.appendChild(img);
              }
              let load = ge('.chapterLoading');
              if (load) {
                  const rge = e => d.querySelector(e);
                  ['.comic-chapter>.next_chapter', '.bottom-bar', 'span.title'].forEach(e => {
                      ge(e).outerHTML = rge(e).outerHTML; //替換元素
                  });
                  showElement();
                  let title = rge('span.title').innerText;
                  if (!/\/\d+_\d+_\d+\.html$/.test(url)) { //是下一話才添加標題分隔條,下一頁則不添加。
                      let docTitle = d.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();
                      }
                  }, 300);
              } else {
                  showElement();
                  let E = ge('.comic-contain');
                  E.innerHTML = '';
                  E.appendChild(F);
              }
          },
          addNextObserver = () => {
              let lastImg = [...ge('.comic-contain').querySelectorAll('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();
                  }
              }
          };

    if (home) {
        addGlobalStyle(`amp-addthis[data-widget-type=floating]{display:none !important}`);
        ge('amp-addthis[data-widget-type=floating]').remove();
    }

    if (read) {
        removeAd();
        addGlobalStyle(readCss);
        addGoBack();
        let imgs = [...gae('.comic-contain amp-img')];
        if (imgs.length > 3) {
            picPreload(imgs, 3, '[CurrentPage]');
        }
        insertData(document);
        addNextObserver();
        if (options.pln) {
            preloadNext();
        }
    }

    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);
    }

})();