// ==UserScript==
// @name 小说下载器
// @name:en novel-downloader
// @name:ja 小説ダウンローダー
// @description 一个可扩展的通用型小说下载器。
// @description:en An scalable universal novel downloader.
// @description:ja スケーラブルなユニバーサル小説ダウンローダー。
// @version 5.2.1074
// @author bgme
// @supportURL https://github.com/404-novel-project/novel-downloader
// @exclude *://www.jjwxc.net/onebook.php?novelid=*&chapterid=*
// @exclude *://m.yuzhaige.cc/tag/*/
// @exclude *://m.yuzhaige.cc/sort/*/
// @exclude *://m.yuzhaige.cc/top/*/
// @exclude *://m.yuzhaige.cc/full/*/
// @exclude *://m.yuzhaige.cc/book/*/
// @exclude *://m.yushuge123.com/tag/*/
// @exclude *://m.yushuge123.com/sort/*/
// @exclude *://m.yushuge123.com/top/*/
// @exclude *://m.yushuge123.com/full/*/
// @exclude *://m.yushuge123.com/book/*/
// @exclude *://m.haitangtxt.net/tag/*/
// @exclude *://m.haitangtxt.net/sort/*/
// @exclude *://m.haitangtxt.net/top/*/
// @exclude *://m.haitangtxt.net/full/*/
// @exclude *://m.haitangtxt.net/book/*/
// @exclude *://www.linovel.net/book/*/*.html
// @exclude *://www.qimao.com/shuku/*-*/
// @exclude *://www.trxs.cc/tongren/*/*.html
// @exclude *://www.trxs.me/tongren/*/*.html
// @exclude *://www.trxs123.com/tongren/*/*.html
// @exclude *://www.jpxs123.com/*/*/*.html
// @exclude *://www.tongrenquan.org/tongren/*/*.html
// @exclude *://www.tongrenquan.me/tongren/*/*.html
// @exclude *://trxs.cc/tongren/*/*.html
// @exclude *://trxs.me/tongren/*/*.html
// @exclude *://trxs123.com/tongren/*/*.html
// @exclude *://jpxs123.com/*/*/*.html
// @exclude *://tongrenquan.org/tongren/*/*.html
// @exclude *://tongrenquan.me/tongren/*/*.html
// @exclude *://www.i25zw.com/lastupdate/
// @exclude *://www.i25zw.com/postdate/
// @exclude *://www.i25zw.com/monthvisit/
// @exclude *://www.i25zw.com/goodnum/
// @exclude *://www.i25zw.com/goodnew/
// @exclude *://dijiuben.com/*_*/*.html
// @exclude *://ncode.syosetu.com/*/*/
// @exclude *://novel18.syosetu.com/*/*/
// @exclude *://manhua.idmzj.com/
// @exclude *://houhuayuan.vip/
// @exclude *://book.sfacg.com/Novel/*/*/*/
// @exclude *://www.alphapolis.co.jp/novel/*/*/episode/*
// @exclude *://novelup.plus/story/*/*
// @exclude *://www.linovelib.com/novel/*/*.html
// @exclude *://www.bilinovel.com/novel/*/*.html
// @exclude *://www.qbtr.cc/*/*/*.html
// @exclude *://www.ciyuanji.com/chapter/*
// @exclude *://www.po18.tw/books/*/articles*
// @match *://www.po18.tw/books/*
// @match *://b.faloo.com/*
// @match *://www.ihuaben.com/book/*
// @match *://www.kadokado.com.tw/book/*
// @match *://www.uaa.com/novel/intro?id=*
// @match *://www.lzdzw.com/*/*.html
// @match *://novelpia.jp/novel/*
// @match *://www.60ksw.com/*/*/*/index.html
// @match *://czbooks.net/n/*
// @match *://book.qq.com/book-detail/*
// @match *://fanqienovel.com/page/*
// @match *://book.sfacg.com/Novel/*/MainIndex/
// @match *://book.sfacg.com/Novel/*/
// @match *://m.sfacg.com/b/*/
// @match *://www.lightnovel.us/cn/series/*
// @match *://www.lightnovel.us/cn/detail/*
// @match *://lcread.com/bookpage/*/index.html
// @match *://book.qidian.com/info/*
// @match *://www.qidian.com/book/*
// @match *://www.jjwxc.net/onebook.php?novelid=*
// @match *://m.jjwxc.com/book2/*
// @match *://m.jjwxc.net/book2/*
// @match *://www.gongzicp.com/novel-*.html
// @match *://gongzicp.com/novel-*.html
// @match *://m.gongzicp.com/novel-*.html
// @match *://book.zongheng.com/showchapter/*.html
// @match *://book.zongheng.com/book/*.html
// @match *://www.zongheng.com/detail/*
// @match *://huayu.zongheng.com/showchapter/*.html
// @match *://huayu.zongheng.com/book/*.html
// @match *://www.linovel.net/book/*.html
// @match *://www.17k.com/list/*.html
// @match *://www.17k.com/book/*.html
// @match *://www.shuhai.com/book/*.htm
// @match *://mm.shuhai.com/book/*.htm
// @match *://www.tadu.com/book/*
// @match *://www.qimao.com/shuku/*/
// @match *://sosad.fun/threads/*/profile*
// @match *://wenzhan.org/threads/*/profile*
// @match *://sosadfun.com/threads/*/profile*
// @match *://xn--pxtr7m5ny.com/threads/*/profile*
// @match *://xn--pxtr7m.com/threads/*/profile*
// @match *://xn--pxtr7m5ny.net/threads/*/profile*
// @match *://xn--pxtr7m.net/threads/*/profile*
// @match *://sosadfun.link/threads/*/profile*
// @match *://www.sosad.fun/threads/*/profile*
// @match *://www.wenzhan.org/threads/*/profile*
// @match *://www.sosadfun.com/threads/*/profile*
// @match *://www.xn--pxtr7m5ny.com/threads/*/profile*
// @match *://www.xn--pxtr7m.com/threads/*/profile*
// @match *://www.xn--pxtr7m5ny.net/threads/*/profile*
// @match *://www.xn--pxtr7m.net/threads/*/profile*
// @match *://www.sosadfun.link/threads/*/profile*
// @match *://www.uukanshu.com/b/*/
// @match *://www.yiruan.la/article/*.html
// @match *://www.ishuquge.org/txt/*/index.html
// @match *://wap.ishuquge.org/s/*.html
// @match *://wap.ishuquge.org/d/*.html
// @match *://www.xkzw.org/xkzw*/
// @match *://www.lewenn.net/lw*/
// @match *://www.266ks.com/book/*/
// @match *://www.266ks.com/book/*/index*.html
// @match *://www.23xsww.cc/book/*/*
// @match *://www.hetushu.com/book/*/index.html
// @match *://www.hetubook.com/book/*/index.html
// @match *://hetushu.com/book/*/index.html
// @match *://hetubook.com/book/*/index.html
// @match *://www.gashuw.com/biquge_*/
// @match *://www.1pwx.com/*.htm
// @match *://www.81book.com/book/*/
// @match *://www.81zw.com/book/*/
// @match *://m.yushuge123.com/*/*/
// @match *://www.wanben.info/*/
// @match *://m.wanben.info/*/
// @match *://www.idejian.com/book/*/
// @match *://www.wenku8.net/novel/*/*/index.htm
// @match *://www.wenku8.net/book/*.htm
// @match *://www.idmzj.com/info/*.html
// @match *://manhua.idmzj.com/*
// @match *://www.westnovel.com/*/*/
// @match *://www.mht99.com/*/
// @match *://www.banzhuer.org/*_*/
// @match *://www.xbiquge.tw/book/*/
// @match *://www.xsbiquge.la/book/*/
// @match *://www.bqu9.cc/book/*/
// @match *://www.bq06.cc/html/*/
// @match *://www.biququ.com/html/*/
// @match *://www.ddyucshu.cc/*/
// @match *://www.ddyveshu.cc/*/
// @match *://www.007zw.com/shuzhai/*/
// @match *://www.shaoniandream.com/book_detail/*
// @match *://www.linovelib.com/novel/*/catalog
// @match *://www.linovelib.com/novel/*.html
// @match *://www.bilinovel.com/novel/*.html
// @match *://www.bilinovel.com/novel/*/catalog
// @match *://www.luoqiuzw.com/book/*/
// @match *://www.yibige.cc/*/
// @match *://www.fushuwang.org/*/*/*/*.html
// @match *://www.fushuwang.org/*/*/*/*.html?*
// @match *://www.fushuwang.org/*/*/*.html
// @match *://www.fushuwang.org/*/*/*.html?*
// @match *://www.soxscc.net/*/
// @match *://www.soxscc.org/*/
// @match *://www.soxs.cc/*/
// @match *://www.soxscc.cc/*/
// @match *://www.soshuwu.com/*/
// @match *://www.soxscc.net/book/*.html
// @match *://www.soxscc.org/book/*.html
// @match *://www.soxs.cc/book/*.html
// @match *://www.soxscc.cc/book/*.html
// @match *://www.soshuwu.com/book/*.html
// @match *://www.shubaowa.org/*_*/
// @match *://www.fuguoduxs.com/*_*/
// @match *://www.630shu.net/shu/*.html
// @match *://www.trxs.cc/tongren/*.html
// @match *://www.trxs.me/tongren/*.html
// @match *://www.trxs123.com/tongren/*.html
// @match *://www.jpxs123.com/*/*.html
// @match *://www.tongrenquan.org/tongren/*.html
// @match *://www.tongrenquan.me/tongren/*.html
// @match *://trxs.cc/tongren/*.html
// @match *://trxs.me/tongren/*.html
// @match *://trxs123.com/tongren/*.html
// @match *://jpxs123.com/*/*.html
// @match *://tongrenquan.org/tongren/*.html
// @match *://tongrenquan.me/tongren/*.html
// @match *://www.256wenku.com/read/*/index.html
// @match *://www.256wenku.com/read/*/
// @match *://www.biquge66.com/biquge*/
// @match *://*.lofter.com/
// @match *://*.lofter.com/?page=*
// @match *://www.shubl.com/book/book_detail/*
// @match *://shubl.com/book/book_detail/*
// @match *://m.haitangtxt.net/*/*/
// @match *://ebook.longmabook.com/*
// @match *://www.haitangbook.com/*
// @match *://www.longmabookcn.com/*
// @match *://ebook.lmbooks.com/*
// @match *://www.lmebooks.com/*
// @match *://www.haitbook.com/*
// @match *://www.htwhbook.com/*
// @match *://www.myhtebook.com/*
// @match *://www.lovehtbooks.com/*
// @match *://www.myhtebooks.com/*
// @match *://www.myhtlmebook.com/*
// @match *://jp.myhtebook.com/*
// @match *://jp.myhtlmebook.com/*
// @match *://ebook.urhtbooks.com/*
// @match *://www.urhtbooks.com/*
// @match *://www.newhtbook.com/*
// @match *://www.lvhtebook.com/*
// @match *://jp.lvhtebook.com/*
// @match *://www.htlvbooks.com/*
// @match *://dijiuben.com/*_*
// @match *://www.biquzw.la/*_*/
// @match *://www.i25zw.com/*/
// @match *://www.tycqzw.com/*_*/
// @match *://www.kanunu8.com/*
// @match *://www.ciyuanji.com/*
// @match *://ciyuanji.com/*
// @match *://m.wanbengo.com/*/
// @match *://www.wanbengo.com/*/
// @match *://www.ranwen.la/files/article/*/*/
// @match *://www.wangshugu.org/books/*/*/
// @match *://m.baihexs.com/info-*/
// @match *://www.quanshuzhai.com/book/*.html
// @match *://masiro.me/admin/novelView?novel_id=*
// @match *://www.pixiv.net/novel/show.php?*
// @match *://www.pixiv.net/novel/series/*
// @match *://kakuyomu.jp/works/*
// @match *://ncode.syosetu.com/*/
// @match *://ncode.syosetu.com/*
// @match *://novel18.syosetu.com/*/
// @match *://novel18.syosetu.com/*
// @match *://syosetu.org/novel/*/
// @match *://houhuayuan.vip/*
// @match *://zhaoze.vip/*/
// @match *://www.myrics.com/novels/*
// @match *://m.lvsewx.com/ebook/*.html
// @match *://www.lvsewx.com/ebook/*.html
// @match *://www.shencou.com/books/read_*.html
// @match *://www.tianyabooks.com/*/*/
// @match *://www.aixiaxs.net/*/*/
// @match *://jingcaiyuedu6.com/novel/*.html
// @match *://www.hanwujinian.com/book/*
// @match *://manga.bilibili.com/detail/mc*
// @match *://www.aixdzs.com/novel/*
// @match *://www.cool18.com/bbs4/index.php?*
// @match *://www.biquge5200.cc/*_*/
// @match *://www.yqxsge.cc/html/*/*/index.html
// @match *://www.18kanshu.com/*/*/info.html
// @match *://www.18kanshu.com/module/novel/info.php?*
// @match *://www.bixia3.com/txt/*/
// @match *://www.xiaoshuowu.com/html/*/*/
// @match *://www.xrzww.com/bookdetail/*
// @match *://xrzww.com/bookdetail/*
// @match *://www.youdubook.com/bookdetail/*
// @match *://youdubook.com/bookdetail/*
// @match *://colorful-fantasybooks.com/module/novel/info.php?*
// @match *://www.dizishu.cc/*/*/
// @match *://www.ibiquge.la/*/*/
// @match *://www.akatsuki-novels.com/stories/index/novel_id~*
// @match *://www.alphapolis.co.jp/novel/*/*
// @match *://novelup.plus/story/*
// @match *://69shuba.cx/book/*.htm
// @match *://book.xbookcn.net/search/label/*
// @match *://new-read.readmoo.com/mooreader/*
// @match *://www.iqingguo.com/book/detail/?id=*
// @match *://www.ywggzy.com/bxwx/*/
// @match *://www.piaotia.com/html/*
// @match *://www.mbtxt.la/go/*/
// @match *://m.kuangguwenhua.com/bqg/*/
// @match *://m.kuangguwenhua.com/bqg/11365/index_*.html
// @match *://www.xyb3.net/5200/*/
// @match *://hongxiuzhao.me/*.html
// @match *://www.mijiashe.com/*/
// @match *://www.duread.cn/book/*
// @match *://duread.cn/book/*
// @match *://www.ttkan.co/novel/chapters/*
// @match *://cn.ttkan.co/novel/chapters/*
// @match *://tw.ttkan.co/novel/chapters/*
// @match *://www.xbyuan.com/*/
// @match *://www.ruochu.com/book/*
// @match *://www.quanzhifashi.com/novel/*/
// @match *://www.42zw.la/book/*/
// @match *://www.boqugew.com/shu/*/
// @match *://www.doufuyuedu.com/novel-*
// @match *://www.qbtr.cc/*/*.html
// @match *://www.penana.com/story/*/*/
// @match *://b.guidaye.com/*/*/
// @match *://www.esjzone.one/detail/*
// @match *://esjzone.one/detail/*
// @match *://www.esjzone.cc/detail/*
// @match *://www.fxshu.top/*/*.html
// @match *://xr.unionread.net/bookdetail/*
// @match *://www.qu-la.com/booktxt/*/
// @match *://www.bilibili.com/read/readlist/*
// @match *://www.69yuedu.net/article/*.html
// @compatible Firefox 100+
// @compatible Chrome 85+
// @compatible Edge 85+
// @compatible Opera 71+
// @compatible Safari 13.1+
// @connect self
// @connect bilibili.com
// @connect lightnovel.us
// @connect www.fxshu.top
// @connect qidian.com
// @connect yuewen.com
// @connect kuangxiangit.com
// @connect sinaimg.cn
// @connect jjwxc.net
// @connect jjwxc.com
// @connect gashuw.com
// @connect qpic.cn
// @connect zongheng.com
// @connect 17k.com
// @connect uukanshu.com
// @connect aliyuncs.com
// @connect cdn.bcebos.com
// @connect rs.sfacg.com
// @connect shuhai.com
// @connect ch-intel.com
// @connect huluxia.com
// @connect linovel.net
// @connect ax1x.com
// @connect tadu.com
// @connect zhangyue01.com
// @connect cdn.wtzw.com
// @connect wenku8.com
// @connect idmzj.com
// @connect 007zw.com
// @connect hongyeshuzhai.com
// @connect linovelib.com
// @connect soxscc.net
// @connect soxscc.org
// @connect soxs.cc
// @connect soxscc.cc
// @connect soshuwu.com
// @connect idejian.com
// @connect postimg.cc
// @connect lofter.com
// @connect lf127.net
// @connect 126.net
// @connect shubl.com
// @connect loli.net
// @connect alicdn.com
// @connect toutiaoimg.com
// @connect imgdb.cn
// @connect meego.cn
// @connect poco.cn
// @connect dijiuzww.com
// @connect dijiushu.net
// @connect i25zw.com
// @connect sina.com.cn
// @connect ciyuanji.com
// @connect wanben.org
// @connect baihexs.com
// @connect masiro.me
// @connect pximg.net
// @connect mitemin.net
// @connect myrics.com
// @connect jingcaiyuedu6.com
// @connect aixdzs.com
// @connect b5200.net
// @connect xrzww.com
// @connect youdubook.com
// @connect akatsuki-novels.com
// @connect alphapolis.co.jp
// @connect cdn.shucdn.com
// @connect readmoo.com
// @connect qingoo.cn
// @connect sundung.com
// @connect duread.cn
// @connect ttkan.co
// @connect bg3.co
// @connect wanbengo.com
// @connect xbyuan.com
// @connect shaoniandream.com
// @connect fuxs1.com
// @connect bqu9.cc
// @connect biququ.com
// @connect ddyucshu.cc
// @connect lcread.com
// @connect ddyveshu.cc
// @connect xr.unionread.net
// @connect www.qu-la.com
// @connect *
// @grant unsafeWindow
// @grant GM_info
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM.info
// @grant GM.xmlHttpRequest
// @grant GM.setValue
// @grant GM.getValue
// @grant GM.deleteValue
// @homepageURL https://github.com/404-novel-project/novel-downloader
// @icon https://fastly.jsdelivr.net/gh/404-novel-project/novel-downloader/assets/icon.png
// @incompatible Internet Explorer
// @license AGPL-3.0-or-later
// @namespace https://blog.bgme.me
// @noframes
// @require https://unpkg.com/crypto-js@4.1.1/crypto-js.js#sha512-NQVmLzNy4Lr5QTrmXvq/WzTMUnRHmv7nyIT/M6LyGPBS+TIeRxZ+YQaqWxjpRpvRMQSuYPQURZz/+pLi81xXeA==
// @require https://unpkg.com/fflate@0.8.0/umd/index.js#sha512-3yw8GlXXje/3cAJoUioEOZlQkRQptqZLsWUL2KUUkvsiTMpnuXPAn6ESSAeQVLnY+2VrTHOADFMTElWqjKG/Yg==
// @require https://unpkg.com/nunjucks@3.2.4/browser/nunjucks.min.js#sha512-YvU0oaPCJSOIFni9rIOthOs5GgtU5kNZMKQG/Nt33t/H9g/1+TK7KJuMsCZS6v4O3+x253OZlTzPryrUtxxORw==
// @require https://unpkg.com/vue@3.3.4/dist/vue.global.prod.js#sha512-7cmvZh1K81vCevOl9YPcvR6lCFgxol/biMYQ+YwsCiQFePxFrMVbJaHGUlu01/2EhNxKzKRpztUhWrwLyKCfiQ==
// @run-at document-start
// ==/UserScript==
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/@mozilla/readability/Readability-readerable.js":
/***/ ((module) => {
/*
* Copyright (c) 2010 Arc90 Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This code is heavily based on Arc90's readability.js (1.7.1) script
* available at: http://code.google.com/p/arc90labs-readability
*/
var REGEXPS = {
// NOTE: These two regular expressions are duplicated in
// Readability.js. Please keep both copies in sync.
unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i,
};
function isNodeVisible(node) {
// Have to null-check node.style and node.className.indexOf to deal with SVG and MathML nodes.
return (!node.style || node.style.display != "none")
&& !node.hasAttribute("hidden")
//check for "fallback-image" so that wikimedia math images are displayed
&& (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || (node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1));
}
/**
* Decides whether or not the document is reader-able without parsing the whole thing.
* @param {Object} options Configuration object.
* @param {number} [options.minContentLength=140] The minimum node content length used to decide if the document is readerable.
* @param {number} [options.minScore=20] The minumum cumulated 'score' used to determine if the document is readerable.
* @param {Function} [options.visibilityChecker=isNodeVisible] The function used to determine if a node is visible.
* @return {boolean} Whether or not we suspect Readability.parse() will suceeed at returning an article object.
*/
function isProbablyReaderable(doc, options = {}) {
// For backward compatibility reasons 'options' can either be a configuration object or the function used
// to determine if a node is visible.
if (typeof options == "function") {
options = { visibilityChecker: options };
}
var defaultOptions = { minScore: 20, minContentLength: 140, visibilityChecker: isNodeVisible };
options = Object.assign(defaultOptions, options);
var nodes = doc.querySelectorAll("p, pre, article");
// Get <div> nodes which have <br> node(s) and append them into the `nodes` variable.
// Some articles' DOM structures might look like
// <div>
// Sentences<br>
// <br>
// Sentences<br>
// </div>
var brNodes = doc.querySelectorAll("div > br");
if (brNodes.length) {
var set = new Set(nodes);
[].forEach.call(brNodes, function (node) {
set.add(node.parentNode);
});
nodes = Array.from(set);
}
var score = 0;
// This is a little cheeky, we use the accumulator 'score' to decide what to return from
// this callback:
return [].some.call(nodes, function (node) {
if (!options.visibilityChecker(node)) {
return false;
}
var matchString = node.className + " " + node.id;
if (REGEXPS.unlikelyCandidates.test(matchString) &&
!REGEXPS.okMaybeItsACandidate.test(matchString)) {
return false;
}
if (node.matches("li p")) {
return false;
}
var textContentLength = node.textContent.trim().length;
if (textContentLength < options.minContentLength) {
return false;
}
score += Math.sqrt(textContentLength - options.minContentLength);
if (score > options.minScore) {
return true;
}
return false;
});
}
if (true) {
/* global module */
module.exports = isProbablyReaderable;
}
/***/ }),
/***/ "./node_modules/@mozilla/readability/Readability.js":
/***/ ((module) => {
/*
* Copyright (c) 2010 Arc90 Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This code is heavily based on Arc90's readability.js (1.7.1) script
* available at: http://code.google.com/p/arc90labs-readability
*/
/**
* Public constructor.
* @param {HTMLDocument} doc The document to parse.
* @param {Object} options The options object.
*/
function Readability(doc, options) {
// In some older versions, people passed a URI as the first argument. Cope:
if (options && options.documentElement) {
doc = options;
options = arguments[2];
} else if (!doc || !doc.documentElement) {
throw new Error("First argument to Readability constructor should be a document object.");
}
options = options || {};
this._doc = doc;
this._docJSDOMParser = this._doc.firstChild.__JSDOMParser__;
this._articleTitle = null;
this._articleByline = null;
this._articleDir = null;
this._articleSiteName = null;
this._attempts = [];
// Configurable options
this._debug = !!options.debug;
this._maxElemsToParse = options.maxElemsToParse || this.DEFAULT_MAX_ELEMS_TO_PARSE;
this._nbTopCandidates = options.nbTopCandidates || this.DEFAULT_N_TOP_CANDIDATES;
this._charThreshold = options.charThreshold || this.DEFAULT_CHAR_THRESHOLD;
this._classesToPreserve = this.CLASSES_TO_PRESERVE.concat(options.classesToPreserve || []);
this._keepClasses = !!options.keepClasses;
this._serializer = options.serializer || function(el) {
return el.innerHTML;
};
this._disableJSONLD = !!options.disableJSONLD;
this._allowedVideoRegex = options.allowedVideoRegex || this.REGEXPS.videos;
// Start with all flags set
this._flags = this.FLAG_STRIP_UNLIKELYS |
this.FLAG_WEIGHT_CLASSES |
this.FLAG_CLEAN_CONDITIONALLY;
// Control whether log messages are sent to the console
if (this._debug) {
let logNode = function(node) {
if (node.nodeType == node.TEXT_NODE) {
return `${node.nodeName} ("${node.textContent}")`;
}
let attrPairs = Array.from(node.attributes || [], function(attr) {
return `${attr.name}="${attr.value}"`;
}).join(" ");
return `<${node.localName} ${attrPairs}>`;
};
this.log = function () {
if (typeof console !== "undefined") {
let args = Array.from(arguments, arg => {
if (arg && arg.nodeType == this.ELEMENT_NODE) {
return logNode(arg);
}
return arg;
});
args.unshift("Reader: (Readability)");
console.log.apply(console, args);
} else if (typeof dump !== "undefined") {
/* global dump */
var msg = Array.prototype.map.call(arguments, function(x) {
return (x && x.nodeName) ? logNode(x) : x;
}).join(" ");
dump("Reader: (Readability) " + msg + "\n");
}
};
} else {
this.log = function () {};
}
}
Readability.prototype = {
FLAG_STRIP_UNLIKELYS: 0x1,
FLAG_WEIGHT_CLASSES: 0x2,
FLAG_CLEAN_CONDITIONALLY: 0x4,
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
ELEMENT_NODE: 1,
TEXT_NODE: 3,
// Max number of nodes supported by this parser. Default: 0 (no limit)
DEFAULT_MAX_ELEMS_TO_PARSE: 0,
// The number of top candidates to consider when analysing how
// tight the competition is among candidates.
DEFAULT_N_TOP_CANDIDATES: 5,
// Element tags to score by default.
DEFAULT_TAGS_TO_SCORE: "section,h2,h3,h4,h5,h6,p,td,pre".toUpperCase().split(","),
// The default number of chars an article must have in order to return a result
DEFAULT_CHAR_THRESHOLD: 500,
// All of the regular expressions in use within readability.
// Defined up here so we don't instantiate them repeatedly in loops.
REGEXPS: {
// NOTE: These two regular expressions are duplicated in
// Readability-readerable.js. Please keep both copies in sync.
unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i,
positive: /article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,
negative: /-ad-|hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|gdpr|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
extraneous: /print|archive|comment|discuss|e[\-]?mail|share|reply|all|login|sign|single|utility/i,
byline: /byline|author|dateline|writtenby|p-author/i,
replaceFonts: /<(\/?)font[^>]*>/gi,
normalize: /\s{2,}/g,
videos: /\/\/(www\.)?((dailymotion|youtube|youtube-nocookie|player\.vimeo|v\.qq)\.com|(archive|upload\.wikimedia)\.org|player\.twitch\.tv)/i,
shareElements: /(\b|_)(share|sharedaddy)(\b|_)/i,
nextLink: /(next|weiter|continue|>([^\|]|$)|»([^\|]|$))/i,
prevLink: /(prev|earl|old|new|<|«)/i,
tokenize: /\W+/g,
whitespace: /^\s*$/,
hasContent: /\S$/,
hashUrl: /^#.+/,
srcsetUrl: /(\S+)(\s+[\d.]+[xw])?(\s*(?:,|$))/g,
b64DataUrl: /^data:\s*([^\s;,]+)\s*;\s*base64\s*,/i,
// Commas as used in Latin, Sindhi, Chinese and various other scripts.
// see: https://en.wikipedia.org/wiki/Comma#Comma_variants
commas: /\u002C|\u060C|\uFE50|\uFE10|\uFE11|\u2E41|\u2E34|\u2E32|\uFF0C/g,
// See: https://schema.org/Article
jsonLdArticleTypes: /^Article|AdvertiserContentArticle|NewsArticle|AnalysisNewsArticle|AskPublicNewsArticle|BackgroundNewsArticle|OpinionNewsArticle|ReportageNewsArticle|ReviewNewsArticle|Report|SatiricalArticle|ScholarlyArticle|MedicalScholarlyArticle|SocialMediaPosting|BlogPosting|LiveBlogPosting|DiscussionForumPosting|TechArticle|APIReference$/
},
UNLIKELY_ROLES: [ "menu", "menubar", "complementary", "navigation", "alert", "alertdialog", "dialog" ],
DIV_TO_P_ELEMS: new Set([ "BLOCKQUOTE", "DL", "DIV", "IMG", "OL", "P", "PRE", "TABLE", "UL" ]),
ALTER_TO_DIV_EXCEPTIONS: ["DIV", "ARTICLE", "SECTION", "P"],
PRESENTATIONAL_ATTRIBUTES: [ "align", "background", "bgcolor", "border", "cellpadding", "cellspacing", "frame", "hspace", "rules", "style", "valign", "vspace" ],
DEPRECATED_SIZE_ATTRIBUTE_ELEMS: [ "TABLE", "TH", "TD", "HR", "PRE" ],
// The commented out elements qualify as phrasing content but tend to be
// removed by readability when put into paragraphs, so we ignore them here.
PHRASING_ELEMS: [
// "CANVAS", "IFRAME", "SVG", "VIDEO",
"ABBR", "AUDIO", "B", "BDO", "BR", "BUTTON", "CITE", "CODE", "DATA",
"DATALIST", "DFN", "EM", "EMBED", "I", "IMG", "INPUT", "KBD", "LABEL",
"MARK", "MATH", "METER", "NOSCRIPT", "OBJECT", "OUTPUT", "PROGRESS", "Q",
"RUBY", "SAMP", "SCRIPT", "SELECT", "SMALL", "SPAN", "STRONG", "SUB",
"SUP", "TEXTAREA", "TIME", "VAR", "WBR"
],
// These are the classes that readability sets itself.
CLASSES_TO_PRESERVE: [ "page" ],
// These are the list of HTML entities that need to be escaped.
HTML_ESCAPE_MAP: {
"lt": "<",
"gt": ">",
"amp": "&",
"quot": '"',
"apos": "'",
},
/**
* Run any post-process modifications to article content as necessary.
*
* @param Element
* @return void
**/
_postProcessContent: function(articleContent) {
// Readability cannot open relative uris so we convert them to absolute uris.
this._fixRelativeUris(articleContent);
this._simplifyNestedElements(articleContent);
if (!this._keepClasses) {
// Remove classes.
this._cleanClasses(articleContent);
}
},
/**
* Iterates over a NodeList, calls `filterFn` for each node and removes node
* if function returned `true`.
*
* If function is not passed, removes all the nodes in node list.
*
* @param NodeList nodeList The nodes to operate on
* @param Function filterFn the function to use as a filter
* @return void
*/
_removeNodes: function(nodeList, filterFn) {
// Avoid ever operating on live node lists.
if (this._docJSDOMParser && nodeList._isLiveNodeList) {
throw new Error("Do not pass live node lists to _removeNodes");
}
for (var i = nodeList.length - 1; i >= 0; i--) {
var node = nodeList[i];
var parentNode = node.parentNode;
if (parentNode) {
if (!filterFn || filterFn.call(this, node, i, nodeList)) {
parentNode.removeChild(node);
}
}
}
},
/**
* Iterates over a NodeList, and calls _setNodeTag for each node.
*
* @param NodeList nodeList The nodes to operate on
* @param String newTagName the new tag name to use
* @return void
*/
_replaceNodeTags: function(nodeList, newTagName) {
// Avoid ever operating on live node lists.
if (this._docJSDOMParser && nodeList._isLiveNodeList) {
throw new Error("Do not pass live node lists to _replaceNodeTags");
}
for (const node of nodeList) {
this._setNodeTag(node, newTagName);
}
},
/**
* Iterate over a NodeList, which doesn't natively fully implement the Array
* interface.
*
* For convenience, the current object context is applied to the provided
* iterate function.
*
* @param NodeList nodeList The NodeList.
* @param Function fn The iterate function.
* @return void
*/
_forEachNode: function(nodeList, fn) {
Array.prototype.forEach.call(nodeList, fn, this);
},
/**
* Iterate over a NodeList, and return the first node that passes
* the supplied test function
*
* For convenience, the current object context is applied to the provided
* test function.
*
* @param NodeList nodeList The NodeList.
* @param Function fn The test function.
* @return void
*/
_findNode: function(nodeList, fn) {
return Array.prototype.find.call(nodeList, fn, this);
},
/**
* Iterate over a NodeList, return true if any of the provided iterate
* function calls returns true, false otherwise.
*
* For convenience, the current object context is applied to the
* provided iterate function.
*
* @param NodeList nodeList The NodeList.
* @param Function fn The iterate function.
* @return Boolean
*/
_someNode: function(nodeList, fn) {
return Array.prototype.some.call(nodeList, fn, this);
},
/**
* Iterate over a NodeList, return true if all of the provided iterate
* function calls return true, false otherwise.
*
* For convenience, the current object context is applied to the
* provided iterate function.
*
* @param NodeList nodeList The NodeList.
* @param Function fn The iterate function.
* @return Boolean
*/
_everyNode: function(nodeList, fn) {
return Array.prototype.every.call(nodeList, fn, this);
},
/**
* Concat all nodelists passed as arguments.
*
* @return ...NodeList
* @return Array
*/
_concatNodeLists: function() {
var slice = Array.prototype.slice;
var args = slice.call(arguments);
var nodeLists = args.map(function(list) {
return slice.call(list);
});
return Array.prototype.concat.apply([], nodeLists);
},
_getAllNodesWithTag: function(node, tagNames) {
if (node.querySelectorAll) {
return node.querySelectorAll(tagNames.join(","));
}
return [].concat.apply([], tagNames.map(function(tag) {
var collection = node.getElementsByTagName(tag);
return Array.isArray(collection) ? collection : Array.from(collection);
}));
},
/**
* Removes the class="" attribute from every element in the given
* subtree, except those that match CLASSES_TO_PRESERVE and
* the classesToPreserve array from the options object.
*
* @param Element
* @return void
*/
_cleanClasses: function(node) {
var classesToPreserve = this._classesToPreserve;
var className = (node.getAttribute("class") || "")
.split(/\s+/)
.filter(function(cls) {
return classesToPreserve.indexOf(cls) != -1;
})
.join(" ");
if (className) {
node.setAttribute("class", className);
} else {
node.removeAttribute("class");
}
for (node = node.firstElementChild; node; node = node.nextElementSibling) {
this._cleanClasses(node);
}
},
/**
* Converts each <a> and <img> uri in the given element to an absolute URI,
* ignoring #ref URIs.
*
* @param Element
* @return void
*/
_fixRelativeUris: function(articleContent) {
var baseURI = this._doc.baseURI;
var documentURI = this._doc.documentURI;
function toAbsoluteURI(uri) {
// Leave hash links alone if the base URI matches the document URI:
if (baseURI == documentURI && uri.charAt(0) == "#") {
return uri;
}
// Otherwise, resolve against base URI:
try {
return new URL(uri, baseURI).href;
} catch (ex) {
// Something went wrong, just return the original:
}
return uri;
}
var links = this._getAllNodesWithTag(articleContent, ["a"]);
this._forEachNode(links, function(link) {
var href = link.getAttribute("href");
if (href) {
// Remove links with javascript: URIs, since
// they won't work after scripts have been removed from the page.
if (href.indexOf("javascript:") === 0) {
// if the link only contains simple text content, it can be converted to a text node
if (link.childNodes.length === 1 && link.childNodes[0].nodeType === this.TEXT_NODE) {
var text = this._doc.createTextNode(link.textContent);
link.parentNode.replaceChild(text, link);
} else {
// if the link has multiple children, they should all be preserved
var container = this._doc.createElement("span");
while (link.firstChild) {
container.appendChild(link.firstChild);
}
link.parentNode.replaceChild(container, link);
}
} else {
link.setAttribute("href", toAbsoluteURI(href));
}
}
});
var medias = this._getAllNodesWithTag(articleContent, [
"img", "picture", "figure", "video", "audio", "source"
]);
this._forEachNode(medias, function(media) {
var src = media.getAttribute("src");
var poster = media.getAttribute("poster");
var srcset = media.getAttribute("srcset");
if (src) {
media.setAttribute("src", toAbsoluteURI(src));
}
if (poster) {
media.setAttribute("poster", toAbsoluteURI(poster));
}
if (srcset) {
var newSrcset = srcset.replace(this.REGEXPS.srcsetUrl, function(_, p1, p2, p3) {
return toAbsoluteURI(p1) + (p2 || "") + p3;
});
media.setAttribute("srcset", newSrcset);
}
});
},
_simplifyNestedElements: function(articleContent) {
var node = articleContent;
while (node) {
if (node.parentNode && ["DIV", "SECTION"].includes(node.tagName) && !(node.id && node.id.startsWith("readability"))) {
if (this._isElementWithoutContent(node)) {
node = this._removeAndGetNext(node);
continue;
} else if (this._hasSingleTagInsideElement(node, "DIV") || this._hasSingleTagInsideElement(node, "SECTION")) {
var child = node.children[0];
for (var i = 0; i < node.attributes.length; i++) {
child.setAttribute(node.attributes[i].name, node.attributes[i].value);
}
node.parentNode.replaceChild(child, node);
node = child;
continue;
}
}
node = this._getNextNode(node);
}
},
/**
* Get the article title as an H1.
*
* @return string
**/
_getArticleTitle: function() {
var doc = this._doc;
var curTitle = "";
var origTitle = "";
try {
curTitle = origTitle = doc.title.trim();
// If they had an element with id "title" in their HTML
if (typeof curTitle !== "string")
curTitle = origTitle = this._getInnerText(doc.getElementsByTagName("title")[0]);
} catch (e) {/* ignore exceptions setting the title. */}
var titleHadHierarchicalSeparators = false;
function wordCount(str) {
return str.split(/\s+/).length;
}
// If there's a separator in the title, first remove the final part
if ((/ [\|\-\\\/>»] /).test(curTitle)) {
titleHadHierarchicalSeparators = / [\\\/>»] /.test(curTitle);
curTitle = origTitle.replace(/(.*)[\|\-\\\/>»] .*/gi, "$1");
// If the resulting title is too short (3 words or fewer), remove
// the first part instead:
if (wordCount(curTitle) < 3)
curTitle = origTitle.replace(/[^\|\-\\\/>»]*[\|\-\\\/>»](.*)/gi, "$1");
} else if (curTitle.indexOf(": ") !== -1) {
// Check if we have an heading containing this exact string, so we
// could assume it's the full title.
var headings = this._concatNodeLists(
doc.getElementsByTagName("h1"),
doc.getElementsByTagName("h2")
);
var trimmedTitle = curTitle.trim();
var match = this._someNode(headings, function(heading) {
return heading.textContent.trim() === trimmedTitle;
});
// If we don't, let's extract the title out of the original title string.
if (!match) {
curTitle = origTitle.substring(origTitle.lastIndexOf(":") + 1);
// If the title is now too short, try the first colon instead:
if (wordCount(curTitle) < 3) {
curTitle = origTitle.substring(origTitle.indexOf(":") + 1);
// But if we have too many words before the colon there's something weird
// with the titles and the H tags so let's just use the original title instead
} else if (wordCount(origTitle.substr(0, origTitle.indexOf(":"))) > 5) {
curTitle = origTitle;
}
}
} else if (curTitle.length > 150 || curTitle.length < 15) {
var hOnes = doc.getElementsByTagName("h1");
if (hOnes.length === 1)
curTitle = this._getInnerText(hOnes[0]);
}
curTitle = curTitle.trim().replace(this.REGEXPS.normalize, " ");
// If we now have 4 words or fewer as our title, and either no
// 'hierarchical' separators (\, /, > or ») were found in the original
// title or we decreased the number of words by more than 1 word, use
// the original title.
var curTitleWordCount = wordCount(curTitle);
if (curTitleWordCount <= 4 &&
(!titleHadHierarchicalSeparators ||
curTitleWordCount != wordCount(origTitle.replace(/[\|\-\\\/>»]+/g, "")) - 1)) {
curTitle = origTitle;
}
return curTitle;
},
/**
* Prepare the HTML document for readability to scrape it.
* This includes things like stripping javascript, CSS, and handling terrible markup.
*
* @return void
**/
_prepDocument: function() {
var doc = this._doc;
// Remove all style tags in head
this._removeNodes(this._getAllNodesWithTag(doc, ["style"]));
if (doc.body) {
this._replaceBrs(doc.body);
}
this._replaceNodeTags(this._getAllNodesWithTag(doc, ["font"]), "SPAN");
},
/**
* Finds the next node, starting from the given node, and ignoring
* whitespace in between. If the given node is an element, the same node is
* returned.
*/
_nextNode: function (node) {
var next = node;
while (next
&& (next.nodeType != this.ELEMENT_NODE)
&& this.REGEXPS.whitespace.test(next.textContent)) {
next = next.nextSibling;
}
return next;
},
/**
* Replaces 2 or more successive <br> elements with a single <p>.
* Whitespace between <br> elements are ignored. For example:
* <div>foo<br>bar<br> <br><br>abc</div>
* will become:
* <div>foo<br>bar<p>abc</p></div>
*/
_replaceBrs: function (elem) {
this._forEachNode(this._getAllNodesWithTag(elem, ["br"]), function(br) {
var next = br.nextSibling;
// Whether 2 or more <br> elements have been found and replaced with a
// <p> block.
var replaced = false;
// If we find a <br> chain, remove the <br>s until we hit another node
// or non-whitespace. This leaves behind the first <br> in the chain
// (which will be replaced with a <p> later).
while ((next = this._nextNode(next)) && (next.tagName == "BR")) {
replaced = true;
var brSibling = next.nextSibling;
next.parentNode.removeChild(next);
next = brSibling;
}
// If we removed a <br> chain, replace the remaining <br> with a <p>. Add
// all sibling nodes as children of the <p> until we hit another <br>
// chain.
if (replaced) {
var p = this._doc.createElement("p");
br.parentNode.replaceChild(p, br);
next = p.nextSibling;
while (next) {
// If we've hit another <br><br>, we're done adding children to this <p>.
if (next.tagName == "BR") {
var nextElem = this._nextNode(next.nextSibling);
if (nextElem && nextElem.tagName == "BR")
break;
}
if (!this._isPhrasingContent(next))
break;
// Otherwise, make this node a child of the new <p>.
var sibling = next.nextSibling;
p.appendChild(next);
next = sibling;
}
while (p.lastChild && this._isWhitespace(p.lastChild)) {
p.removeChild(p.lastChild);
}
if (p.parentNode.tagName === "P")
this._setNodeTag(p.parentNode, "DIV");
}
});
},
_setNodeTag: function (node, tag) {
this.log("_setNodeTag", node, tag);
if (this._docJSDOMParser) {
node.localName = tag.toLowerCase();
node.tagName = tag.toUpperCase();
return node;
}
var replacement = node.ownerDocument.createElement(tag);
while (node.firstChild) {
replacement.appendChild(node.firstChild);
}
node.parentNode.replaceChild(replacement, node);
if (node.readability)
replacement.readability = node.readability;
for (var i = 0; i < node.attributes.length; i++) {
try {
replacement.setAttribute(node.attributes[i].name, node.attributes[i].value);
} catch (ex) {
/* it's possible for setAttribute() to throw if the attribute name
* isn't a valid XML Name. Such attributes can however be parsed from
* source in HTML docs, see https://github.com/whatwg/html/issues/4275,
* so we can hit them here and then throw. We don't care about such
* attributes so we ignore them.
*/
}
}
return replacement;
},
/**
* Prepare the article node for display. Clean out any inline styles,
* iframes, forms, strip extraneous <p> tags, etc.
*
* @param Element
* @return void
**/
_prepArticle: function(articleContent) {
this._cleanStyles(articleContent);
// Check for data tables before we continue, to avoid removing items in
// those tables, which will often be isolated even though they're
// visually linked to other content-ful elements (text, images, etc.).
this._markDataTables(articleContent);
this._fixLazyImages(articleContent);
// Clean out junk from the article content
this._cleanConditionally(articleContent, "form");
this._cleanConditionally(articleContent, "fieldset");
this._clean(articleContent, "object");
this._clean(articleContent, "embed");
this._clean(articleContent, "footer");
this._clean(articleContent, "link");
this._clean(articleContent, "aside");
// Clean out elements with little content that have "share" in their id/class combinations from final top candidates,
// which means we don't remove the top candidates even they have "share".
var shareElementThreshold = this.DEFAULT_CHAR_THRESHOLD;
this._forEachNode(articleContent.children, function (topCandidate) {
this._cleanMatchedNodes(topCandidate, function (node, matchString) {
return this.REGEXPS.shareElements.test(matchString) && node.textContent.length < shareElementThreshold;
});
});
this._clean(articleContent, "iframe");
this._clean(articleContent, "input");
this._clean(articleContent, "textarea");
this._clean(articleContent, "select");
this._clean(articleContent, "button");
this._cleanHeaders(articleContent);
// Do these last as the previous stuff may have removed junk
// that will affect these
this._cleanConditionally(articleContent, "table");
this._cleanConditionally(articleContent, "ul");
this._cleanConditionally(articleContent, "div");
// replace H1 with H2 as H1 should be only title that is displayed separately
this._replaceNodeTags(this._getAllNodesWithTag(articleContent, ["h1"]), "h2");
// Remove extra paragraphs
this._removeNodes(this._getAllNodesWithTag(articleContent, ["p"]), function (paragraph) {
var imgCount = paragraph.getElementsByTagName("img").length;
var embedCount = paragraph.getElementsByTagName("embed").length;
var objectCount = paragraph.getElementsByTagName("object").length;
// At this point, nasty iframes have been removed, only remain embedded video ones.
var iframeCount = paragraph.getElementsByTagName("iframe").length;
var totalCount = imgCount + embedCount + objectCount + iframeCount;
return totalCount === 0 && !this._getInnerText(paragraph, false);
});
this._forEachNode(this._getAllNodesWithTag(articleContent, ["br"]), function(br) {
var next = this._nextNode(br.nextSibling);
if (next && next.tagName == "P")
br.parentNode.removeChild(br);
});
// Remove single-cell tables
this._forEachNode(this._getAllNodesWithTag(articleContent, ["table"]), function(table) {
var tbody = this._hasSingleTagInsideElement(table, "TBODY") ? table.firstElementChild : table;
if (this._hasSingleTagInsideElement(tbody, "TR")) {
var row = tbody.firstElementChild;
if (this._hasSingleTagInsideElement(row, "TD")) {
var cell = row.firstElementChild;
cell = this._setNodeTag(cell, this._everyNode(cell.childNodes, this._isPhrasingContent) ? "P" : "DIV");
table.parentNode.replaceChild(cell, table);
}
}
});
},
/**
* Initialize a node with the readability object. Also checks the
* className/id for special names to add to its score.
*
* @param Element
* @return void
**/
_initializeNode: function(node) {
node.readability = {"contentScore": 0};
switch (node.tagName) {
case "DIV":
node.readability.contentScore += 5;
break;
case "PRE":
case "TD":
case "BLOCKQUOTE":
node.readability.contentScore += 3;
break;
case "ADDRESS":
case "OL":
case "UL":
case "DL":
case "DD":
case "DT":
case "LI":
case "FORM":
node.readability.contentScore -= 3;
break;
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
case "TH":
node.readability.contentScore -= 5;
break;
}
node.readability.contentScore += this._getClassWeight(node);
},
_removeAndGetNext: function(node) {
var nextNode = this._getNextNode(node, true);
node.parentNode.removeChild(node);
return nextNode;
},
/**
* Traverse the DOM from node to node, starting at the node passed in.
* Pass true for the second parameter to indicate this node itself
* (and its kids) are going away, and we want the next node over.
*
* Calling this in a loop will traverse the DOM depth-first.
*/
_getNextNode: function(node, ignoreSelfAndKids) {
// First check for kids if those aren't being ignored
if (!ignoreSelfAndKids && node.firstElementChild) {
return node.firstElementChild;
}
// Then for siblings...
if (node.nextElementSibling) {
return node.nextElementSibling;
}
// And finally, move up the parent chain *and* find a sibling
// (because this is depth-first traversal, we will have already
// seen the parent nodes themselves).
do {
node = node.parentNode;
} while (node && !node.nextElementSibling);
return node && node.nextElementSibling;
},
// compares second text to first one
// 1 = same text, 0 = completely different text
// works the way that it splits both texts into words and then finds words that are unique in second text
// the result is given by the lower length of unique parts
_textSimilarity: function(textA, textB) {
var tokensA = textA.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean);
var tokensB = textB.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean);
if (!tokensA.length || !tokensB.length) {
return 0;
}
var uniqTokensB = tokensB.filter(token => !tokensA.includes(token));
var distanceB = uniqTokensB.join(" ").length / tokensB.join(" ").length;
return 1 - distanceB;
},
_checkByline: function(node, matchString) {
if (this._articleByline) {
return false;
}
if (node.getAttribute !== undefined) {
var rel = node.getAttribute("rel");
var itemprop = node.getAttribute("itemprop");
}
if ((rel === "author" || (itemprop && itemprop.indexOf("author") !== -1) || this.REGEXPS.byline.test(matchString)) && this._isValidByline(node.textContent)) {
this._articleByline = node.textContent.trim();
return true;
}
return false;
},
_getNodeAncestors: function(node, maxDepth) {
maxDepth = maxDepth || 0;
var i = 0, ancestors = [];
while (node.parentNode) {
ancestors.push(node.parentNode);
if (maxDepth && ++i === maxDepth)
break;
node = node.parentNode;
}
return ancestors;
},
/***
* grabArticle - Using a variety of metrics (content score, classname, element types), find the content that is
* most likely to be the stuff a user wants to read. Then return it wrapped up in a div.
*
* @param page a document to run upon. Needs to be a full document, complete with body.
* @return Element
**/
_grabArticle: function (page) {
this.log("**** grabArticle ****");
var doc = this._doc;
var isPaging = page !== null;
page = page ? page : this._doc.body;
// We can't grab an article if we don't have a page!
if (!page) {
this.log("No body found in document. Abort.");
return null;
}
var pageCacheHtml = page.innerHTML;
while (true) {
this.log("Starting grabArticle loop");
var stripUnlikelyCandidates = this._flagIsActive(this.FLAG_STRIP_UNLIKELYS);
// First, node prepping. Trash nodes that look cruddy (like ones with the
// class name "comment", etc), and turn divs into P tags where they have been
// used inappropriately (as in, where they contain no other block level elements.)
var elementsToScore = [];
var node = this._doc.documentElement;
let shouldRemoveTitleHeader = true;
while (node) {
if (node.tagName === "HTML") {
this._articleLang = node.getAttribute("lang");
}
var matchString = node.className + " " + node.id;
if (!this._isProbablyVisible(node)) {
this.log("Removing hidden node - " + matchString);
node = this._removeAndGetNext(node);
continue;
}
// User is not able to see elements applied with both "aria-modal = true" and "role = dialog"
if (node.getAttribute("aria-modal") == "true" && node.getAttribute("role") == "dialog") {
node = this._removeAndGetNext(node);
continue;
}
// Check to see if this node is a byline, and remove it if it is.
if (this._checkByline(node, matchString)) {
node = this._removeAndGetNext(node);
continue;
}
if (shouldRemoveTitleHeader && this._headerDuplicatesTitle(node)) {
this.log("Removing header: ", node.textContent.trim(), this._articleTitle.trim());
shouldRemoveTitleHeader = false;
node = this._removeAndGetNext(node);
continue;
}
// Remove unlikely candidates
if (stripUnlikelyCandidates) {
if (this.REGEXPS.unlikelyCandidates.test(matchString) &&
!this.REGEXPS.okMaybeItsACandidate.test(matchString) &&
!this._hasAncestorTag(node, "table") &&
!this._hasAncestorTag(node, "code") &&
node.tagName !== "BODY" &&
node.tagName !== "A") {
this.log("Removing unlikely candidate - " + matchString);
node = this._removeAndGetNext(node);
continue;
}
if (this.UNLIKELY_ROLES.includes(node.getAttribute("role"))) {
this.log("Removing content with role " + node.getAttribute("role") + " - " + matchString);
node = this._removeAndGetNext(node);
continue;
}
}
// Remove DIV, SECTION, and HEADER nodes without any content(e.g. text, image, video, or iframe).
if ((node.tagName === "DIV" || node.tagName === "SECTION" || node.tagName === "HEADER" ||
node.tagName === "H1" || node.tagName === "H2" || node.tagName === "H3" ||
node.tagName === "H4" || node.tagName === "H5" || node.tagName === "H6") &&
this._isElementWithoutContent(node)) {
node = this._removeAndGetNext(node);
continue;
}
if (this.DEFAULT_TAGS_TO_SCORE.indexOf(node.tagName) !== -1) {
elementsToScore.push(node);
}
// Turn all divs that don't have children block level elements into p's
if (node.tagName === "DIV") {
// Put phrasing content into paragraphs.
var p = null;
var childNode = node.firstChild;
while (childNode) {
var nextSibling = childNode.nextSibling;
if (this._isPhrasingContent(childNode)) {
if (p !== null) {
p.appendChild(childNode);
} else if (!this._isWhitespace(childNode)) {
p = doc.createElement("p");
node.replaceChild(p, childNode);
p.appendChild(childNode);
}
} else if (p !== null) {
while (p.lastChild && this._isWhitespace(p.lastChild)) {
p.removeChild(p.lastChild);
}
p = null;
}
childNode = nextSibling;
}
// Sites like http://mobile.slate.com encloses each paragraph with a DIV
// element. DIVs with only a P element inside and no text content can be
// safely converted into plain P elements to avoid confusing the scoring
// algorithm with DIVs with are, in practice, paragraphs.
if (this._hasSingleTagInsideElement(node, "P") && this._getLinkDensity(node) < 0.25) {
var newNode = node.children[0];
node.parentNode.replaceChild(newNode, node);
node = newNode;
elementsToScore.push(node);
} else if (!this._hasChildBlockElement(node)) {
node = this._setNodeTag(node, "P");
elementsToScore.push(node);
}
}
node = this._getNextNode(node);
}
/**
* Loop through all paragraphs, and assign a score to them based on how content-y they look.
* Then add their score to their parent node.
*
* A score is determined by things like number of commas, class names, etc. Maybe eventually link density.
**/
var candidates = [];
this._forEachNode(elementsToScore, function(elementToScore) {
if (!elementToScore.parentNode || typeof(elementToScore.parentNode.tagName) === "undefined")
return;
// If this paragraph is less than 25 characters, don't even count it.
var innerText = this._getInnerText(elementToScore);
if (innerText.length < 25)
return;
// Exclude nodes with no ancestor.
var ancestors = this._getNodeAncestors(elementToScore, 5);
if (ancestors.length === 0)
return;
var contentScore = 0;
// Add a point for the paragraph itself as a base.
contentScore += 1;
// Add points for any commas within this paragraph.
contentScore += innerText.split(this.REGEXPS.commas).length;
// For every 100 characters in this paragraph, add another point. Up to 3 points.
contentScore += Math.min(Math.floor(innerText.length / 100), 3);
// Initialize and score ancestors.
this._forEachNode(ancestors, function(ancestor, level) {
if (!ancestor.tagName || !ancestor.parentNode || typeof(ancestor.parentNode.tagName) === "undefined")
return;
if (typeof(ancestor.readability) === "undefined") {
this._initializeNode(ancestor);
candidates.push(ancestor);
}
// Node score divider:
// - parent: 1 (no division)
// - grandparent: 2
// - great grandparent+: ancestor level * 3
if (level === 0)
var scoreDivider = 1;
else if (level === 1)
scoreDivider = 2;
else
scoreDivider = level * 3;
ancestor.readability.contentScore += contentScore / scoreDivider;
});
});
// After we've calculated scores, loop through all of the possible
// candidate nodes we found and find the one with the highest score.
var topCandidates = [];
for (var c = 0, cl = candidates.length; c < cl; c += 1) {
var candidate = candidates[c];
// Scale the final candidates score based on link density. Good content
// should have a relatively small link density (5% or less) and be mostly
// unaffected by this operation.
var candidateScore = candidate.readability.contentScore * (1 - this._getLinkDensity(candidate));
candidate.readability.contentScore = candidateScore;
this.log("Candidate:", candidate, "with score " + candidateScore);
for (var t = 0; t < this._nbTopCandidates; t++) {
var aTopCandidate = topCandidates[t];
if (!aTopCandidate || candidateScore > aTopCandidate.readability.contentScore) {
topCandidates.splice(t, 0, candidate);
if (topCandidates.length > this._nbTopCandidates)
topCandidates.pop();
break;
}
}
}
var topCandidate = topCandidates[0] || null;
var neededToCreateTopCandidate = false;
var parentOfTopCandidate;
// If we still have no top candidate, just use the body as a last resort.
// We also have to copy the body node so it is something we can modify.
if (topCandidate === null || topCandidate.tagName === "BODY") {
// Move all of the page's children into topCandidate
topCandidate = doc.createElement("DIV");
neededToCreateTopCandidate = true;
// Move everything (not just elements, also text nodes etc.) into the container
// so we even include text directly in the body:
while (page.firstChild) {
this.log("Moving child out:", page.firstChild);
topCandidate.appendChild(page.firstChild);
}
page.appendChild(topCandidate);
this._initializeNode(topCandidate);
} else if (topCandidate) {
// Find a better top candidate node if it contains (at least three) nodes which belong to `topCandidates` array
// and whose scores are quite closed with current `topCandidate` node.
var alternativeCandidateAncestors = [];
for (var i = 1; i < topCandidates.length; i++) {
if (topCandidates[i].readability.contentScore / topCandidate.readability.contentScore >= 0.75) {
alternativeCandidateAncestors.push(this._getNodeAncestors(topCandidates[i]));
}
}
var MINIMUM_TOPCANDIDATES = 3;
if (alternativeCandidateAncestors.length >= MINIMUM_TOPCANDIDATES) {
parentOfTopCandidate = topCandidate.parentNode;
while (parentOfTopCandidate.tagName !== "BODY") {
var listsContainingThisAncestor = 0;
for (var ancestorIndex = 0; ancestorIndex < alternativeCandidateAncestors.length && listsContainingThisAncestor < MINIMUM_TOPCANDIDATES; ancestorIndex++) {
listsContainingThisAncestor += Number(alternativeCandidateAncestors[ancestorIndex].includes(parentOfTopCandidate));
}
if (listsContainingThisAncestor >= MINIMUM_TOPCANDIDATES) {
topCandidate = parentOfTopCandidate;
break;
}
parentOfTopCandidate = parentOfTopCandidate.parentNode;
}
}
if (!topCandidate.readability) {
this._initializeNode(topCandidate);
}
// Because of our bonus system, parents of candidates might have scores
// themselves. They get half of the node. There won't be nodes with higher
// scores than our topCandidate, but if we see the score going *up* in the first
// few steps up the tree, that's a decent sign that there might be more content
// lurking in other places that we want to unify in. The sibling stuff
// below does some of that - but only if we've looked high enough up the DOM
// tree.
parentOfTopCandidate = topCandidate.parentNode;
var lastScore = topCandidate.readability.contentScore;
// The scores shouldn't get too low.
var scoreThreshold = lastScore / 3;
while (parentOfTopCandidate.tagName !== "BODY") {
if (!parentOfTopCandidate.readability) {
parentOfTopCandidate = parentOfTopCandidate.parentNode;
continue;
}
var parentScore = parentOfTopCandidate.readability.contentScore;
if (parentScore < scoreThreshold)
break;
if (parentScore > lastScore) {
// Alright! We found a better parent to use.
topCandidate = parentOfTopCandidate;
break;
}
lastScore = parentOfTopCandidate.readability.contentScore;
parentOfTopCandidate = parentOfTopCandidate.parentNode;
}
// If the top candidate is the only child, use parent instead. This will help sibling
// joining logic when adjacent content is actually located in parent's sibling node.
parentOfTopCandidate = topCandidate.parentNode;
while (parentOfTopCandidate.tagName != "BODY" && parentOfTopCandidate.children.length == 1) {
topCandidate = parentOfTopCandidate;
parentOfTopCandidate = topCandidate.parentNode;
}
if (!topCandidate.readability) {
this._initializeNode(topCandidate);
}
}
// Now that we have the top candidate, look through its siblings for content
// that might also be related. Things like preambles, content split by ads
// that we removed, etc.
var articleContent = doc.createElement("DIV");
if (isPaging)
articleContent.id = "readability-content";
var siblingScoreThreshold = Math.max(10, topCandidate.readability.contentScore * 0.2);
// Keep potential top candidate's parent node to try to get text direction of it later.
parentOfTopCandidate = topCandidate.parentNode;
var siblings = parentOfTopCandidate.children;
for (var s = 0, sl = siblings.length; s < sl; s++) {
var sibling = siblings[s];
var append = false;
this.log("Looking at sibling node:", sibling, sibling.readability ? ("with score " + sibling.readability.contentScore) : "");
this.log("Sibling has score", sibling.readability ? sibling.readability.contentScore : "Unknown");
if (sibling === topCandidate) {
append = true;
} else {
var contentBonus = 0;
// Give a bonus if sibling nodes and top candidates have the example same classname
if (sibling.className === topCandidate.className && topCandidate.className !== "")
contentBonus += topCandidate.readability.contentScore * 0.2;
if (sibling.readability &&
((sibling.readability.contentScore + contentBonus) >= siblingScoreThreshold)) {
append = true;
} else if (sibling.nodeName === "P") {
var linkDensity = this._getLinkDensity(sibling);
var nodeContent = this._getInnerText(sibling);
var nodeLength = nodeContent.length;
if (nodeLength > 80 && linkDensity < 0.25) {
append = true;
} else if (nodeLength < 80 && nodeLength > 0 && linkDensity === 0 &&
nodeContent.search(/\.( |$)/) !== -1) {
append = true;
}
}
}
if (append) {
this.log("Appending node:", sibling);
if (this.ALTER_TO_DIV_EXCEPTIONS.indexOf(sibling.nodeName) === -1) {
// We have a node that isn't a common block level element, like a form or td tag.
// Turn it into a div so it doesn't get filtered out later by accident.
this.log("Altering sibling:", sibling, "to div.");
sibling = this._setNodeTag(sibling, "DIV");
}
articleContent.appendChild(sibling);
// Fetch children again to make it compatible
// with DOM parsers without live collection support.
siblings = parentOfTopCandidate.children;
// siblings is a reference to the children array, and
// sibling is removed from the array when we call appendChild().
// As a result, we must revisit this index since the nodes
// have been shifted.
s -= 1;
sl -= 1;
}
}
if (this._debug)
this.log("Article content pre-prep: " + articleContent.innerHTML);
// So we have all of the content that we need. Now we clean it up for presentation.
this._prepArticle(articleContent);
if (this._debug)
this.log("Article content post-prep: " + articleContent.innerHTML);
if (neededToCreateTopCandidate) {
// We already created a fake div thing, and there wouldn't have been any siblings left
// for the previous loop, so there's no point trying to create a new div, and then
// move all the children over. Just assign IDs and class names here. No need to append
// because that already happened anyway.
topCandidate.id = "readability-page-1";
topCandidate.className = "page";
} else {
var div = doc.createElement("DIV");
div.id = "readability-page-1";
div.className = "page";
while (articleContent.firstChild) {
div.appendChild(articleContent.firstChild);
}
articleContent.appendChild(div);
}
if (this._debug)
this.log("Article content after paging: " + articleContent.innerHTML);
var parseSuccessful = true;
// Now that we've gone through the full algorithm, check to see if
// we got any meaningful content. If we didn't, we may need to re-run
// grabArticle with different flags set. This gives us a higher likelihood of
// finding the content, and the sieve approach gives us a higher likelihood of
// finding the -right- content.
var textLength = this._getInnerText(articleContent, true).length;
if (textLength < this._charThreshold) {
parseSuccessful = false;
page.innerHTML = pageCacheHtml;
if (this._flagIsActive(this.FLAG_STRIP_UNLIKELYS)) {
this._removeFlag(this.FLAG_STRIP_UNLIKELYS);
this._attempts.push({articleContent: articleContent, textLength: textLength});
} else if (this._flagIsActive(this.FLAG_WEIGHT_CLASSES)) {
this._removeFlag(this.FLAG_WEIGHT_CLASSES);
this._attempts.push({articleContent: articleContent, textLength: textLength});
} else if (this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY)) {
this._removeFlag(this.FLAG_CLEAN_CONDITIONALLY);
this._attempts.push({articleContent: articleContent, textLength: textLength});
} else {
this._attempts.push({articleContent: articleContent, textLength: textLength});
// No luck after removing flags, just return the longest text we found during the different loops
this._attempts.sort(function (a, b) {
return b.textLength - a.textLength;
});
// But first check if we actually have something
if (!this._attempts[0].textLength) {
return null;
}
articleContent = this._attempts[0].articleContent;
parseSuccessful = true;
}
}
if (parseSuccessful) {
// Find out text direction from ancestors of final top candidate.
var ancestors = [parentOfTopCandidate, topCandidate].concat(this._getNodeAncestors(parentOfTopCandidate));
this._someNode(ancestors, function(ancestor) {
if (!ancestor.tagName)
return false;
var articleDir = ancestor.getAttribute("dir");
if (articleDir) {
this._articleDir = articleDir;
return true;
}
return false;
});
return articleContent;
}
}
},
/**
* Check whether the input string could be a byline.
* This verifies that the input is a string, and that the length
* is less than 100 chars.
*
* @param possibleByline {string} - a string to check whether its a byline.
* @return Boolean - whether the input string is a byline.
*/
_isValidByline: function(byline) {
if (typeof byline == "string" || byline instanceof String) {
byline = byline.trim();
return (byline.length > 0) && (byline.length < 100);
}
return false;
},
/**
* Converts some of the common HTML entities in string to their corresponding characters.
*
* @param str {string} - a string to unescape.
* @return string without HTML entity.
*/
_unescapeHtmlEntities: function(str) {
if (!str) {
return str;
}
var htmlEscapeMap = this.HTML_ESCAPE_MAP;
return str.replace(/&(quot|amp|apos|lt|gt);/g, function(_, tag) {
return htmlEscapeMap[tag];
}).replace(/&#(?:x([0-9a-z]{1,4})|([0-9]{1,4}));/gi, function(_, hex, numStr) {
var num = parseInt(hex || numStr, hex ? 16 : 10);
return String.fromCharCode(num);
});
},
/**
* Try to extract metadata from JSON-LD object.
* For now, only Schema.org objects of type Article or its subtypes are supported.
* @return Object with any metadata that could be extracted (possibly none)
*/
_getJSONLD: function (doc) {
var scripts = this._getAllNodesWithTag(doc, ["script"]);
var metadata;
this._forEachNode(scripts, function(jsonLdElement) {
if (!metadata && jsonLdElement.getAttribute("type") === "application/ld+json") {
try {
// Strip CDATA markers if present
var content = jsonLdElement.textContent.replace(/^\s*<!\[CDATA\[|\]\]>\s*$/g, "");
var parsed = JSON.parse(content);
if (
!parsed["@context"] ||
!parsed["@context"].match(/^https?\:\/\/schema\.org$/)
) {
return;
}
if (!parsed["@type"] && Array.isArray(parsed["@graph"])) {
parsed = parsed["@graph"].find(function(it) {
return (it["@type"] || "").match(
this.REGEXPS.jsonLdArticleTypes
);
});
}
if (
!parsed ||
!parsed["@type"] ||
!parsed["@type"].match(this.REGEXPS.jsonLdArticleTypes)
) {
return;
}
metadata = {};
if (typeof parsed.name === "string" && typeof parsed.headline === "string" && parsed.name !== parsed.headline) {
// we have both name and headline element in the JSON-LD. They should both be the same but some websites like aktualne.cz
// put their own name into "name" and the article title to "headline" which confuses Readability. So we try to check if either
// "name" or "headline" closely matches the html title, and if so, use that one. If not, then we use "name" by default.
var title = this._getArticleTitle();
var nameMatches = this._textSimilarity(parsed.name, title) > 0.75;
var headlineMatches = this._textSimilarity(parsed.headline, title) > 0.75;
if (headlineMatches && !nameMatches) {
metadata.title = parsed.headline;
} else {
metadata.title = parsed.name;
}
} else if (typeof parsed.name === "string") {
metadata.title = parsed.name.trim();
} else if (typeof parsed.headline === "string") {
metadata.title = parsed.headline.trim();
}
if (parsed.author) {
if (typeof parsed.author.name === "string") {
metadata.byline = parsed.author.name.trim();
} else if (Array.isArray(parsed.author) && parsed.author[0] && typeof parsed.author[0].name === "string") {
metadata.byline = parsed.author
.filter(function(author) {
return author && typeof author.name === "string";
})
.map(function(author) {
return author.name.trim();
})
.join(", ");
}
}
if (typeof parsed.description === "string") {
metadata.excerpt = parsed.description.trim();
}
if (
parsed.publisher &&
typeof parsed.publisher.name === "string"
) {
metadata.siteName = parsed.publisher.name.trim();
}
if (typeof parsed.datePublished === "string") {
metadata.datePublished = parsed.datePublished.trim();
}
return;
} catch (err) {
this.log(err.message);
}
}
});
return metadata ? metadata : {};
},
/**
* Attempts to get excerpt and byline metadata for the article.
*
* @param {Object} jsonld — object containing any metadata that
* could be extracted from JSON-LD object.
*
* @return Object with optional "excerpt" and "byline" properties
*/
_getArticleMetadata: function(jsonld) {
var metadata = {};
var values = {};
var metaElements = this._doc.getElementsByTagName("meta");
// property is a space-separated list of values
var propertyPattern = /\s*(article|dc|dcterm|og|twitter)\s*:\s*(author|creator|description|published_time|title|site_name)\s*/gi;
// name is a single value
var namePattern = /^\s*(?:(dc|dcterm|og|twitter|weibo:(article|webpage))\s*[\.:]\s*)?(author|creator|description|title|site_name)\s*$/i;
// Find description tags.
this._forEachNode(metaElements, function(element) {
var elementName = element.getAttribute("name");
var elementProperty = element.getAttribute("property");
var content = element.getAttribute("content");
if (!content) {
return;
}
var matches = null;
var name = null;
if (elementProperty) {
matches = elementProperty.match(propertyPattern);
if (matches) {
// Convert to lowercase, and remove any whitespace
// so we can match below.
name = matches[0].toLowerCase().replace(/\s/g, "");
// multiple authors
values[name] = content.trim();
}
}
if (!matches && elementName && namePattern.test(elementName)) {
name = elementName;
if (content) {
// Convert to lowercase, remove any whitespace, and convert dots
// to colons so we can match below.
name = name.toLowerCase().replace(/\s/g, "").replace(/\./g, ":");
values[name] = content.trim();
}
}
});
// get title
metadata.title = jsonld.title ||
values["dc:title"] ||
values["dcterm:title"] ||
values["og:title"] ||
values["weibo:article:title"] ||
values["weibo:webpage:title"] ||
values["title"] ||
values["twitter:title"];
if (!metadata.title) {
metadata.title = this._getArticleTitle();
}
// get author
metadata.byline = jsonld.byline ||
values["dc:creator"] ||
values["dcterm:creator"] ||
values["author"];
// get description
metadata.excerpt = jsonld.excerpt ||
values["dc:description"] ||
values["dcterm:description"] ||
values["og:description"] ||
values["weibo:article:description"] ||
values["weibo:webpage:description"] ||
values["description"] ||
values["twitter:description"];
// get site name
metadata.siteName = jsonld.siteName ||
values["og:site_name"];
// get article published time
metadata.publishedTime = jsonld.datePublished ||
values["article:published_time"] || null;
// in many sites the meta value is escaped with HTML entities,
// so here we need to unescape it
metadata.title = this._unescapeHtmlEntities(metadata.title);
metadata.byline = this._unescapeHtmlEntities(metadata.byline);
metadata.excerpt = this._unescapeHtmlEntities(metadata.excerpt);
metadata.siteName = this._unescapeHtmlEntities(metadata.siteName);
metadata.publishedTime = this._unescapeHtmlEntities(metadata.publishedTime);
return metadata;
},
/**
* Check if node is image, or if node contains exactly only one image
* whether as a direct child or as its descendants.
*
* @param Element
**/
_isSingleImage: function(node) {
if (node.tagName === "IMG") {
return true;
}
if (node.children.length !== 1 || node.textContent.trim() !== "") {
return false;
}
return this._isSingleImage(node.children[0]);
},
/**
* Find all <noscript> that are located after <img> nodes, and which contain only one
* <img> element. Replace the first image with the image from inside the <noscript> tag,
* and remove the <noscript> tag. This improves the quality of the images we use on
* some sites (e.g. Medium).
*
* @param Element
**/
_unwrapNoscriptImages: function(doc) {
// Find img without source or attributes that might contains image, and remove it.
// This is done to prevent a placeholder img is replaced by img from noscript in next step.
var imgs = Array.from(doc.getElementsByTagName("img"));
this._forEachNode(imgs, function(img) {
for (var i = 0; i < img.attributes.length; i++) {
var attr = img.attributes[i];
switch (attr.name) {
case "src":
case "srcset":
case "data-src":
case "data-srcset":
return;
}
if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
return;
}
}
img.parentNode.removeChild(img);
});
// Next find noscript and try to extract its image
var noscripts = Array.from(doc.getElementsByTagName("noscript"));
this._forEachNode(noscripts, function(noscript) {
// Parse content of noscript and make sure it only contains image
var tmp = doc.createElement("div");
tmp.innerHTML = noscript.innerHTML;
if (!this._isSingleImage(tmp)) {
return;
}
// If noscript has previous sibling and it only contains image,
// replace it with noscript content. However we also keep old
// attributes that might contains image.
var prevElement = noscript.previousElementSibling;
if (prevElement && this._isSingleImage(prevElement)) {
var prevImg = prevElement;
if (prevImg.tagName !== "IMG") {
prevImg = prevElement.getElementsByTagName("img")[0];
}
var newImg = tmp.getElementsByTagName("img")[0];
for (var i = 0; i < prevImg.attributes.length; i++) {
var attr = prevImg.attributes[i];
if (attr.value === "") {
continue;
}
if (attr.name === "src" || attr.name === "srcset" || /\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
if (newImg.getAttribute(attr.name) === attr.value) {
continue;
}
var attrName = attr.name;
if (newImg.hasAttribute(attrName)) {
attrName = "data-old-" + attrName;
}
newImg.setAttribute(attrName, attr.value);
}
}
noscript.parentNode.replaceChild(tmp.firstElementChild, prevElement);
}
});
},
/**
* Removes script tags from the document.
*
* @param Element
**/
_removeScripts: function(doc) {
this._removeNodes(this._getAllNodesWithTag(doc, ["script", "noscript"]));
},
/**
* Check if this node has only whitespace and a single element with given tag
* Returns false if the DIV node contains non-empty text nodes
* or if it contains no element with given tag or more than 1 element.
*
* @param Element
* @param string tag of child element
**/
_hasSingleTagInsideElement: function(element, tag) {
// There should be exactly 1 element child with given tag
if (element.children.length != 1 || element.children[0].tagName !== tag) {
return false;
}
// And there should be no text nodes with real content
return !this._someNode(element.childNodes, function(node) {
return node.nodeType === this.TEXT_NODE &&
this.REGEXPS.hasContent.test(node.textContent);
});
},
_isElementWithoutContent: function(node) {
return node.nodeType === this.ELEMENT_NODE &&
node.textContent.trim().length == 0 &&
(node.children.length == 0 ||
node.children.length == node.getElementsByTagName("br").length + node.getElementsByTagName("hr").length);
},
/**
* Determine whether element has any children block level elements.
*
* @param Element
*/
_hasChildBlockElement: function (element) {
return this._someNode(element.childNodes, function(node) {
return this.DIV_TO_P_ELEMS.has(node.tagName) ||
this._hasChildBlockElement(node);
});
},
/***
* Determine if a node qualifies as phrasing content.
* https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content
**/
_isPhrasingContent: function(node) {
return node.nodeType === this.TEXT_NODE || this.PHRASING_ELEMS.indexOf(node.tagName) !== -1 ||
((node.tagName === "A" || node.tagName === "DEL" || node.tagName === "INS") &&
this._everyNode(node.childNodes, this._isPhrasingContent));
},
_isWhitespace: function(node) {
return (node.nodeType === this.TEXT_NODE && node.textContent.trim().length === 0) ||
(node.nodeType === this.ELEMENT_NODE && node.tagName === "BR");
},
/**
* Get the inner text of a node - cross browser compatibly.
* This also strips out any excess whitespace to be found.
*
* @param Element
* @param Boolean normalizeSpaces (default: true)
* @return string
**/
_getInnerText: function(e, normalizeSpaces) {
normalizeSpaces = (typeof normalizeSpaces === "undefined") ? true : normalizeSpaces;
var textContent = e.textContent.trim();
if (normalizeSpaces) {
return textContent.replace(this.REGEXPS.normalize, " ");
}
return textContent;
},
/**
* Get the number of times a string s appears in the node e.
*
* @param Element
* @param string - what to split on. Default is ","
* @return number (integer)
**/
_getCharCount: function(e, s) {
s = s || ",";
return this._getInnerText(e).split(s).length - 1;
},
/**
* Remove the style attribute on every e and under.
* TODO: Test if getElementsByTagName(*) is faster.
*
* @param Element
* @return void
**/
_cleanStyles: function(e) {
if (!e || e.tagName.toLowerCase() === "svg")
return;
// Remove `style` and deprecated presentational attributes
for (var i = 0; i < this.PRESENTATIONAL_ATTRIBUTES.length; i++) {
e.removeAttribute(this.PRESENTATIONAL_ATTRIBUTES[i]);
}
if (this.DEPRECATED_SIZE_ATTRIBUTE_ELEMS.indexOf(e.tagName) !== -1) {
e.removeAttribute("width");
e.removeAttribute("height");
}
var cur = e.firstElementChild;
while (cur !== null) {
this._cleanStyles(cur);
cur = cur.nextElementSibling;
}
},
/**
* Get the density of links as a percentage of the content
* This is the amount of text that is inside a link divided by the total text in the node.
*
* @param Element
* @return number (float)
**/
_getLinkDensity: function(element) {
var textLength = this._getInnerText(element).length;
if (textLength === 0)
return 0;
var linkLength = 0;
// XXX implement _reduceNodeList?
this._forEachNode(element.getElementsByTagName("a"), function(linkNode) {
var href = linkNode.getAttribute("href");
var coefficient = href && this.REGEXPS.hashUrl.test(href) ? 0.3 : 1;
linkLength += this._getInnerText(linkNode).length * coefficient;
});
return linkLength / textLength;
},
/**
* Get an elements class/id weight. Uses regular expressions to tell if this
* element looks good or bad.
*
* @param Element
* @return number (Integer)
**/
_getClassWeight: function(e) {
if (!this._flagIsActive(this.FLAG_WEIGHT_CLASSES))
return 0;
var weight = 0;
// Look for a special classname
if (typeof(e.className) === "string" && e.className !== "") {
if (this.REGEXPS.negative.test(e.className))
weight -= 25;
if (this.REGEXPS.positive.test(e.className))
weight += 25;
}
// Look for a special ID
if (typeof(e.id) === "string" && e.id !== "") {
if (this.REGEXPS.negative.test(e.id))
weight -= 25;
if (this.REGEXPS.positive.test(e.id))
weight += 25;
}
return weight;
},
/**
* Clean a node of all elements of type "tag".
* (Unless it's a youtube/vimeo video. People love movies.)
*
* @param Element
* @param string tag to clean
* @return void
**/
_clean: function(e, tag) {
var isEmbed = ["object", "embed", "iframe"].indexOf(tag) !== -1;
this._removeNodes(this._getAllNodesWithTag(e, [tag]), function(element) {
// Allow youtube and vimeo videos through as people usually want to see those.
if (isEmbed) {
// First, check the elements attributes to see if any of them contain youtube or vimeo
for (var i = 0; i < element.attributes.length; i++) {
if (this._allowedVideoRegex.test(element.attributes[i].value)) {
return false;
}
}
// For embed with <object> tag, check inner HTML as well.
if (element.tagName === "object" && this._allowedVideoRegex.test(element.innerHTML)) {
return false;
}
}
return true;
});
},
/**
* Check if a given node has one of its ancestor tag name matching the
* provided one.
* @param HTMLElement node
* @param String tagName
* @param Number maxDepth
* @param Function filterFn a filter to invoke to determine whether this node 'counts'
* @return Boolean
*/
_hasAncestorTag: function(node, tagName, maxDepth, filterFn) {
maxDepth = maxDepth || 3;
tagName = tagName.toUpperCase();
var depth = 0;
while (node.parentNode) {
if (maxDepth > 0 && depth > maxDepth)
return false;
if (node.parentNode.tagName === tagName && (!filterFn || filterFn(node.parentNode)))
return true;
node = node.parentNode;
depth++;
}
return false;
},
/**
* Return an object indicating how many rows and columns this table has.
*/
_getRowAndColumnCount: function(table) {
var rows = 0;
var columns = 0;
var trs = table.getElementsByTagName("tr");
for (var i = 0; i < trs.length; i++) {
var rowspan = trs[i].getAttribute("rowspan") || 0;
if (rowspan) {
rowspan = parseInt(rowspan, 10);
}
rows += (rowspan || 1);
// Now look for column-related info
var columnsInThisRow = 0;
var cells = trs[i].getElementsByTagName("td");
for (var j = 0; j < cells.length; j++) {
var colspan = cells[j].getAttribute("colspan") || 0;
if (colspan) {
colspan = parseInt(colspan, 10);
}
columnsInThisRow += (colspan || 1);
}
columns = Math.max(columns, columnsInThisRow);
}
return {rows: rows, columns: columns};
},
/**
* Look for 'data' (as opposed to 'layout') tables, for which we use
* similar checks as
* https://searchfox.org/mozilla-central/rev/f82d5c549f046cb64ce5602bfd894b7ae807c8f8/accessible/generic/TableAccessible.cpp#19
*/
_markDataTables: function(root) {
var tables = root.getElementsByTagName("table");
for (var i = 0; i < tables.length; i++) {
var table = tables[i];
var role = table.getAttribute("role");
if (role == "presentation") {
table._readabilityDataTable = false;
continue;
}
var datatable = table.getAttribute("datatable");
if (datatable == "0") {
table._readabilityDataTable = false;
continue;
}
var summary = table.getAttribute("summary");
if (summary) {
table._readabilityDataTable = true;
continue;
}
var caption = table.getElementsByTagName("caption")[0];
if (caption && caption.childNodes.length > 0) {
table._readabilityDataTable = true;
continue;
}
// If the table has a descendant with any of these tags, consider a data table:
var dataTableDescendants = ["col", "colgroup", "tfoot", "thead", "th"];
var descendantExists = function(tag) {
return !!table.getElementsByTagName(tag)[0];
};
if (dataTableDescendants.some(descendantExists)) {
this.log("Data table because found data-y descendant");
table._readabilityDataTable = true;
continue;
}
// Nested tables indicate a layout table:
if (table.getElementsByTagName("table")[0]) {
table._readabilityDataTable = false;
continue;
}
var sizeInfo = this._getRowAndColumnCount(table);
if (sizeInfo.rows >= 10 || sizeInfo.columns > 4) {
table._readabilityDataTable = true;
continue;
}
// Now just go by size entirely:
table._readabilityDataTable = sizeInfo.rows * sizeInfo.columns > 10;
}
},
/* convert images and figures that have properties like data-src into images that can be loaded without JS */
_fixLazyImages: function (root) {
this._forEachNode(this._getAllNodesWithTag(root, ["img", "picture", "figure"]), function (elem) {
// In some sites (e.g. Kotaku), they put 1px square image as base64 data uri in the src attribute.
// So, here we check if the data uri is too short, just might as well remove it.
if (elem.src && this.REGEXPS.b64DataUrl.test(elem.src)) {
// Make sure it's not SVG, because SVG can have a meaningful image in under 133 bytes.
var parts = this.REGEXPS.b64DataUrl.exec(elem.src);
if (parts[1] === "image/svg+xml") {
return;
}
// Make sure this element has other attributes which contains image.
// If it doesn't, then this src is important and shouldn't be removed.
var srcCouldBeRemoved = false;
for (var i = 0; i < elem.attributes.length; i++) {
var attr = elem.attributes[i];
if (attr.name === "src") {
continue;
}
if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
srcCouldBeRemoved = true;
break;
}
}
// Here we assume if image is less than 100 bytes (or 133B after encoded to base64)
// it will be too small, therefore it might be placeholder image.
if (srcCouldBeRemoved) {
var b64starts = elem.src.search(/base64\s*/i) + 7;
var b64length = elem.src.length - b64starts;
if (b64length < 133) {
elem.removeAttribute("src");
}
}
}
// also check for "null" to work around https://github.com/jsdom/jsdom/issues/2580
if ((elem.src || (elem.srcset && elem.srcset != "null")) && elem.className.toLowerCase().indexOf("lazy") === -1) {
return;
}
for (var j = 0; j < elem.attributes.length; j++) {
attr = elem.attributes[j];
if (attr.name === "src" || attr.name === "srcset" || attr.name === "alt") {
continue;
}
var copyTo = null;
if (/\.(jpg|jpeg|png|webp)\s+\d/.test(attr.value)) {
copyTo = "srcset";
} else if (/^\s*\S+\.(jpg|jpeg|png|webp)\S*\s*$/.test(attr.value)) {
copyTo = "src";
}
if (copyTo) {
//if this is an img or picture, set the attribute directly
if (elem.tagName === "IMG" || elem.tagName === "PICTURE") {
elem.setAttribute(copyTo, attr.value);
} else if (elem.tagName === "FIGURE" && !this._getAllNodesWithTag(elem, ["img", "picture"]).length) {
//if the item is a <figure> that does not contain an image or picture, create one and place it inside the figure
//see the nytimes-3 testcase for an example
var img = this._doc.createElement("img");
img.setAttribute(copyTo, attr.value);
elem.appendChild(img);
}
}
}
});
},
_getTextDensity: function(e, tags) {
var textLength = this._getInnerText(e, true).length;
if (textLength === 0) {
return 0;
}
var childrenLength = 0;
var children = this._getAllNodesWithTag(e, tags);
this._forEachNode(children, (child) => childrenLength += this._getInnerText(child, true).length);
return childrenLength / textLength;
},
/**
* Clean an element of all tags of type "tag" if they look fishy.
* "Fishy" is an algorithm based on content length, classnames, link density, number of images & embeds, etc.
*
* @return void
**/
_cleanConditionally: function(e, tag) {
if (!this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY))
return;
// Gather counts for other typical elements embedded within.
// Traverse backwards so we can remove nodes at the same time
// without effecting the traversal.
//
// TODO: Consider taking into account original contentScore here.
this._removeNodes(this._getAllNodesWithTag(e, [tag]), function(node) {
// First check if this node IS data table, in which case don't remove it.
var isDataTable = function(t) {
return t._readabilityDataTable;
};
var isList = tag === "ul" || tag === "ol";
if (!isList) {
var listLength = 0;
var listNodes = this._getAllNodesWithTag(node, ["ul", "ol"]);
this._forEachNode(listNodes, (list) => listLength += this._getInnerText(list).length);
isList = listLength / this._getInnerText(node).length > 0.9;
}
if (tag === "table" && isDataTable(node)) {
return false;
}
// Next check if we're inside a data table, in which case don't remove it as well.
if (this._hasAncestorTag(node, "table", -1, isDataTable)) {
return false;
}
if (this._hasAncestorTag(node, "code")) {
return false;
}
var weight = this._getClassWeight(node);
this.log("Cleaning Conditionally", node);
var contentScore = 0;
if (weight + contentScore < 0) {
return true;
}
if (this._getCharCount(node, ",") < 10) {
// If there are not very many commas, and the number of
// non-paragraph elements is more than paragraphs or other
// ominous signs, remove the element.
var p = node.getElementsByTagName("p").length;
var img = node.getElementsByTagName("img").length;
var li = node.getElementsByTagName("li").length - 100;
var input = node.getElementsByTagName("input").length;
var headingDensity = this._getTextDensity(node, ["h1", "h2", "h3", "h4", "h5", "h6"]);
var embedCount = 0;
var embeds = this._getAllNodesWithTag(node, ["object", "embed", "iframe"]);
for (var i = 0; i < embeds.length; i++) {
// If this embed has attribute that matches video regex, don't delete it.
for (var j = 0; j < embeds[i].attributes.length; j++) {
if (this._allowedVideoRegex.test(embeds[i].attributes[j].value)) {
return false;
}
}
// For embed with <object> tag, check inner HTML as well.
if (embeds[i].tagName === "object" && this._allowedVideoRegex.test(embeds[i].innerHTML)) {
return false;
}
embedCount++;
}
var linkDensity = this._getLinkDensity(node);
var contentLength = this._getInnerText(node).length;
var haveToRemove =
(img > 1 && p / img < 0.5 && !this._hasAncestorTag(node, "figure")) ||
(!isList && li > p) ||
(input > Math.floor(p/3)) ||
(!isList && headingDensity < 0.9 && contentLength < 25 && (img === 0 || img > 2) && !this._hasAncestorTag(node, "figure")) ||
(!isList && weight < 25 && linkDensity > 0.2) ||
(weight >= 25 && linkDensity > 0.5) ||
((embedCount === 1 && contentLength < 75) || embedCount > 1);
// Allow simple lists of images to remain in pages
if (isList && haveToRemove) {
for (var x = 0; x < node.children.length; x++) {
let child = node.children[x];
// Don't filter in lists with li's that contain more than one child
if (child.children.length > 1) {
return haveToRemove;
}
}
let li_count = node.getElementsByTagName("li").length;
// Only allow the list to remain if every li contains an image
if (img == li_count) {
return false;
}
}
return haveToRemove;
}
return false;
});
},
/**
* Clean out elements that match the specified conditions
*
* @param Element
* @param Function determines whether a node should be removed
* @return void
**/
_cleanMatchedNodes: function(e, filter) {
var endOfSearchMarkerNode = this._getNextNode(e, true);
var next = this._getNextNode(e);
while (next && next != endOfSearchMarkerNode) {
if (filter.call(this, next, next.className + " " + next.id)) {
next = this._removeAndGetNext(next);
} else {
next = this._getNextNode(next);
}
}
},
/**
* Clean out spurious headers from an Element.
*
* @param Element
* @return void
**/
_cleanHeaders: function(e) {
let headingNodes = this._getAllNodesWithTag(e, ["h1", "h2"]);
this._removeNodes(headingNodes, function(node) {
let shouldRemove = this._getClassWeight(node) < 0;
if (shouldRemove) {
this.log("Removing header with low class weight:", node);
}
return shouldRemove;
});
},
/**
* Check if this node is an H1 or H2 element whose content is mostly
* the same as the article title.
*
* @param Element the node to check.
* @return boolean indicating whether this is a title-like header.
*/
_headerDuplicatesTitle: function(node) {
if (node.tagName != "H1" && node.tagName != "H2") {
return false;
}
var heading = this._getInnerText(node, false);
this.log("Evaluating similarity of header:", heading, this._articleTitle);
return this._textSimilarity(this._articleTitle, heading) > 0.75;
},
_flagIsActive: function(flag) {
return (this._flags & flag) > 0;
},
_removeFlag: function(flag) {
this._flags = this._flags & ~flag;
},
_isProbablyVisible: function(node) {
// Have to null-check node.style and node.className.indexOf to deal with SVG and MathML nodes.
return (!node.style || node.style.display != "none")
&& (!node.style || node.style.visibility != "hidden")
&& !node.hasAttribute("hidden")
//check for "fallback-image" so that wikimedia math images are displayed
&& (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || (node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1));
},
/**
* Runs readability.
*
* Workflow:
* 1. Prep the document by removing script tags, css, etc.
* 2. Build readability's DOM tree.
* 3. Grab the article content from the current dom tree.
* 4. Replace the current DOM tree with the new one.
* 5. Read peacefully.
*
* @return void
**/
parse: function () {
// Avoid parsing too large documents, as per configuration option
if (this._maxElemsToParse > 0) {
var numTags = this._doc.getElementsByTagName("*").length;
if (numTags > this._maxElemsToParse) {
throw new Error("Aborting parsing document; " + numTags + " elements found");
}
}
// Unwrap image from noscript
this._unwrapNoscriptImages(this._doc);
// Extract JSON-LD metadata before removing scripts
var jsonLd = this._disableJSONLD ? {} : this._getJSONLD(this._doc);
// Remove script tags from the document.
this._removeScripts(this._doc);
this._prepDocument();
var metadata = this._getArticleMetadata(jsonLd);
this._articleTitle = metadata.title;
var articleContent = this._grabArticle();
if (!articleContent)
return null;
this.log("Grabbed: " + articleContent.innerHTML);
this._postProcessContent(articleContent);
// If we haven't found an excerpt in the article's metadata, use the article's
// first paragraph as the excerpt. This is used for displaying a preview of
// the article's content.
if (!metadata.excerpt) {
var paragraphs = articleContent.getElementsByTagName("p");
if (paragraphs.length > 0) {
metadata.excerpt = paragraphs[0].textContent.trim();
}
}
var textContent = articleContent.textContent;
return {
title: this._articleTitle,
byline: metadata.byline || this._articleByline,
dir: this._articleDir,
lang: this._articleLang,
content: this._serializer(articleContent),
textContent: textContent,
length: textContent.length,
excerpt: metadata.excerpt,
siteName: metadata.siteName || this._articleSiteName,
publishedTime: metadata.publishedTime
};
}
};
if (true) {
/* global module */
module.exports = Readability;
}
/***/ }),
/***/ "./node_modules/@mozilla/readability/index.js":
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/* eslint-env node */
var Readability = __webpack_require__("./node_modules/@mozilla/readability/Readability.js");
var isProbablyReaderable = __webpack_require__("./node_modules/@mozilla/readability/Readability-readerable.js");
module.exports = {
Readability: Readability,
isProbablyReaderable: isProbablyReaderable
};
/***/ }),
/***/ "./src/ui/ChapterList.less":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `:root {
--good-chapter-color: #41b883;
--bad-chapter-color: #e73838;
--warning-chapter-color: #ff9900;
}
div.chapter-list-loading {
padding-top: 5em;
padding-bottom: 5em;
text-align: center;
}
div.chapter-list {
max-height: 200px;
overflow-y: scroll;
}
div.chapter-list .section {
margin-top: 1.5em;
display: grid;
grid-template-columns: 32% 32% 32%;
}
div.chapter-list .section > h3:first-child {
grid-column-end: span 3;
text-align: center;
}
div.chapter-list .section > div.chapter {
text-align: center;
padding-top: 0.5em;
padding-bottom: 0.3em;
padding-left: 23px;
padding-right: 20px;
border: 1px solid #d9d9d9;
border-radius: 5px;
margin-left: 10px;
margin-top: 5px;
margin-right: 0;
margin-bottom: 0;
}
div.chapter-list .section a.disabled {
pointer-events: none;
cursor: default;
}
div.chapter-list .section a {
text-decoration: none;
}
div.chapter-list div.chapter.good {
background: var(--good-chapter-color);
}
div.chapter-list div.chapter.bad {
background: var(--bad-chapter-color);
}
div.chapter-list div.chapter.good.warning {
background: var(--warning-chapter-color);
}
div.chapter-list div.chapter.bad a,
div.chapter-list div.chapter.good a {
color: white;
font-size: 0.9em;
}
.nd-setting-body span.good {
color: var(--good-chapter-color);
}
.nd-setting-body span.bad {
color: var(--bad-chapter-color);
}
.nd-setting-body span.warning {
color: var(--warning-chapter-color);
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/ui/TestUI.less":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `#test-page-div {
max-height: 300px;
overflow-y: scroll;
}
#test-page-div table {
text-align: center;
}
#test-page-div td {
all: revert;
padding-top: 0.3em;
}
#test-page-div td > img {
max-height: 15em;
}
#test-page-div tr > td:nth-child(1) {
font-weight: bold;
min-width: 7em;
}
#test-page-div tr > td:nth-child(2) div,
#test-page-div tr > td:nth-child(2) p {
text-align: left;
}
#test-page-div hr {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
#test-page-div h2 {
text-align: center;
margin-bottom: 1.3em;
}
#test-page-div h4 {
text-align: center;
}
#test-page-div .chapter p {
line-height: 1.4;
}
#test-page-div .chapter img {
max-width: 95%;
}
#test-page-div .preview-chapter-setting {
text-align: center;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/ui/button.less":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `.button-div {
position: fixed;
top: 15%;
right: 5%;
z-index: 10000;
}
.button-div button {
border-style: none;
text-align: center;
vertical-align: baseline;
background-color: rgba(128, 128, 128, 0.2);
padding: 3px;
border-radius: 12px;
min-width: auto;
min-height: auto;
}
.button-div img.start,
.button-div img.jump {
height: 2em;
}
.button-div img.setting {
height: 1em;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/ui/setting.less":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `.nd-setting-body {
background: #e0e0e0;
padding: 1em;
border-top-right-radius: 3px;
}
.nd-setting-body hr {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
.nd-setting-body input[type="checkbox"],
.nd-setting-body input[type="radio"],
.nd-setting-body input[type="text"] {
position: static;
opacity: 1;
margin: auto;
padding: initial;
appearance: revert !important;
-webkit-appearance: revert !important;
all: revert;
}
dialog-ui .tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
color: black;
line-height: normal;
display: inline-block;
text-align: center;
font-weight: bold;
max-width: 9em;
box-sizing: initial;
}
dialog-ui .tab-button:hover {
background: #e0e0e0;
}
dialog-ui .tab-button.active {
background: #e0e0e0;
}
dialog-ui #nd-setting-tab-1 input + label {
all: revert;
}
dialog-ui #nd-setting-tab-2 select {
all: revert;
}
.nd-setting-footer {
background: #e0e0e0;
padding-bottom: 0.7em;
text-align: center;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
.nd-setting-footer > button {
all: revert;
}
/* 日志页面 */
#novel-downloader-log {
max-height: 300px;
overflow: scroll;
}
/* 彩色斜纹 来自:https://www.zhangxinxu.com/wordpress/2021/05/css-html-hr/ */
.hr-twill-colorful {
all: revert;
border: 0;
padding: 3px;
background: linear-gradient(135deg, red, orange, green, blue, purple);
--mask-image: repeating-linear-gradient(135deg, #000 0px, #000 1px, transparent 1px, transparent 6px);
-webkit-mask-image: var(--mask-image);
mask-image: var(--mask-image);
}
/* 两头虚 来自:https://www.zhangxinxu.com/wordpress/2021/05/css-html-hr/ */
.hr-edge-weak {
all: revert;
border: 0;
padding-top: 1px;
background: linear-gradient(to right, transparent, #d0d0d5, transparent);
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/save/main.css":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `h1 {
line-height: 130%;
text-align: center;
font-weight: bold;
font-size: xx-large;
margin-top: 3.2em;
margin-bottom: 3.3em;
}
h2 {
line-height: 130%;
text-align: center;
font-weight: bold;
font-size: x-large;
margin-top: 1.2em;
margin-bottom: 2.3em;
}
div {
margin: 0;
padding: 0;
text-align: justify;
}
p {
text-indent: 2em;
display: block;
line-height: 1.3em;
margin-top: 0.4em;
margin-bottom: 0.4em;
}
img {
vertical-align: text-bottom;
max-width: 90%;
}
.title {
margin-bottom: 0.7em;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/save/sgc-toc.css":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `div.sgc-toc-title {
font-size: 2em;
font-weight: bold;
margin-bottom: 1em;
text-align: center;
}
div.sgc-toc-level-1 {
margin-left: 0em;
}
div.sgc-toc-level-2 {
margin-left: 2em;
}
div.sgc-toc-level-3 {
margin-left: 2em;
}
div.sgc-toc-level-4 {
margin-left: 2em;
}
div.sgc-toc-level-5 {
margin-left: 2em;
}
div.sgc-toc-level-6 {
margin-left: 2em;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/save/toc.css":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `img {
max-width: 100%;
max-height: 15em;
}
.introduction {
font-size: smaller;
max-height: 18em;
overflow-y: scroll;
}
.introduction p {
text-indent: 0;
}
.bookurl {
text-align: center;
font-size: smaller;
padding-top: 1em;
padding-bottom: 0.5em;
margin-top: 0.4em;
}
.bookurl > a {
color: gray;
}
.info h3 {
padding-left: 0.5em;
margin-top: -1.2em;
margin-bottom: 0.5em;
}
.section {
margin-top: 1.5em;
display: grid;
grid-template-columns: 33% 33% 33%;
}
.section > h2:first-child {
grid-column-end: span 3;
}
.section > .chapter {
padding-bottom: 0.3em;
text-align: center;
}
.main > h1 {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
a.disabled {
pointer-events: none;
cursor: default;
color: gray;
}
.author::before {
content: "作者:";
}
.author {
text-align: center;
margin-top: -3em;
margin-bottom: 3em;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/save/web.css":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI",
"Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div.main {
width: 900px;
margin: 5em auto;
padding: 2em;
background-color: #fdfdff;
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0, 0, 0, 0.02);
}
@media (max-width: 700px) {
div.main {
margin: 0 auto;
width: auto;
}
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/ui/FilterTab.css":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `.filter-setting {
padding-top: 0.4em;
padding-bottom: 0.8em;
text-align: center;
}
.filter-input + .filter-setter {
margin-top: 1em;
}
.filter-description {
font-size: larger;
color: cornflowerblue;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/ui/dialog.css":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `.overlay {
visibility: hidden;
opacity: 0;
z-index: 100000;
position: fixed;
top: -50%;
left: -50%;
height: 200%;
width: 200%;
background-color: black;
}
.overlay.open {
opacity: 0.8;
visibility: visible;
transition: opacity 0.2s ease-in;
}
.overlay:not(.open) {
transition: visibility 0.2s step-end, opacity 0.2s ease-in;
}
.out {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 100001;
}
.dialog {
width: 720px;
max-height: 70%;
display: none;
opacity: 0;
z-index: 100100;
position: fixed;
margin: 0;
padding: 0;
}
.dialog.open {
opacity: 1;
display: block;
transition: opacity 0.2s ease-in;
}
.dialog > * {
box-sizing: border-box;
}
.dialog > .titlebar {
background-color: white;
min-height: 24px;
position: relative;
}
.dialog-title {
padding: 10px;
text-transform: uppercase;
background: #ff7bac;
color: #ffffff;
margin: 0;
font-size: 1.5em;
text-align: center;
}
.dialog-close {
background: #ff7bac;
color: #ffffff;
font-style: normal;
font-weight: 400;
font-variant: normal;
text-transform: none;
line-height: 1;
user-select: none;
cursor: pointer;
font-size: 120%;
margin: 0;
padding: 0;
width: 3.6em;
height: 92%;
border: 1px solid transparent;
transition-duration: 0.2s;
display: block;
position: absolute;
right: 0;
top: 0;
white-space: nowrap;
}
.dialog > .body {
background-color: white;
border: 1px solid rgb(255 125 175 / 80%);
text-align: left;
line-height: 1.5;
padding: 1em;
overflow: auto;
min-width: 280px;
height: calc(100% - 2.1em);
max-height: 900px;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./src/ui/progress.css":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/css-loader/dist/runtime/noSourceMaps.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/css-loader/dist/runtime/api.js");
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
// Imports
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `#nd-progress {
position: fixed;
bottom: 8%;
right: 3%;
z-index: 2147483647;
border-style: none;
text-align: center;
vertical-align: baseline;
background-color: rgba(210, 210, 210, 0.2);
padding: 6px;
border-radius: 12px;
}
#chapter-progress {
--color: green;
--position: 0%;
width: 200px;
height: 10px;
border-radius: 30px;
background-color: #ccc;
background-image: radial-gradient(
closest-side circle at var(--position),
var(--color),
var(--color) 100%,
transparent
),
linear-gradient(var(--color), var(--color));
background-image: -webkit-radial-gradient(
var(--position),
circle closest-side,
var(--color),
var(--color) 100%,
transparent
),
-webkit-linear-gradient(var(--color), var(--color));
background-size: 100%, var(--position);
background-repeat: no-repeat;
}
#zip-progress {
--color: yellow;
--position: 0%;
width: 200px;
height: 10px;
border-radius: 30px;
background-color: #ccc;
background-image: radial-gradient(
closest-side circle at var(--position),
var(--color),
var(--color) 100%,
transparent
),
linear-gradient(var(--color), var(--color));
background-image: -webkit-radial-gradient(
var(--position),
circle closest-side,
var(--color),
var(--color) 100%,
transparent
),
-webkit-linear-gradient(var(--color), var(--color));
background-size: 100%, var(--position);
background-repeat: no-repeat;
margin-top: 5px;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
/***/ }),
/***/ "./node_modules/css-loader/dist/runtime/api.js":
/***/ ((module) => {
"use strict";
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
module.exports = function (cssWithMappingToString) {
var list = [];
// return the list of modules as css string
list.toString = function toString() {
return this.map(function (item) {
var content = "";
var needLayer = typeof item[5] !== "undefined";
if (item[4]) {
content += "@supports (".concat(item[4], ") {");
}
if (item[2]) {
content += "@media ".concat(item[2], " {");
}
if (needLayer) {
content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {");
}
content += cssWithMappingToString(item);
if (needLayer) {
content += "}";
}
if (item[2]) {
content += "}";
}
if (item[4]) {
content += "}";
}
return content;
}).join("");
};
// import a list of modules into the list
list.i = function i(modules, media, dedupe, supports, layer) {
if (typeof modules === "string") {
modules = [[null, modules, undefined]];
}
var alreadyImportedModules = {};
if (dedupe) {
for (var k = 0; k < this.length; k++) {
var id = this[k][0];
if (id != null) {
alreadyImportedModules[id] = true;
}
}
}
for (var _k = 0; _k < modules.length; _k++) {
var item = [].concat(modules[_k]);
if (dedupe && alreadyImportedModules[item[0]]) {
continue;
}
if (typeof layer !== "undefined") {
if (typeof item[5] === "undefined") {
item[5] = layer;
} else {
item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}");
item[5] = layer;
}
}
if (media) {
if (!item[2]) {
item[2] = media;
} else {
item[1] = "@media ".concat(item[2], " {").concat(item[1], "}");
item[2] = media;
}
}
if (supports) {
if (!item[4]) {
item[4] = "".concat(supports);
} else {
item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}");
item[4] = supports;
}
}
list.push(item);
}
};
return list;
};
/***/ }),
/***/ "./node_modules/css-loader/dist/runtime/noSourceMaps.js":
/***/ ((module) => {
"use strict";
module.exports = function (i) {
return i[1];
};
/***/ }),
/***/ "./node_modules/file-saver/dist/FileSaver.min.js":
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(a,b){if(true)!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (b),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));else {}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof __webpack_require__.g&&__webpack_require__.g.global===__webpack_require__.g?__webpack_require__.g:void 0,a=f.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open("","_blank"),g&&(g.document.title=g.document.body.innerText="downloading..."),"string"==typeof b)return c(b,d,e);var h="application/octet-stream"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\/[\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&"undefined"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g, true&&(module.exports=g)});
//# sourceMappingURL=FileSaver.min.js.map
/***/ }),
/***/ "./node_modules/loglevel/lib/loglevel.js":
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*
* loglevel - https://github.com/pimterry/loglevel
*
* Copyright (c) 2013 Tim Perry
* Licensed under the MIT license.
*/
(function (root, definition) {
"use strict";
if (true) {
!(__WEBPACK_AMD_DEFINE_FACTORY__ = (definition),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
__WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {}
}(this, function () {
"use strict";
// Slightly dubious tricks to cut down minimized file size
var noop = function() {};
var undefinedType = "undefined";
var isIE = (typeof window !== undefinedType) && (typeof window.navigator !== undefinedType) && (
/Trident\/|MSIE /.test(window.navigator.userAgent)
);
var logMethods = [
"trace",
"debug",
"info",
"warn",
"error"
];
var _loggersByName = {};
var defaultLogger = null;
// Cross-browser bind equivalent that works at least back to IE6
function bindMethod(obj, methodName) {
var method = obj[methodName];
if (typeof method.bind === 'function') {
return method.bind(obj);
} else {
try {
return Function.prototype.bind.call(method, obj);
} catch (e) {
// Missing bind shim or IE8 + Modernizr, fallback to wrapping
return function() {
return Function.prototype.apply.apply(method, [obj, arguments]);
};
}
}
}
// Trace() doesn't print the message in IE, so for that case we need to wrap it
function traceForIE() {
if (console.log) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
// In old IE, native console methods themselves don't have apply().
Function.prototype.apply.apply(console.log, [console, arguments]);
}
}
if (console.trace) console.trace();
}
// Build the best logging method possible for this env
// Wherever possible we want to bind, not wrap, to preserve stack traces
function realMethod(methodName) {
if (methodName === 'debug') {
methodName = 'log';
}
if (typeof console === undefinedType) {
return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives
} else if (methodName === 'trace' && isIE) {
return traceForIE;
} else if (console[methodName] !== undefined) {
return bindMethod(console, methodName);
} else if (console.log !== undefined) {
return bindMethod(console, 'log');
} else {
return noop;
}
}
// These private functions always need `this` to be set properly
function replaceLoggingMethods() {
/*jshint validthis:true */
var level = this.getLevel();
// Replace the actual methods.
for (var i = 0; i < logMethods.length; i++) {
var methodName = logMethods[i];
this[methodName] = (i < level) ?
noop :
this.methodFactory(methodName, level, this.name);
}
// Define log.log as an alias for log.debug
this.log = this.debug;
// Return any important warnings.
if (typeof console === undefinedType && level < this.levels.SILENT) {
return "No console available for logging";
}
}
// In old IE versions, the console isn't present until you first open it.
// We build realMethod() replacements here that regenerate logging methods
function enableLoggingWhenConsoleArrives(methodName) {
return function () {
if (typeof console !== undefinedType) {
replaceLoggingMethods.call(this);
this[methodName].apply(this, arguments);
}
};
}
// By default, we use closely bound real methods wherever possible, and
// otherwise we wait for a console to appear, and then try again.
function defaultMethodFactory(methodName, _level, _loggerName) {
/*jshint validthis:true */
return realMethod(methodName) ||
enableLoggingWhenConsoleArrives.apply(this, arguments);
}
function Logger(name, factory) {
// Private instance variables.
var self = this;
/**
* The level inherited from a parent logger (or a global default). We
* cache this here rather than delegating to the parent so that it stays
* in sync with the actual logging methods that we have installed (the
* parent could change levels but we might not have rebuilt the loggers
* in this child yet).
* @type {number}
*/
var inheritedLevel;
/**
* The default level for this logger, if any. If set, this overrides
* `inheritedLevel`.
* @type {number|null}
*/
var defaultLevel;
/**
* A user-specific level for this logger. If set, this overrides
* `defaultLevel`.
* @type {number|null}
*/
var userLevel;
var storageKey = "loglevel";
if (typeof name === "string") {
storageKey += ":" + name;
} else if (typeof name === "symbol") {
storageKey = undefined;
}
function persistLevelIfPossible(levelNum) {
var levelName = (logMethods[levelNum] || 'silent').toUpperCase();
if (typeof window === undefinedType || !storageKey) return;
// Use localStorage if available
try {
window.localStorage[storageKey] = levelName;
return;
} catch (ignore) {}
// Use session cookie as fallback
try {
window.document.cookie =
encodeURIComponent(storageKey) + "=" + levelName + ";";
} catch (ignore) {}
}
function getPersistedLevel() {
var storedLevel;
if (typeof window === undefinedType || !storageKey) return;
try {
storedLevel = window.localStorage[storageKey];
} catch (ignore) {}
// Fallback to cookies if local storage gives us nothing
if (typeof storedLevel === undefinedType) {
try {
var cookie = window.document.cookie;
var cookieName = encodeURIComponent(storageKey);
var location = cookie.indexOf(cookieName + "=");
if (location !== -1) {
storedLevel = /^([^;]+)/.exec(
cookie.slice(location + cookieName.length + 1)
)[1];
}
} catch (ignore) {}
}
// If the stored level is not valid, treat it as if nothing was stored.
if (self.levels[storedLevel] === undefined) {
storedLevel = undefined;
}
return storedLevel;
}
function clearPersistedLevel() {
if (typeof window === undefinedType || !storageKey) return;
// Use localStorage if available
try {
window.localStorage.removeItem(storageKey);
} catch (ignore) {}
// Use session cookie as fallback
try {
window.document.cookie =
encodeURIComponent(storageKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC";
} catch (ignore) {}
}
function normalizeLevel(input) {
var level = input;
if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
level = self.levels[level.toUpperCase()];
}
if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
return level;
} else {
throw new TypeError("log.setLevel() called with invalid level: " + input);
}
}
/*
*
* Public logger API - see https://github.com/pimterry/loglevel for details
*
*/
self.name = name;
self.levels = { "TRACE": 0, "DEBUG": 1, "INFO": 2, "WARN": 3,
"ERROR": 4, "SILENT": 5};
self.methodFactory = factory || defaultMethodFactory;
self.getLevel = function () {
if (userLevel != null) {
return userLevel;
} else if (defaultLevel != null) {
return defaultLevel;
} else {
return inheritedLevel;
}
};
self.setLevel = function (level, persist) {
userLevel = normalizeLevel(level);
if (persist !== false) { // defaults to true
persistLevelIfPossible(userLevel);
}
// NOTE: in v2, this should call rebuild(), which updates children.
return replaceLoggingMethods.call(self);
};
self.setDefaultLevel = function (level) {
defaultLevel = normalizeLevel(level);
if (!getPersistedLevel()) {
self.setLevel(level, false);
}
};
self.resetLevel = function () {
userLevel = null;
clearPersistedLevel();
replaceLoggingMethods.call(self);
};
self.enableAll = function(persist) {
self.setLevel(self.levels.TRACE, persist);
};
self.disableAll = function(persist) {
self.setLevel(self.levels.SILENT, persist);
};
self.rebuild = function () {
if (defaultLogger !== self) {
inheritedLevel = normalizeLevel(defaultLogger.getLevel());
}
replaceLoggingMethods.call(self);
if (defaultLogger === self) {
for (var childName in _loggersByName) {
_loggersByName[childName].rebuild();
}
}
};
// Initialize all the internal levels.
inheritedLevel = normalizeLevel(
defaultLogger ? defaultLogger.getLevel() : "WARN"
);
var initialLevel = getPersistedLevel();
if (initialLevel != null) {
userLevel = normalizeLevel(initialLevel);
}
replaceLoggingMethods.call(self);
}
/*
*
* Top-level API
*
*/
defaultLogger = new Logger();
defaultLogger.getLogger = function getLogger(name) {
if ((typeof name !== "symbol" && typeof name !== "string") || name === "") {
throw new TypeError("You must supply a name when creating a logger.");
}
var logger = _loggersByName[name];
if (!logger) {
logger = _loggersByName[name] = new Logger(
name,
defaultLogger.methodFactory
);
}
return logger;
};
// Grab the current global log variable in case of overwrite
var _log = (typeof window !== undefinedType) ? window.log : undefined;
defaultLogger.noConflict = function() {
if (typeof window !== undefinedType &&
window.log === defaultLogger) {
window.log = _log;
}
return defaultLogger;
};
defaultLogger.getLoggers = function getLoggers() {
return _loggersByName;
};
// ES6 default export, for compatibility
defaultLogger['default'] = defaultLogger;
return defaultLogger;
}));
/***/ }),
/***/ "./node_modules/magic-bytes.js/dist/index.js":
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.filetypeextension = exports.filetypemime = exports.filetypename = exports.filetypeinfo = void 0;
const pattern_tree_1 = __importDefault(__webpack_require__("./node_modules/magic-bytes.js/dist/model/pattern-tree.js"));
const toHex_1 = __webpack_require__("./node_modules/magic-bytes.js/dist/model/toHex.js");
const patternTree = pattern_tree_1.default();
const filetypeinfo = (bytes) => {
let tree = patternTree;
for (const k of Object.keys(tree.offset)) {
const offset = toHex_1.fromHex(k);
const offsetExceedsFile = offset >= bytes.length;
if (offsetExceedsFile) {
continue;
}
const node = patternTree.offset[k];
const guessed = walkTree(offset, bytes, node);
if (guessed.length > 0) {
return guessed;
}
}
if (tree.noOffset === null) {
return [];
}
return walkTree(0, bytes, tree.noOffset);
};
exports.filetypeinfo = filetypeinfo;
const walkTree = (index, bytes, node) => {
let step = node;
let guessFile = [];
while (true) {
const currentByte = toHex_1.toHex(bytes[index]);
if (step.bytes["?"] && !step.bytes[currentByte]) {
step = step.bytes["?"];
}
else {
step = step.bytes[currentByte];
}
if (!step) {
return guessFile;
}
if (step && step.matches) {
guessFile = step.matches.slice(0);
}
index += 1;
}
};
exports["default"] = exports.filetypeinfo;
const filetypename = (bytes) => exports.filetypeinfo(bytes).map((e) => e.typename);
exports.filetypename = filetypename;
const filetypemime = (bytes) => exports.filetypeinfo(bytes)
.map((e) => (e.mime ? e.mime : null))
.filter((x) => x !== null);
exports.filetypemime = filetypemime;
const filetypeextension = (bytes) => exports.filetypeinfo(bytes)
.map((e) => (e.extension ? e.extension : null))
.filter((x) => x !== null);
exports.filetypeextension = filetypeextension;
/***/ }),
/***/ "./node_modules/magic-bytes.js/dist/model/pattern-tree.js":
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
const toHex_1 = __webpack_require__("./node_modules/magic-bytes.js/dist/model/toHex.js");
const tree_1 = __webpack_require__("./node_modules/magic-bytes.js/dist/model/tree.js");
// https://en.wikipedia.org/wiki/List_of_file_signatures
let tree = {
noOffset: null,
offset: {},
};
const add = (typename, signature, additionalInfo, offset) => {
if (offset) {
const existing = tree.offset[toHex_1.toHex(offset)];
if (!existing) {
tree.offset[toHex_1.toHex(offset)] = tree_1.createComplexNode(typename, signature.map((e) => e.toLowerCase()), additionalInfo);
}
else {
const merged = tree_1.merge(tree_1.createNode(typename, signature.map((e) => e.toLowerCase()), additionalInfo), { ...existing });
tree.offset[toHex_1.toHex(offset)] = merged;
}
}
else {
if (tree.noOffset === null) {
tree.noOffset = tree_1.createComplexNode(typename, signature.map((e) => e.toLowerCase()), additionalInfo);
}
else {
tree.noOffset = tree_1.merge(tree_1.createNode(typename, signature.map((e) => e.toLowerCase()), additionalInfo), tree.noOffset);
}
}
};
add("gif", ["0x47", "0x49", "0x46", "0x38", "0x37", "0x61"], {
mime: "image/gif",
extension: "gif",
});
add("gif", ["0x47", "0x49", "0x46", "0x38", "0x39", "0x61"], {
mime: "image/gif",
extension: "gif",
});
add("jpg", ["0xFF", "0xD8", "0xFF"], {
mime: "image/jpeg",
extension: "jpeg",
});
add("webp", [
"0x52",
"0x49",
"0x46",
"0x46",
"?",
"?",
"?",
"?",
"0x57",
"0x45",
"0x42",
"0x50",
], { mime: "image/webp", extension: "webp" });
add("heif", ["0x66", "0x74", "0x79", "0x70", "0x6D", "0x69", "0x66", "0x31"], { mime: "image/heif", extension: "heif" }, 4);
add("heif", ["0x66", "0x74", "0x79", "0x70", "0x68", "0x65", "0x69", "0x63"], { mime: "image/heif", extension: "heic" }, 4);
add("rpm", ["0xed", "0xab", "0xee", "0xdb"]);
add("bin", ["0x53", "0x50", "0x30", "0x31"], {
mime: "application/octet-stream",
extension: "bin",
});
add("pic", ["0x00"]);
add("pif", ["0x00"]);
add("sea", ["0x00"]);
add("ytr", ["0x00"]);
// 66747970
// 6D703432
add("mp4", ["0x66", "0x74", "0x79", "0x70"], { mime: "video/mp4", extension: "mp4" }, 0x4);
add("ttf", ["0x00", "0x01", "0x00", "0x00", "0x00"], {
mime: "font/ttf",
extension: "ttf",
});
add("otf", ["0x4F", "0x54", "0x54", "0x4F"], {
mime: "font/otf",
extension: "otf",
});
add("eot", ["0x50", "0x4C"], {
mime: "application/vnd.ms-fontobject",
extension: "eot",
});
add("woff", ["0x77", "0x4F", "0x46", "0x46"], {
mime: "font/woff",
extension: "woff",
});
add("woff2", ["0x77", "0x4F", "0x46", "0x32"], {
mime: "font/woff2",
extension: "woff2",
});
add("pdb", [
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
]);
add("dba", ["0xBE", "0xBA", "0xFE", "0xCA"]);
add("dba2", ["0x00", "0x01", "0x42", "0x44"]);
add("tda", ["0x00", "0x01", "0x44", "0x54"]);
add("tda2", ["0x00", "0x01", "0x00", "0x00"]);
add("ico", ["0x00", "0x00", "0x01", "0x00"], {
mime: "image/x-icon",
extension: "ico",
});
add("3gp", ["0x66", "0x74", "0x79", "0x70", "0x33", "0x67"]);
add("z", ["0x1F", "0x9D"]);
add("tar.z", ["0x1F", "0xA0"]);
add("bac", [
"0x42",
"0x41",
"0x43",
"0x4B",
"0x4D",
"0x49",
"0x4B",
"0x45",
"0x44",
"0x49",
"0x53",
"0x4B",
]);
add("bz2", ["0x42", "0x5A", "0x68"], {
mime: "application/x-bzip2",
extension: "bz2",
});
add("tif", ["0x49", "0x49", "0x2A", "0x00"], {
mime: "image/tiff",
extension: "tif",
});
add("tiff", ["0x4D", "0x4D", "0x00", "0x2A"], {
mime: "image/tiff",
extension: "tiff",
});
add("cr2", [
"0x49",
"0x49",
"0x2A",
"0x00",
"0x10",
"0x00",
"0x00",
"0x00",
"0x43",
"0x52",
]);
add("cin", ["0x80", "0x2A", "0x5F", "0xD7"]);
add("cin1", ["0x52", "0x4E", "0x43", "0x01"]);
add("cin2", ["0x52", "0x4E", "0x43", "0x02"]);
add("dpx", ["0x53", "0x44", "0x50", "0x58"]);
add("dpx2", ["0x58", "0x50", "0x44", "0x53"]);
add("exr", ["0x76", "0x2F", "0x31", "0x01"]);
add("bpg", ["0x42", "0x50", "0x47", "0xFB"]);
add("ilbm", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x49",
"0x4C",
"0x42",
"0x4D",
]);
add("8svx", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x38",
"0x53",
"0x56",
"0x58",
]);
add("acbm", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x41",
"0x43",
"0x42",
"0x4D",
]);
add("anbm", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x41",
"0x4E",
"0x42",
"0x4D",
]);
add("anim", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x41",
"0x4E",
"0x49",
"0x4D",
]);
add("faxx", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x46",
"0x41",
"0x58",
"0x58",
]);
add("ftxt", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x46",
"0x54",
"0x58",
"0x54",
]);
add("smus", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x53",
"0x4D",
"0x55",
"0x53",
]);
add("cmus", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x43",
"0x4D",
"0x55",
"0x53",
]);
add("yuvn", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x59",
"0x55",
"0x56",
"0x4E",
]);
add("iff", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x46",
"0x41",
"0x4E",
"0x54",
]);
add("aiff", [
"0x46",
"0x4F",
"0x52",
"0x4D",
"?",
"?",
"?",
"?",
"0x41",
"0x49",
"0x46",
"0x46",
], { mime: "audio/x-aiff", extension: "aiff" });
add("idx", ["0x49", "0x4E", "0x44", "0x58"]);
add("lz", ["0x4C", "0x5A", "0x49", "0x50"]);
add("exe", ["0x4D", "0x5A"]);
add("zip", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/zip",
extension: "zip",
});
add("zip", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/zip",
extension: "zip",
});
add("zip", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/zip",
extension: "zip",
});
add("jar", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/java-archive",
extension: "jar",
});
add("jar", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/java-archive",
extension: "jar",
});
add("jar", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/java-archive",
extension: "jar",
});
add("odt", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.oasis.opendocument.text",
extension: "odt",
});
add("odt", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.oasis.opendocument.text",
extension: "odt",
});
add("odt", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.oasis.opendocument.text",
extension: "odt",
});
add("ods", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.oasis.opendocument.spreadsheet",
extension: "ods",
});
add("ods", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.oasis.opendocument.spreadsheet",
extension: "ods",
});
add("ods", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.oasis.opendocument.spreadsheet",
extension: "ods",
});
add("odp", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.oasis.opendocument.presentation",
extension: "odp",
});
add("odp", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.oasis.opendocument.presentation",
extension: "odp",
});
add("odp", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.oasis.opendocument.presentation",
extension: "odp",
});
add("docx", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
extension: "docx",
});
add("docx", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
extension: "docx",
});
add("docx", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
extension: "docx",
});
add("xlsx", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
extension: "xlsx",
});
add("xlsx", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
extension: "xlsx",
});
add("xlsx", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
extension: "xlsx",
});
add("pptx", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
extension: "pptx",
});
add("pptx", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
extension: "pptx",
});
add("pptx", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
extension: "pptx",
});
add("vsdx", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.ms-visio.drawing",
extension: "vsdx",
});
add("vsdx", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.ms-visio.drawing",
extension: "vsdx",
});
add("vsdx", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.ms-visio.drawing",
extension: "vsdx",
});
add("apk", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.android.package-archive",
extension: "apk",
});
add("apk", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.android.package-archive",
extension: "apk",
});
add("apk", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.android.package-archive",
extension: "apk",
});
add("aar", ["0x50", "0x4B", "0x03", "0x04"], {
mime: "application/vnd.android.package-archive",
extension: "aar",
});
add("aar", ["0x50", "0x4B", "0x05", "0x06"], {
mime: "application/vnd.android.package-archive",
extension: "aar",
});
add("aar", ["0x50", "0x4B", "0x07", "0x08"], {
mime: "application/vnd.android.package-archive",
extension: "aar",
});
add("rar", ["0x52", "0x61", "0x72", "0x21", "0x1A", "0x07", "0x00"], {
mime: "application/vnd.rar",
extension: "rar",
});
add("rar", ["0x52", "0x61", "0x72", "0x21", "0x1A", "0x07", "0x01", "0x00"], {
mime: "application/vnd.rar",
extension: "rar",
});
add("rar", ["0x7F", "0x45", "0x4C", "0x46"], {
mime: "application/vnd.rar",
extension: "rar",
});
add("png", ["0x89", "0x50", "0x4E", "0x47", "0x0D", "0x0A", "0x1A", "0x0A"], {
mime: "image/png",
extension: "png",
});
add("apng", ["0x89", "0x50", "0x4E", "0x47", "0x0D", "0x0A", "0x1A", "0x0A"], {
mime: "image/apng",
extension: "apng",
});
add("class", ["0xCA", "0xFE", "0xBA", "0xBE"]);
add("class", ["0xEF", "0xBB", "0xBF"]);
add("class", ["0xFE", "0xed", "0xFA", "0xCE"], undefined, 0x1000);
add("class", ["0xFE", "0xed", "0xFA", "0xCF"], undefined, 0x1000);
add("class", ["0xCE", "0xFA", "0xed", "0xFE"]);
add("class", ["0xCF", "0xFA", "0xed", "0xFE"]);
add("class", ["0xFF", "0xFE"]);
add("class", ["0xFF", "0xFE"]);
add("class", ["0xFF", "0xFE", "0x00", "0x00"]);
add("ps", ["0x25", "0x21", "0x50", "0x53"], {
mime: "application/postscript",
extension: ".ps"
});
add("pdf", ["0x25", "0x50", "0x44", "0x46"], {
mime: "application/pdf",
extension: "pdf",
});
add("asf", [
"0x30",
"0x26",
"0xB2",
"0x75",
"0x8E",
"0x66",
"0xCF",
"0x11",
"0xA6",
"0xD9",
"0x00",
"0xAA",
"0x00",
"0x62",
"0xCE",
"0x6C",
]);
add("wma", [
"0x30",
"0x26",
"0xB2",
"0x75",
"0x8E",
"0x66",
"0xCF",
"0x11",
"0xA6",
"0xD9",
"0x00",
"0xAA",
"0x00",
"0x62",
"0xCE",
"0x6C",
]);
add("wmv", [
"0x30",
"0x26",
"0xB2",
"0x75",
"0x8E",
"0x66",
"0xCF",
"0x11",
"0xA6",
"0xD9",
"0x00",
"0xAA",
"0x00",
"0x62",
"0xCE",
"0x6C",
]);
add("deploymentimage", [
"0x24",
"0x53",
"0x44",
"0x49",
"0x30",
"0x30",
"0x30",
"0x31",
]);
// ogg video ' theora'
add("ogv", [
"0x4F",
"0x67",
"0x67",
"0x53",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"0x80",
"0x74",
"0x68",
"0x65",
"0x6F",
"0x72",
"0x61",
], {
mime: "video/ogg",
extension: "ogv",
});
// ogg video '\x01video'
add("ogm", [
"0x4F",
"0x67",
"0x67",
"0x53",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"0x01",
"0x76",
"0x69",
"0x64",
"0x65",
"0x6F",
"0x00",
], {
mime: "video/ogg",
extension: "ogm",
});
// ogg audio ' FLAC'
add("oga", [
"0x4F",
"0x67",
"0x67",
"0x53",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"0x7F",
"0x46",
"0x4C",
"0x41",
"0x43",
], {
mime: "audio/ogg",
extension: "oga",
});
// ogg audio 'Speex '
add("spx", [
"0x4F",
"0x67",
"0x67",
"0x53",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"0x53",
"0x70",
"0x65",
"0x65",
"0x78",
"0x20",
"0x20",
], {
mime: "audio/ogg",
extension: "spx",
});
// ogg audio '\x01vorbis '
add("ogg", [
"0x4F",
"0x67",
"0x67",
"0x53",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"?",
"0x01",
"0x76",
"0x6F",
"0x72",
"0x62",
"0x69",
"0x73",
], {
mime: "audio/ogg",
extension: "ogg",
});
// default OGG container
add("ogx", ["0x4F", "0x67", "0x67", "0x53"], {
mime: "application/ogg",
extension: "ogx",
});
add("psd", ["0x38", "0x42", "0x50", "0x53"], {
mime: "application/x-photoshop",
extension: "psd",
});
add("clip", ["0x43", "0x53", "0x46", "0x43", "0x48", "0x55", "0x4e", "0x4b"]);
add("wav", [
"0x52",
"0x49",
"0x46",
"0x46",
"?",
"?",
"?",
"?",
"0x57",
"0x41",
"0x56",
"0x45",
], { mime: "audio/x-wav", extension: "wav" });
add("avi", [
"0x52",
"0x49",
"0x46",
"0x46",
"?",
"?",
"?",
"?",
"0x41",
"0x56",
"0x49",
"0x20",
], { mime: "video/x-msvideo", extension: "avi" });
add("mp3", ["0xFF", "0xFB"], { mime: "audio/mpeg", extension: "mp3" });
add("mp3", ["0xFF", "0xF3"], { mime: "audio/mpeg", extension: "mp3" });
add("mp3", ["0xFF", "0xF2"], { mime: "audio/mpeg", extension: "mp3" });
add("mp3", ["0x49", "0x44", "0x33"], { mime: "audio/mpeg", extension: "mp3" });
add("bmp", ["0x42", "0x4D"], { mime: "image/bmp", extension: "bmp" });
add("iso", ["0x43", "0x44", "0x30", "0x30", "0x31"]);
add("flac", ["0x66", "0x4C", "0x61", "0x43"]);
add("mid", ["0x4D", "0x54", "0x68", "0x64"], {
mime: "audio/midi",
extension: "mid",
});
add("midi", ["0x4D", "0x54", "0x68", "0x64"], {
mime: "audio/midi",
extension: "midi",
});
add("doc", ["0xD0", "0xCF", "0x11", "0xE0", "0xA1", "0xB1", "0x1A", "0xE1"], {
mime: "application/msword",
extension: "doc",
});
add("xls", ["0xD0", "0xCF", "0x11", "0xE0", "0xA1", "0xB1", "0x1A", "0xE1"], {
mime: "application/vnd.ms-excel",
extension: "xls",
});
add("ppt", ["0xD0", "0xCF", "0x11", "0xE0", "0xA1", "0xB1", "0x1A", "0xE1"], {
mime: "application/vnd.ms-powerpoint",
extension: "ppt",
});
add("msg", ["0xD0", "0xCF", "0x11", "0xE0", "0xA1", "0xB1", "0x1A", "0xE1"]);
add("dex", ["0x64", "0x65", "0x78", "0x0A", "0x30", "0x33", "0x35", "0x00"]);
add("vmdk", ["0x4B", "0x44", "0x4D"]);
add("crx", ["0x43", "0x72", "0x32", "0x34"]);
add("fh8", ["0x41", "0x47", "0x44", "0x33"]);
add("cwk", [
"0x05",
"0x07",
"0x00",
"0x00",
"0x42",
"0x4F",
"0x42",
"0x4F",
"0x05",
"0x07",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x01",
]);
add("cwk", [
"0x06",
"0x07",
"0xE1",
"0x00",
"0x42",
"0x4F",
"0x42",
"0x4F",
"0x06",
"0x07",
"0xE1",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x01",
]);
add("toast", ["0x45", "0x52", "0x02", "0x00", "0x00", "0x00"]);
add("toast", ["0x8B", "0x45", "0x52", "0x02", "0x00", "0x00", "0x00"]);
add("dmg", ["0x78", "0x01", "0x73", "0x0D", "0x62", "0x62", "0x60"]);
add("xar", ["0x78", "0x61", "0x72", "0x21"]);
add("dat", ["0x50", "0x4D", "0x4F", "0x43", "0x43", "0x4D", "0x4F", "0x43"]);
add("nes", ["0x4E", "0x45", "0x53", "0x1A"]);
add("tar", ["0x75", "0x73", "0x74", "0x61", "0x72", "0x00", "0x30", "0x30"], {
// As per Mozilla documentation available at:
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
// or wikipedia page:
// https://en.wikipedia.org/wiki/List_of_archive_formats
mime: "application/x-tar",
extension: "tar"
}, 0x101);
add("tar", ["0x75", "0x73", "0x74", "0x61", "0x72", "0x20", "0x20", "0x00"], {
mime: "application/x-tar",
extension: "tar"
}, 0x101);
add("tox", ["0x74", "0x6F", "0x78", "0x33"]);
add("mlv", ["0x4D", "0x4C", "0x56", "0x49"]);
add("windowsupdate", [
"0x44",
"0x43",
"0x4D",
"0x01",
"0x50",
"0x41",
"0x33",
"0x30",
]);
add("7z", ["0x37", "0x7A", "0xBC", "0xAF", "0x27", "0x1C"], {
mime: "application/x-7z-compressed",
extension: "7z",
});
add("gz", ["0x1F", "0x8B"], { mime: "application/gzip", extension: "gz" });
add("tar.gz", ["0x1F", "0x8B"], {
mime: "application/gzip",
extension: "tar.gz",
});
add("xz", ["0xFD", "0x37", "0x7A", "0x58", "0x5A", "0x00", "0x00"], {
mime: "application/gzip",
extension: "xz",
});
add("tar.xz", ["0xFD", "0x37", "0x7A", "0x58", "0x5A", "0x00", "0x00"], {
mime: "application/gzip",
extension: "tar.xz",
});
add("lz2", ["0x04", "0x22", "0x4D", "0x18"]);
add("cab", ["0x4D", "0x53", "0x43", "0x46"]);
add("mkv", ["0x1A", "0x45", "0xDF", "0xA3"], {
mime: "video/x-matroska",
extension: "mkv",
});
add("mka", ["0x1A", "0x45", "0xDF", "0xA3"], {
mime: "audio/x-matroska",
extension: "mka",
});
add("mks", ["0x1A", "0x45", "0xDF", "0xA3"], {
mime: "video/x-matroska",
extension: "mks",
});
add("mk3d", ["0x1A", "0x45", "0xDF", "0xA3"]);
add("webm", ["0x1A", "0x45", "0xDF", "0xA3"], {
mime: "audio/webm",
extension: "webm",
});
add("dcm", ["0x44", "0x49", "0x43", "0x4D"], undefined, 0x80);
add("xml", ["0x3C", "0x3f", "0x78", "0x6d", "0x6C", "0x20"], {
mime: "application/xml",
extension: "xml",
});
add("wasm", ["0x00", "0x61", "0x73", "0x6d"], {
mime: "application/wasm",
extension: "wasm",
});
add("lep", ["0xCF", "0x84", "0x01"]);
add("swf", ["0x43", "0x57", "0x53"], {
mime: "application/x-shockwave-flash",
extension: "swf",
});
add("swf", ["0x46", "0x57", "0x53"], {
mime: "application/x-shockwave-flash",
extension: "swf",
});
add("deb", ["0x21", "0x3C", "0x61", "0x72", "0x63", "0x68", "0x3E"]);
add("rtf", ["0x7B", "0x5C", "0x72", "0x74", "0x66", "0x31"], {
mime: "application/rtf",
extension: "rtf",
});
add("m2p", ["0x00", "0x00", "0x01", "0xBA"]);
add("vob", ["0x00", "0x00", "0x01", "0xBA"]);
add("mpg", ["0x00", "0x00", "0x01", "0xBA"], {
mime: "video/mpeg",
extension: "mpg",
});
add("mpeg", ["0x00", "0x00", "0x01", "0xBA"], {
mime: "video/mpeg",
extension: "mpeg",
});
add("mpeg", ["0x47"], { mime: "video/mpeg", extension: "mpeg" });
add("mpeg", ["0x00", "0x00", "0x01", "0xB3"], {
mime: "video/mpeg",
extension: "mpeg",
});
// mov 'free' TODO: find test file
add("mov", ["0x66", "0x72", "0x65", "0x65"], {
mime: "video/quicktime",
extension: "mov",
}, 0x4);
// mov 'mdat'
add("mov", ["0x6D", "0x64", "0x61", "0x74"], {
mime: "video/quicktime",
extension: "mov",
}, 0x4);
// mov 'moov' TODO: find test file
add("mov", ["0x6D", "0x6F", "0x6F", "0x76"], {
mime: "video/quicktime",
extension: "mov",
}, 0x4);
// move 'wide' TODO: find test file
add("mov", ["0x77", "0x69", "0x64", "0x65"], {
mime: "video/quicktime",
extension: "mov",
}, 0x4);
// mov 'ftypqt'
add("mov", ["0x66", "0x74", "0x79", "0x70", "0x71", "0x74"], {
mime: "video/quicktime",
extension: "mov",
}, 0x4);
add("hl2demo", ["0x48", "0x4C", "0x32", "0x44", "0x45", "0x4D", "0x4F"]);
add("txt", ["0xEF", "0xBB", "0xBF"], {
mime: "text/plain; charset=UTF-8",
extension: "txt",
});
add("txt", ["0xFF", "0xFE"], {
mime: "text/plain; charset=UTF-16LE",
extension: "txt",
});
add("txt", ["0xFE", "0xFF"], {
mime: "text/plain; charset=UTF-16BE",
extension: "txt",
});
add("txt", ["0xFF", "0xFE", "0x00", "0x00"], {
mime: "text/plain; charset=UTF-32LE",
extension: "txt",
});
add("txt", ["0x00", "0x00", "0xFE", "0xFF"], {
mime: "text/plain; charset=UTF-32BE",
extension: "txt",
});
add("SubRip", ["0x31", "0x0D", "0x0A", "0x30", "0x30", "0x3A"], {
mime: "application/x-subrip",
extension: "srt",
});
add("WebVTT", [
"0xEF",
"0xBB",
"0xBF",
"0x57",
"0x45",
"0x42",
"0x56",
"0x54",
"0x54",
"0x0A",
], {
mime: "text/vtt",
extension: "vtt",
});
add("WebVTT", [
"0xEF",
"0xBB",
"0xBF",
"0x57",
"0x45",
"0x42",
"0x56",
"0x54",
"0x54",
"0x0D",
], {
mime: "text/vtt",
extension: "vtt",
});
add("WebVTT", [
"0xEF",
"0xBB",
"0xBF",
"0x57",
"0x45",
"0x42",
"0x56",
"0x54",
"0x54",
"0x20",
], {
mime: "text/vtt",
extension: "vtt",
});
add("WebVTT", [
"0xEF",
"0xBB",
"0xBF",
"0x57",
"0x45",
"0x42",
"0x56",
"0x54",
"0x54",
"0x09",
], {
mime: "text/vtt",
extension: "vtt",
});
add("WebVTT", ["0x57", "0x45", "0x42", "0x56", "0x54", "0x54", "0x0A"], {
mime: "text/vtt",
extension: "vtt",
});
add("WebVTT", ["0x57", "0x45", "0x42", "0x56", "0x54", "0x54", "0x0D"], {
mime: "text/vtt",
extension: "vtt",
});
add("WebVTT", ["0x57", "0x45", "0x42", "0x56", "0x54", "0x54", "0x20"], {
mime: "text/vtt",
extension: "vtt",
});
add("WebVTT", ["0x57", "0x45", "0x42", "0x56", "0x54", "0x54", "0x09"], {
mime: "text/vtt",
extension: "vtt",
});
add("Json", ["0x7B"], {
mime: "application/json",
extension: ".json",
});
add("Json", ["0x5B"], {
mime: "application/json",
extension: ".json",
});
add("ELF", ["0x7F", "0x45", "0x4C", "0x46"], {
mime: "application/x-executable",
extension: ".elf",
});
add("Mach-O", ["0xFE", "0xED", "0xFA", "0xC"], {
mime: "application/x-mach-binary",
extension: ".o",
});
add("Mach-O", ["0xFE", "0xED", "0xFA", "0xCF"], {
mime: "application/x-executable",
extension: "elf",
});
add("EML", ["0x52", "0x65", "0x63", "0x65", "0x69", "0x76", "0x65", "0x64", "0x3A"], {
mime: "message/rfc822",
extension: ".eml",
});
add("SVG", ["0x3c", "0x73", "0x76", "0x67"], {
mime: "image/svg+xml",
extension: "svg",
});
exports["default"] = () => tree;
/***/ }),
/***/ "./node_modules/magic-bytes.js/dist/model/toHex.js":
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.fromHex = exports.toHex = void 0;
const hex = (num) => new Number(num).toString(16).toLowerCase();
const toHex = (num) => `0x${hex(num).length === 1 ? "0" + hex(num) : hex(num)}`;
exports.toHex = toHex;
const fromHex = (hex) => new Number(hex);
exports.fromHex = fromHex;
/***/ }),
/***/ "./node_modules/magic-bytes.js/dist/model/tree.js":
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.createComplexNode = exports.createNode = exports.merge = void 0;
const createMatch = (leaf) => ({
typename: leaf.typename,
mime: leaf.info.mime,
extension: leaf.info.extension,
});
const isMatchingNode = (tree, path) => tree && path.length === 0;
const head = (arr) => arr[0];
const tail = (arr) => arr.slice(1, arr.length);
const merge = (node, tree) => {
if (node.bytes.length === 0)
return tree;
const currentByte = head(node.bytes); // 0
const path = tail(node.bytes); // [1,2]
const currentTree = tree.bytes[currentByte];
// traversed to end. Just add key to leaf.
if (isMatchingNode(currentTree, path)) {
const matchingNode = tree.bytes[currentByte];
tree.bytes[currentByte] = {
...matchingNode,
matches: [
...(matchingNode.matches ? matchingNode.matches : []),
createMatch(node),
],
};
return tree;
}
// Path exists already, Merge subtree
if (tree.bytes[currentByte]) {
tree.bytes[currentByte] = exports.merge(exports.createNode(node.typename, path, node.info), tree.bytes[currentByte]);
return tree;
}
// Tree did not exist before
if (!tree.bytes[currentByte]) {
tree.bytes[currentByte] = {
...tree.bytes[currentByte],
...exports.createComplexNode(node.typename, path, node.info),
};
}
return tree;
};
exports.merge = merge;
const createNode = (typename, bytes, info) => {
return { typename, bytes, info: info ? info : {} };
};
exports.createNode = createNode;
const createComplexNode = (typename, bytes, info) => {
let obj = {
bytes: {},
matches: undefined,
};
const currentKey = head(bytes); // 0
const path = tail(bytes); // [1,2]
if (bytes.length === 0) {
return {
matches: [
createMatch({
typename: typename,
info: info ? { extension: info.extension, mime: info.mime } : {},
}),
],
bytes: {},
};
}
obj.bytes[currentKey] = exports.createComplexNode(typename, path, info);
return obj;
};
exports.createComplexNode = createComplexNode;
/***/ }),
/***/ "./node_modules/mime-db/index.js":
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
/*!
* mime-db
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2015-2022 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module exports.
*/
module.exports = __webpack_require__("./node_modules/mime-db/db.json")
/***/ }),
/***/ "./node_modules/source-map-js/lib/array-set.js":
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var util = __webpack_require__("./node_modules/source-map-js/lib/util.js");
var has = Object.prototype.hasOwnProperty;
var hasNativeMap = typeof Map !== "undefined";
/**
* A data structure which is a combination of an array and a set. Adding a new
* member is O(1), testing for membership is O(1), and finding the index of an
* element is O(1). Removing elements from the set is not supported. Only
* strings are supported for membership.
*/
function ArraySet() {
this._array = [];
this._set = hasNativeMap ? new Map() : Object.create(null);
}
/**
* Static method for creating ArraySet instances from an existing array.
*/
ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
var set = new ArraySet();
for (var i = 0, len = aArray.length; i < len; i++) {
set.add(aArray[i], aAllowDuplicates);
}
return set;
};
/**
* Return how many unique items are in this ArraySet. If duplicates have been
* added, than those do not count towards the size.
*
* @returns Number
*/
ArraySet.prototype.size = function ArraySet_size() {
return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length;
};
/**
* Add the given string to this set.
*
* @param String aStr
*/
ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
var sStr = hasNativeMap ? aStr : util.toSetString(aStr);
var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);
var idx = this._array.length;
if (!isDuplicate || aAllowDuplicates) {
this._array.push(aStr);
}
if (!isDuplicate) {
if (hasNativeMap) {
this._set.set(aStr, idx);
} else {
this._set[sStr] = idx;
}
}
};
/**
* Is the given string a member of this set?
*
* @param String aStr
*/
ArraySet.prototype.has = function ArraySet_has(aStr) {
if (hasNativeMap) {
return this._set.has(aStr);
} else {
var sStr = util.toSetString(aStr);
return has.call(this._set, sStr);
}
};
/**
* What is the index of the given string in the array?
*
* @param String aStr
*/
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
if (hasNativeMap) {
var idx = this._set.get(aStr);
if (idx >= 0) {
return idx;
}
} else {
var sStr = util.toSetString(aStr);
if (has.call(this._set, sStr)) {
return this._set[sStr];
}
}
throw new Error('"' + aStr + '" is not in the set.');
};
/**
* What is the element at the given index?
*
* @param Number aIdx
*/
ArraySet.prototype.at = function ArraySet_at(aIdx) {
if (aIdx >= 0 && aIdx < this._array.length) {
return this._array[aIdx];
}
throw new Error('No element indexed by ' + aIdx);
};
/**
* Returns the array representation of this set (which has the proper indices
* indicated by indexOf). Note that this is a copy of the internal array used
* for storing the members so that no one can mess with internal state.
*/
ArraySet.prototype.toArray = function ArraySet_toArray() {
return this._array.slice();
};
exports.C = ArraySet;
/***/ }),
/***/ "./node_modules/source-map-js/lib/base64-vlq.js":
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*
* Based on the Base 64 VLQ implementation in Closure Compiler:
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
*
* Copyright 2011 The Closure Compiler Authors. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var base64 = __webpack_require__("./node_modules/source-map-js/lib/base64.js");
// A single base 64 digit can contain 6 bits of data. For the base 64 variable
// length quantities we use in the source map spec, the first bit is the sign,
// the next four bits are the actual value, and the 6th bit is the
// continuation bit. The continuation bit tells us whether there are more
// digits in this value following this digit.
//
// Continuation
// | Sign
// | |
// V V
// 101011
var VLQ_BASE_SHIFT = 5;
// binary: 100000
var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
// binary: 011111
var VLQ_BASE_MASK = VLQ_BASE - 1;
// binary: 100000
var VLQ_CONTINUATION_BIT = VLQ_BASE;
/**
* Converts from a two-complement value to a value where the sign bit is
* placed in the least significant bit. For example, as decimals:
* 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
* 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
*/
function toVLQSigned(aValue) {
return aValue < 0
? ((-aValue) << 1) + 1
: (aValue << 1) + 0;
}
/**
* Converts to a two-complement value from a value where the sign bit is
* placed in the least significant bit. For example, as decimals:
* 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
* 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
*/
function fromVLQSigned(aValue) {
var isNegative = (aValue & 1) === 1;
var shifted = aValue >> 1;
return isNegative
? -shifted
: shifted;
}
/**
* Returns the base 64 VLQ encoded value.
*/
exports.encode = function base64VLQ_encode(aValue) {
var encoded = "";
var digit;
var vlq = toVLQSigned(aValue);
do {
digit = vlq & VLQ_BASE_MASK;
vlq >>>= VLQ_BASE_SHIFT;
if (vlq > 0) {
// There are still more digits in this value, so we must make sure the
// continuation bit is marked.
digit |= VLQ_CONTINUATION_BIT;
}
encoded += base64.encode(digit);
} while (vlq > 0);
return encoded;
};
/**
* Decodes the next base 64 VLQ value from the given string and returns the
* value and the rest of the string via the out parameter.
*/
exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
var strLen = aStr.length;
var result = 0;
var shift = 0;
var continuation, digit;
do {
if (aIndex >= strLen) {
throw new Error("Expected more digits in base 64 VLQ value.");
}
digit = base64.decode(aStr.charCodeAt(aIndex++));
if (digit === -1) {
throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1));
}
continuation = !!(digit & VLQ_CONTINUATION_BIT);
digit &= VLQ_BASE_MASK;
result = result + (digit << shift);
shift += VLQ_BASE_SHIFT;
} while (continuation);
aOutParam.value = fromVLQSigned(result);
aOutParam.rest = aIndex;
};
/***/ }),
/***/ "./node_modules/source-map-js/lib/base64.js":
/***/ ((__unused_webpack_module, exports) => {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
/**
* Encode an integer in the range of 0 to 63 to a single base 64 digit.
*/
exports.encode = function (number) {
if (0 <= number && number < intToCharMap.length) {
return intToCharMap[number];
}
throw new TypeError("Must be between 0 and 63: " + number);
};
/**
* Decode a single base 64 character code digit to an integer. Returns -1 on
* failure.
*/
exports.decode = function (charCode) {
var bigA = 65; // 'A'
var bigZ = 90; // 'Z'
var littleA = 97; // 'a'
var littleZ = 122; // 'z'
var zero = 48; // '0'
var nine = 57; // '9'
var plus = 43; // '+'
var slash = 47; // '/'
var littleOffset = 26;
var numberOffset = 52;
// 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ
if (bigA <= charCode && charCode <= bigZ) {
return (charCode - bigA);
}
// 26 - 51: abcdefghijklmnopqrstuvwxyz
if (littleA <= charCode && charCode <= littleZ) {
return (charCode - littleA + littleOffset);
}
// 52 - 61: 0123456789
if (zero <= charCode && charCode <= nine) {
return (charCode - zero + numberOffset);
}
// 62: +
if (charCode == plus) {
return 62;
}
// 63: /
if (charCode == slash) {
return 63;
}
// Invalid base64 digit.
return -1;
};
/***/ }),
/***/ "./node_modules/source-map-js/lib/mapping-list.js":
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2014 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var util = __webpack_require__("./node_modules/source-map-js/lib/util.js");
/**
* Determine whether mappingB is after mappingA with respect to generated
* position.
*/
function generatedPositionAfter(mappingA, mappingB) {
// Optimized for most common case
var lineA = mappingA.generatedLine;
var lineB = mappingB.generatedLine;
var columnA = mappingA.generatedColumn;
var columnB = mappingB.generatedColumn;
return lineB > lineA || lineB == lineA && columnB >= columnA ||
util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
}
/**
* A data structure to provide a sorted view of accumulated mappings in a
* performance conscious manner. It trades a neglibable overhead in general
* case for a large speedup in case of mappings being added in order.
*/
function MappingList() {
this._array = [];
this._sorted = true;
// Serves as infimum
this._last = {generatedLine: -1, generatedColumn: 0};
}
/**
* Iterate through internal items. This method takes the same arguments that
* `Array.prototype.forEach` takes.
*
* NOTE: The order of the mappings is NOT guaranteed.
*/
MappingList.prototype.unsortedForEach =
function MappingList_forEach(aCallback, aThisArg) {
this._array.forEach(aCallback, aThisArg);
};
/**
* Add the given source mapping.
*
* @param Object aMapping
*/
MappingList.prototype.add = function MappingList_add(aMapping) {
if (generatedPositionAfter(this._last, aMapping)) {
this._last = aMapping;
this._array.push(aMapping);
} else {
this._sorted = false;
this._array.push(aMapping);
}
};
/**
* Returns the flat, sorted array of mappings. The mappings are sorted by
* generated position.
*
* WARNING: This method returns internal data without copying, for
* performance. The return value must NOT be mutated, and should be treated as
* an immutable borrow. If you want to take ownership, you must make your own
* copy.
*/
MappingList.prototype.toArray = function MappingList_toArray() {
if (!this._sorted) {
this._array.sort(util.compareByGeneratedPositionsInflated);
this._sorted = true;
}
return this._array;
};
exports.P = MappingList;
/***/ }),
/***/ "./node_modules/source-map-js/lib/source-map-generator.js":
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
var base64VLQ = __webpack_require__("./node_modules/source-map-js/lib/base64-vlq.js");
var util = __webpack_require__("./node_modules/source-map-js/lib/util.js");
var ArraySet = (__webpack_require__("./node_modules/source-map-js/lib/array-set.js")/* .ArraySet */ .C);
var MappingList = (__webpack_require__("./node_modules/source-map-js/lib/mapping-list.js")/* .MappingList */ .P);
/**
* An instance of the SourceMapGenerator represents a source map which is
* being built incrementally. You may pass an object with the following
* properties:
*
* - file: The filename of the generated source.
* - sourceRoot: A root for all relative URLs in this source map.
*/
function SourceMapGenerator(aArgs) {
if (!aArgs) {
aArgs = {};
}
this._file = util.getArg(aArgs, 'file', null);
this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
this._sources = new ArraySet();
this._names = new ArraySet();
this._mappings = new MappingList();
this._sourcesContents = null;
}
SourceMapGenerator.prototype._version = 3;
/**
* Creates a new SourceMapGenerator based on a SourceMapConsumer
*
* @param aSourceMapConsumer The SourceMap.
*/
SourceMapGenerator.fromSourceMap =
function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
var sourceRoot = aSourceMapConsumer.sourceRoot;
var generator = new SourceMapGenerator({
file: aSourceMapConsumer.file,
sourceRoot: sourceRoot
});
aSourceMapConsumer.eachMapping(function (mapping) {
var newMapping = {
generated: {
line: mapping.generatedLine,
column: mapping.generatedColumn
}
};
if (mapping.source != null) {
newMapping.source = mapping.source;
if (sourceRoot != null) {
newMapping.source = util.relative(sourceRoot, newMapping.source);
}
newMapping.original = {
line: mapping.originalLine,
column: mapping.originalColumn
};
if (mapping.name != null) {
newMapping.name = mapping.name;
}
}
generator.addMapping(newMapping);
});
aSourceMapConsumer.sources.forEach(function (sourceFile) {
var sourceRelative = sourceFile;
if (sourceRoot !== null) {
sourceRelative = util.relative(sourceRoot, sourceFile);
}
if (!generator._sources.has(sourceRelative)) {
generator._sources.add(sourceRelative);
}
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content != null) {
generator.setSourceContent(sourceFile, content);
}
});
return generator;
};
/**
* Add a single mapping from original source line and column to the generated
* source's line and column for this source map being created. The mapping
* object should have the following properties:
*
* - generated: An object with the generated line and column positions.
* - original: An object with the original line and column positions.
* - source: The original source file (relative to the sourceRoot).
* - name: An optional original token name for this mapping.
*/
SourceMapGenerator.prototype.addMapping =
function SourceMapGenerator_addMapping(aArgs) {
var generated = util.getArg(aArgs, 'generated');
var original = util.getArg(aArgs, 'original', null);
var source = util.getArg(aArgs, 'source', null);
var name = util.getArg(aArgs, 'name', null);
if (!this._skipValidation) {
this._validateMapping(generated, original, source, name);
}
if (source != null) {
source = String(source);
if (!this._sources.has(source)) {
this._sources.add(source);
}
}
if (name != null) {
name = String(name);
if (!this._names.has(name)) {
this._names.add(name);
}
}
this._mappings.add({
generatedLine: generated.line,
generatedColumn: generated.column,
originalLine: original != null && original.line,
originalColumn: original != null && original.column,
source: source,
name: name
});
};
/**
* Set the source content for a source file.
*/
SourceMapGenerator.prototype.setSourceContent =
function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
var source = aSourceFile;
if (this._sourceRoot != null) {
source = util.relative(this._sourceRoot, source);
}
if (aSourceContent != null) {
// Add the source content to the _sourcesContents map.
// Create a new _sourcesContents map if the property is null.
if (!this._sourcesContents) {
this._sourcesContents = Object.create(null);
}
this._sourcesContents[util.toSetString(source)] = aSourceContent;
} else if (this._sourcesContents) {
// Remove the source file from the _sourcesContents map.
// If the _sourcesContents map is empty, set the property to null.
delete this._sourcesContents[util.toSetString(source)];
if (Object.keys(this._sourcesContents).length === 0) {
this._sourcesContents = null;
}
}
};
/**
* Applies the mappings of a sub-source-map for a specific source file to the
* source map being generated. Each mapping to the supplied source file is
* rewritten using the supplied source map. Note: The resolution for the
* resulting mappings is the minimium of this map and the supplied map.
*
* @param aSourceMapConsumer The source map to be applied.
* @param aSourceFile Optional. The filename of the source file.
* If omitted, SourceMapConsumer's file property will be used.
* @param aSourceMapPath Optional. The dirname of the path to the source map
* to be applied. If relative, it is relative to the SourceMapConsumer.
* This parameter is needed when the two source maps aren't in the same
* directory, and the source map to be applied contains relative source
* paths. If so, those relative source paths need to be rewritten
* relative to the SourceMapGenerator.
*/
SourceMapGenerator.prototype.applySourceMap =
function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
var sourceFile = aSourceFile;
// If aSourceFile is omitted, we will use the file property of the SourceMap
if (aSourceFile == null) {
if (aSourceMapConsumer.file == null) {
throw new Error(
'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
'or the source map\'s "file" property. Both were omitted.'
);
}
sourceFile = aSourceMapConsumer.file;
}
var sourceRoot = this._sourceRoot;
// Make "sourceFile" relative if an absolute Url is passed.
if (sourceRoot != null) {
sourceFile = util.relative(sourceRoot, sourceFile);
}
// Applying the SourceMap can add and remove items from the sources and
// the names array.
var newSources = new ArraySet();
var newNames = new ArraySet();
// Find mappings for the "sourceFile"
this._mappings.unsortedForEach(function (mapping) {
if (mapping.source === sourceFile && mapping.originalLine != null) {
// Check if it can be mapped by the source map, then update the mapping.
var original = aSourceMapConsumer.originalPositionFor({
line: mapping.originalLine,
column: mapping.originalColumn
});
if (original.source != null) {
// Copy mapping
mapping.source = original.source;
if (aSourceMapPath != null) {
mapping.source = util.join(aSourceMapPath, mapping.source)
}
if (sourceRoot != null) {
mapping.source = util.relative(sourceRoot, mapping.source);
}
mapping.originalLine = original.line;
mapping.originalColumn = original.column;
if (original.name != null) {
mapping.name = original.name;
}
}
}
var source = mapping.source;
if (source != null && !newSources.has(source)) {
newSources.add(source);
}
var name = mapping.name;
if (name != null && !newNames.has(name)) {
newNames.add(name);
}
}, this);
this._sources = newSources;
this._names = newNames;
// Copy sourcesContents of applied map.
aSourceMapConsumer.sources.forEach(function (sourceFile) {
var content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content != null) {
if (aSourceMapPath != null) {
sourceFile = util.join(aSourceMapPath, sourceFile);
}
if (sourceRoot != null) {
sourceFile = util.relative(sourceRoot, sourceFile);
}
this.setSourceContent(sourceFile, content);
}
}, this);
};
/**
* A mapping can have one of the three levels of data:
*
* 1. Just the generated position.
* 2. The Generated position, original position, and original source.
* 3. Generated and original position, original source, as well as a name
* token.
*
* To maintain consistency, we validate that any new mapping being added falls
* in to one of these categories.
*/
SourceMapGenerator.prototype._validateMapping =
function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
aName) {
// When aOriginal is truthy but has empty values for .line and .column,
// it is most likely a programmer error. In this case we throw a very
// specific error message to try to guide them the right way.
// For example: https://github.com/Polymer/polymer-bundler/pull/519
if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {
throw new Error(
'original.line and original.column are not numbers -- you probably meant to omit ' +
'the original mapping entirely and only map the generated position. If so, pass ' +
'null for the original mapping instead of an object with empty or null values.'
);
}
if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
&& aGenerated.line > 0 && aGenerated.column >= 0
&& !aOriginal && !aSource && !aName) {
// Case 1.
return;
}
else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
&& aOriginal && 'line' in aOriginal && 'column' in aOriginal
&& aGenerated.line > 0 && aGenerated.column >= 0
&& aOriginal.line > 0 && aOriginal.column >= 0
&& aSource) {
// Cases 2 and 3.
return;
}
else {
throw new Error('Invalid mapping: ' + JSON.stringify({
generated: aGenerated,
source: aSource,
original: aOriginal,
name: aName
}));
}
};
/**
* Serialize the accumulated mappings in to the stream of base 64 VLQs
* specified by the source map format.
*/
SourceMapGenerator.prototype._serializeMappings =
function SourceMapGenerator_serializeMappings() {
var previousGeneratedColumn = 0;
var previousGeneratedLine = 1;
var previousOriginalColumn = 0;
var previousOriginalLine = 0;
var previousName = 0;
var previousSource = 0;
var result = '';
var next;
var mapping;
var nameIdx;
var sourceIdx;
var mappings = this._mappings.toArray();
for (var i = 0, len = mappings.length; i < len; i++) {
mapping = mappings[i];
next = ''
if (mapping.generatedLine !== previousGeneratedLine) {
previousGeneratedColumn = 0;
while (mapping.generatedLine !== previousGeneratedLine) {
next += ';';
previousGeneratedLine++;
}
}
else {
if (i > 0) {
if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
continue;
}
next += ',';
}
}
next += base64VLQ.encode(mapping.generatedColumn
- previousGeneratedColumn);
previousGeneratedColumn = mapping.generatedColumn;
if (mapping.source != null) {
sourceIdx = this._sources.indexOf(mapping.source);
next += base64VLQ.encode(sourceIdx - previousSource);
previousSource = sourceIdx;
// lines are stored 0-based in SourceMap spec version 3
next += base64VLQ.encode(mapping.originalLine - 1
- previousOriginalLine);
previousOriginalLine = mapping.originalLine - 1;
next += base64VLQ.encode(mapping.originalColumn
- previousOriginalColumn);
previousOriginalColumn = mapping.originalColumn;
if (mapping.name != null) {
nameIdx = this._names.indexOf(mapping.name);
next += base64VLQ.encode(nameIdx - previousName);
previousName = nameIdx;
}
}
result += next;
}
return result;
};
SourceMapGenerator.prototype._generateSourcesContent =
function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
return aSources.map(function (source) {
if (!this._sourcesContents) {
return null;
}
if (aSourceRoot != null) {
source = util.relative(aSourceRoot, source);
}
var key = util.toSetString(source);
return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
? this._sourcesContents[key]
: null;
}, this);
};
/**
* Externalize the source map.
*/
SourceMapGenerator.prototype.toJSON =
function SourceMapGenerator_toJSON() {
var map = {
version: this._version,
sources: this._sources.toArray(),
names: this._names.toArray(),
mappings: this._serializeMappings()
};
if (this._file != null) {
map.file = this._file;
}
if (this._sourceRoot != null) {
map.sourceRoot = this._sourceRoot;
}
if (this._sourcesContents) {
map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
}
return map;
};
/**
* Render the source map being generated to a string.
*/
SourceMapGenerator.prototype.toString =
function SourceMapGenerator_toString() {
return JSON.stringify(this.toJSON());
};
exports.x = SourceMapGenerator;
/***/ }),
/***/ "./node_modules/source-map-js/lib/util.js":
/***/ ((__unused_webpack_module, exports) => {
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
/**
* This is a helper function for getting values from parameter/options
* objects.
*
* @param args The object we are extracting values from
* @param name The name of the property we are getting.
* @param defaultValue An optional value to return if the property is missing
* from the object. If this is not specified and the property is missing, an
* error will be thrown.
*/
function getArg(aArgs, aName, aDefaultValue) {
if (aName in aArgs) {
return aArgs[aName];
} else if (arguments.length === 3) {
return aDefaultValue;
} else {
throw new Error('"' + aName + '" is a required argument.');
}
}
exports.getArg = getArg;
var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;
var dataUrlRegexp = /^data:.+\,.+$/;
function urlParse(aUrl) {
var match = aUrl.match(urlRegexp);
if (!match) {
return null;
}
return {
scheme: match[1],
auth: match[2],
host: match[3],
port: match[4],
path: match[5]
};
}
exports.urlParse = urlParse;
function urlGenerate(aParsedUrl) {
var url = '';
if (aParsedUrl.scheme) {
url += aParsedUrl.scheme + ':';
}
url += '//';
if (aParsedUrl.auth) {
url += aParsedUrl.auth + '@';
}
if (aParsedUrl.host) {
url += aParsedUrl.host;
}
if (aParsedUrl.port) {
url += ":" + aParsedUrl.port
}
if (aParsedUrl.path) {
url += aParsedUrl.path;
}
return url;
}
exports.urlGenerate = urlGenerate;
var MAX_CACHED_INPUTS = 32;
/**
* Takes some function `f(input) -> result` and returns a memoized version of
* `f`.
*
* We keep at most `MAX_CACHED_INPUTS` memoized results of `f` alive. The
* memoization is a dumb-simple, linear least-recently-used cache.
*/
function lruMemoize(f) {
var cache = [];
return function(input) {
for (var i = 0; i < cache.length; i++) {
if (cache[i].input === input) {
var temp = cache[0];
cache[0] = cache[i];
cache[i] = temp;
return cache[0].result;
}
}
var result = f(input);
cache.unshift({
input,
result,
});
if (cache.length > MAX_CACHED_INPUTS) {
cache.pop();
}
return result;
};
}
/**
* Normalizes a path, or the path portion of a URL:
*
* - Replaces consecutive slashes with one slash.
* - Removes unnecessary '.' parts.
* - Removes unnecessary '<dir>/..' parts.
*
* Based on code in the Node.js 'path' core module.
*
* @param aPath The path or url to normalize.
*/
var normalize = lruMemoize(function normalize(aPath) {
var path = aPath;
var url = urlParse(aPath);
if (url) {
if (!url.path) {
return aPath;
}
path = url.path;
}
var isAbsolute = exports.isAbsolute(path);
// Split the path into parts between `/` characters. This is much faster than
// using `.split(/\/+/g)`.
var parts = [];
var start = 0;
var i = 0;
while (true) {
start = i;
i = path.indexOf("/", start);
if (i === -1) {
parts.push(path.slice(start));
break;
} else {
parts.push(path.slice(start, i));
while (i < path.length && path[i] === "/") {
i++;
}
}
}
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
part = parts[i];
if (part === '.') {
parts.splice(i, 1);
} else if (part === '..') {
up++;
} else if (up > 0) {
if (part === '') {
// The first part is blank if the path is absolute. Trying to go
// above the root is a no-op. Therefore we can remove all '..' parts
// directly after the root.
parts.splice(i + 1, up);
up = 0;
} else {
parts.splice(i, 2);
up--;
}
}
}
path = parts.join('/');
if (path === '') {
path = isAbsolute ? '/' : '.';
}
if (url) {
url.path = path;
return urlGenerate(url);
}
return path;
});
exports.normalize = normalize;
/**
* Joins two paths/URLs.
*
* @param aRoot The root path or URL.
* @param aPath The path or URL to be joined with the root.
*
* - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
* scheme-relative URL: Then the scheme of aRoot, if any, is prepended
* first.
* - Otherwise aPath is a path. If aRoot is a URL, then its path portion
* is updated with the result and aRoot is returned. Otherwise the result
* is returned.
* - If aPath is absolute, the result is aPath.
* - Otherwise the two paths are joined with a slash.
* - Joining for example 'http://' and 'www.example.com' is also supported.
*/
function join(aRoot, aPath) {
if (aRoot === "") {
aRoot = ".";
}
if (aPath === "") {
aPath = ".";
}
var aPathUrl = urlParse(aPath);
var aRootUrl = urlParse(aRoot);
if (aRootUrl) {
aRoot = aRootUrl.path || '/';
}
// `join(foo, '//www.example.org')`
if (aPathUrl && !aPathUrl.scheme) {
if (aRootUrl) {
aPathUrl.scheme = aRootUrl.scheme;
}
return urlGenerate(aPathUrl);
}
if (aPathUrl || aPath.match(dataUrlRegexp)) {
return aPath;
}
// `join('http://', 'www.example.com')`
if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
aRootUrl.host = aPath;
return urlGenerate(aRootUrl);
}
var joined = aPath.charAt(0) === '/'
? aPath
: normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
if (aRootUrl) {
aRootUrl.path = joined;
return urlGenerate(aRootUrl);
}
return joined;
}
exports.join = join;
exports.isAbsolute = function (aPath) {
return aPath.charAt(0) === '/' || urlRegexp.test(aPath);
};
/**
* Make a path relative to a URL or another path.
*
* @param aRoot The root path or URL.
* @param aPath The path or URL to be made relative to aRoot.
*/
function relative(aRoot, aPath) {
if (aRoot === "") {
aRoot = ".";
}
aRoot = aRoot.replace(/\/$/, '');
// It is possible for the path to be above the root. In this case, simply
// checking whether the root is a prefix of the path won't work. Instead, we
// need to remove components from the root one by one, until either we find
// a prefix that fits, or we run out of components to remove.
var level = 0;
while (aPath.indexOf(aRoot + '/') !== 0) {
var index = aRoot.lastIndexOf("/");
if (index < 0) {
return aPath;
}
// If the only part of the root that is left is the scheme (i.e. http://,
// file:///, etc.), one or more slashes (/), or simply nothing at all, we
// have exhausted all components, so the path is not relative to the root.
aRoot = aRoot.slice(0, index);
if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
return aPath;
}
++level;
}
// Make sure we add a "../" for each component we removed from the root.
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
}
exports.relative = relative;
var supportsNullProto = (function () {
var obj = Object.create(null);
return !('__proto__' in obj);
}());
function identity (s) {
return s;
}
/**
* Because behavior goes wacky when you set `__proto__` on objects, we
* have to prefix all the strings in our set with an arbitrary character.
*
* See https://github.com/mozilla/source-map/pull/31 and
* https://github.com/mozilla/source-map/issues/30
*
* @param String aStr
*/
function toSetString(aStr) {
if (isProtoString(aStr)) {
return '$' + aStr;
}
return aStr;
}
exports.toSetString = supportsNullProto ? identity : toSetString;
function fromSetString(aStr) {
if (isProtoString(aStr)) {
return aStr.slice(1);
}
return aStr;
}
exports.fromSetString = supportsNullProto ? identity : fromSetString;
function isProtoString(s) {
if (!s) {
return false;
}
var length = s.length;
if (length < 9 /* "__proto__".length */) {
return false;
}
if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||
s.charCodeAt(length - 2) !== 95 /* '_' */ ||
s.charCodeAt(length - 3) !== 111 /* 'o' */ ||
s.charCodeAt(length - 4) !== 116 /* 't' */ ||
s.charCodeAt(length - 5) !== 111 /* 'o' */ ||
s.charCodeAt(length - 6) !== 114 /* 'r' */ ||
s.charCodeAt(length - 7) !== 112 /* 'p' */ ||
s.charCodeAt(length - 8) !== 95 /* '_' */ ||
s.charCodeAt(length - 9) !== 95 /* '_' */) {
return false;
}
for (var i = length - 10; i >= 0; i--) {
if (s.charCodeAt(i) !== 36 /* '$' */) {
return false;
}
}
return true;
}
/**
* Comparator between two mappings where the original positions are compared.
*
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
* mappings with the same original source/line/column, but different generated
* line and column the same. Useful when searching for a mapping with a
* stubbed out mapping.
*/
function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
var cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0 || onlyCompareOriginal) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByOriginalPositions = compareByOriginalPositions;
function compareByOriginalPositionsNoSource(mappingA, mappingB, onlyCompareOriginal) {
var cmp
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0 || onlyCompareOriginal) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByOriginalPositionsNoSource = compareByOriginalPositionsNoSource;
/**
* Comparator between two mappings with deflated source and name indices where
* the generated positions are compared.
*
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
* mappings with the same generated line and column, but different
* source/name/original line and column the same. Useful when searching for a
* mapping with a stubbed out mapping.
*/
function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
var cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0 || onlyCompareGenerated) {
return cmp;
}
cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
function compareByGeneratedPositionsDeflatedNoLine(mappingA, mappingB, onlyCompareGenerated) {
var cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0 || onlyCompareGenerated) {
return cmp;
}
cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsDeflatedNoLine = compareByGeneratedPositionsDeflatedNoLine;
function strcmp(aStr1, aStr2) {
if (aStr1 === aStr2) {
return 0;
}
if (aStr1 === null) {
return 1; // aStr2 !== null
}
if (aStr2 === null) {
return -1; // aStr1 !== null
}
if (aStr1 > aStr2) {
return 1;
}
return -1;
}
/**
* Comparator between two mappings with inflated source and name strings where
* the generated positions are compared.
*/
function compareByGeneratedPositionsInflated(mappingA, mappingB) {
var cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0) {
return cmp;
}
cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
/**
* Strip any JSON XSSI avoidance prefix from the string (as documented
* in the source maps specification), and then parse the string as
* JSON.
*/
function parseSourceMapInput(str) {
return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ''));
}
exports.parseSourceMapInput = parseSourceMapInput;
/**
* Compute the URL of a source given the the source root, the source's
* URL, and the source map's URL.
*/
function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) {
sourceURL = sourceURL || '';
if (sourceRoot) {
// This follows what Chrome does.
if (sourceRoot[sourceRoot.length - 1] !== '/' && sourceURL[0] !== '/') {
sourceRoot += '/';
}
// The spec says:
// Line 4: An optional source root, useful for relocating source
// files on a server or removing repeated values in the
// “sources” entry. This value is prepended to the individual
// entries in the “source” field.
sourceURL = sourceRoot + sourceURL;
}
// Historically, SourceMapConsumer did not take the sourceMapURL as
// a parameter. This mode is still somewhat supported, which is why
// this code block is conditional. However, it's preferable to pass
// the source map URL to SourceMapConsumer, so that this function
// can implement the source URL resolution algorithm as outlined in
// the spec. This block is basically the equivalent of:
// new URL(sourceURL, sourceMapURL).toString()
// ... except it avoids using URL, which wasn't available in the
// older releases of node still supported by this library.
//
// The spec says:
// If the sources are not absolute URLs after prepending of the
// “sourceRoot”, the sources are resolved relative to the
// SourceMap (like resolving script src in a html document).
if (sourceMapURL) {
var parsed = urlParse(sourceMapURL);
if (!parsed) {
throw new Error("sourceMapURL could not be parsed");
}
if (parsed.path) {
// Strip the last path component, but keep the "/".
var index = parsed.path.lastIndexOf('/');
if (index >= 0) {
parsed.path = parsed.path.substring(0, index + 1);
}
}
sourceURL = join(urlGenerate(parsed), sourceURL);
}
return normalize(sourceURL);
}
exports.computeSourceURL = computeSourceURL;
/***/ }),
/***/ "./node_modules/streamsaver/StreamSaver.js":
/***/ (function(module) {
/*! streamsaver. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
/* global chrome location ReadableStream define MessageChannel TransformStream */
;((name, definition) => {
true
? module.exports = definition()
: 0
})('streamSaver', () => {
'use strict'
const global = typeof window === 'object' ? window : this
if (!global.HTMLElement) console.warn('streamsaver is meant to run on browsers main thread')
let mitmTransporter = null
let supportsTransferable = false
const test = fn => { try { fn() } catch (e) {} }
const ponyfill = global.WebStreamsPolyfill || {}
const isSecureContext = global.isSecureContext
// TODO: Must come up with a real detection test (#69)
let useBlobFallback = /constructor/i.test(global.HTMLElement) || !!global.safari || !!global.WebKitPoint
const downloadStrategy = isSecureContext || 'MozAppearance' in document.documentElement.style
? 'iframe'
: 'navigate'
const streamSaver = {
createWriteStream,
WritableStream: global.WritableStream || ponyfill.WritableStream,
supported: true,
version: { full: '2.0.5', major: 2, minor: 0, dot: 5 },
mitm: 'https://jimmywarting.github.io/StreamSaver.js/mitm.html?version=2.0.0'
}
/**
* create a hidden iframe and append it to the DOM (body)
*
* @param {string} src page to load
* @return {HTMLIFrameElement} page to load
*/
function makeIframe (src) {
if (!src) throw new Error('meh')
const iframe = document.createElement('iframe')
iframe.hidden = true
iframe.src = src
iframe.loaded = false
iframe.name = 'iframe'
iframe.isIframe = true
iframe.postMessage = (...args) => iframe.contentWindow.postMessage(...args)
iframe.addEventListener('load', () => {
iframe.loaded = true
}, { once: true })
document.body.appendChild(iframe)
return iframe
}
/**
* create a popup that simulates the basic things
* of what a iframe can do
*
* @param {string} src page to load
* @return {object} iframe like object
*/
function makePopup (src) {
const options = 'width=200,height=100'
const delegate = document.createDocumentFragment()
const popup = {
frame: global.open(src, 'popup', options),
loaded: false,
isIframe: false,
isPopup: true,
remove () { popup.frame.close() },
addEventListener (...args) { delegate.addEventListener(...args) },
dispatchEvent (...args) { delegate.dispatchEvent(...args) },
removeEventListener (...args) { delegate.removeEventListener(...args) },
postMessage (...args) { popup.frame.postMessage(...args) }
}
const onReady = evt => {
if (evt.source === popup.frame) {
popup.loaded = true
global.removeEventListener('message', onReady)
popup.dispatchEvent(new Event('load'))
}
}
global.addEventListener('message', onReady)
return popup
}
try {
// We can't look for service worker since it may still work on http
new Response(new ReadableStream())
if (isSecureContext && !('serviceWorker' in navigator)) {
useBlobFallback = true
}
} catch (err) {
useBlobFallback = true
}
test(() => {
// Transferable stream was first enabled in chrome v73 behind a flag
const { readable } = new TransformStream()
const mc = new MessageChannel()
mc.port1.postMessage(readable, [readable])
mc.port1.close()
mc.port2.close()
supportsTransferable = true
// Freeze TransformStream object (can only work with native)
Object.defineProperty(streamSaver, 'TransformStream', {
configurable: false,
writable: false,
value: TransformStream
})
})
function loadTransporter () {
if (!mitmTransporter) {
mitmTransporter = isSecureContext
? makeIframe(streamSaver.mitm)
: makePopup(streamSaver.mitm)
}
}
/**
* @param {string} filename filename that should be used
* @param {object} options [description]
* @param {number} size deprecated
* @return {WritableStream<Uint8Array>}
*/
function createWriteStream (filename, options, size) {
let opts = {
size: null,
pathname: null,
writableStrategy: undefined,
readableStrategy: undefined
}
let bytesWritten = 0 // by StreamSaver.js (not the service worker)
let downloadUrl = null
let channel = null
let ts = null
// normalize arguments
if (Number.isFinite(options)) {
[ size, options ] = [ options, size ]
console.warn('[StreamSaver] Deprecated pass an object as 2nd argument when creating a write stream')
opts.size = size
opts.writableStrategy = options
} else if (options && options.highWaterMark) {
console.warn('[StreamSaver] Deprecated pass an object as 2nd argument when creating a write stream')
opts.size = size
opts.writableStrategy = options
} else {
opts = options || {}
}
if (!useBlobFallback) {
loadTransporter()
channel = new MessageChannel()
// Make filename RFC5987 compatible
filename = encodeURIComponent(filename.replace(/\//g, ':'))
.replace(/['()]/g, escape)
.replace(/\*/g, '%2A')
const response = {
transferringReadable: supportsTransferable,
pathname: opts.pathname || Math.random().toString().slice(-6) + '/' + filename,
headers: {
'Content-Type': 'application/octet-stream; charset=utf-8',
'Content-Disposition': "attachment; filename*=UTF-8''" + filename
}
}
if (opts.size) {
response.headers['Content-Length'] = opts.size
}
const args = [ response, '*', [ channel.port2 ] ]
if (supportsTransferable) {
const transformer = downloadStrategy === 'iframe' ? undefined : {
// This transformer & flush method is only used by insecure context.
transform (chunk, controller) {
if (!(chunk instanceof Uint8Array)) {
throw new TypeError('Can only write Uint8Arrays')
}
bytesWritten += chunk.length
controller.enqueue(chunk)
if (downloadUrl) {
location.href = downloadUrl
downloadUrl = null
}
},
flush () {
if (downloadUrl) {
location.href = downloadUrl
}
}
}
ts = new streamSaver.TransformStream(
transformer,
opts.writableStrategy,
opts.readableStrategy
)
const readableStream = ts.readable
channel.port1.postMessage({ readableStream }, [ readableStream ])
}
channel.port1.onmessage = evt => {
// Service worker sent us a link that we should open.
if (evt.data.download) {
// Special treatment for popup...
if (downloadStrategy === 'navigate') {
mitmTransporter.remove()
mitmTransporter = null
if (bytesWritten) {
location.href = evt.data.download
} else {
downloadUrl = evt.data.download
}
} else {
if (mitmTransporter.isPopup) {
mitmTransporter.remove()
mitmTransporter = null
// Special case for firefox, they can keep sw alive with fetch
if (downloadStrategy === 'iframe') {
makeIframe(streamSaver.mitm)
}
}
// We never remove this iframes b/c it can interrupt saving
makeIframe(evt.data.download)
}
} else if (evt.data.abort) {
chunks = []
channel.port1.postMessage('abort') //send back so controller is aborted
channel.port1.onmessage = null
channel.port1.close()
channel.port2.close()
channel = null
}
}
if (mitmTransporter.loaded) {
mitmTransporter.postMessage(...args)
} else {
mitmTransporter.addEventListener('load', () => {
mitmTransporter.postMessage(...args)
}, { once: true })
}
}
let chunks = []
return (!useBlobFallback && ts && ts.writable) || new streamSaver.WritableStream({
write (chunk) {
if (!(chunk instanceof Uint8Array)) {
throw new TypeError('Can only write Uint8Arrays')
}
if (useBlobFallback) {
// Safari... The new IE6
// https://github.com/jimmywarting/StreamSaver.js/issues/69
//
// even though it has everything it fails to download anything
// that comes from the service worker..!
chunks.push(chunk)
return
}
// is called when a new chunk of data is ready to be written
// to the underlying sink. It can return a promise to signal
// success or failure of the write operation. The stream
// implementation guarantees that this method will be called
// only after previous writes have succeeded, and never after
// close or abort is called.
// TODO: Kind of important that service worker respond back when
// it has been written. Otherwise we can't handle backpressure
// EDIT: Transferable streams solves this...
channel.port1.postMessage(chunk)
bytesWritten += chunk.length
if (downloadUrl) {
location.href = downloadUrl
downloadUrl = null
}
},
close () {
if (useBlobFallback) {
const blob = new Blob(chunks, { type: 'application/octet-stream; charset=utf-8' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = filename
link.click()
} else {
channel.port1.postMessage('end')
}
},
abort () {
chunks = []
channel.port1.postMessage('abort')
channel.port1.onmessage = null
channel.port1.close()
channel.port2.close()
channel = null
}
}, opts.writableStrategy)
}
return streamSaver
})
/***/ }),
/***/ "./src/lib/GM.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ JU: () => (/* binding */ _GM_deleteValue),
/* harmony export */ JX: () => (/* binding */ _GM_info),
/* harmony export */ er: () => (/* binding */ _GM_getValue),
/* harmony export */ mN: () => (/* binding */ _GM_setValue),
/* harmony export */ nV: () => (/* binding */ _GM_xmlhttpRequest)
/* harmony export */ });
function get_GM_info() {
if (typeof GM_info !== "undefined") {
return GM_info;
}
if (typeof GM !== "undefined" && typeof GM.info !== "undefined") {
return GM.info;
}
throw new Error("Not found: GM_info and GM.info!");
}
const _GM_info = get_GM_info();
function _GM_xmlhttpRequest(details) {
if (typeof GM_xmlhttpRequest === "function") {
GM_xmlhttpRequest(details);
return;
}
if (typeof GM !== "undefined" && typeof GM.xmlHttpRequest === "function") {
GM.xmlHttpRequest(details);
return;
}
throw new Error("Not found: GM_xmlhttpRequest or GM.xmlHttpRequest!");
}
async function _GM_setValue(name, value) {
if (typeof GM_setValue === "function") {
return GM_setValue(name, value);
}
if (typeof GM !== "undefined" && typeof GM.setValue === "function") {
return await GM.setValue(name, value);
}
throw new Error("Not found: GM_setValue or GM.setValue!");
}
async function _GM_getValue(name, defaultValue) {
if (typeof GM_getValue === "function") {
return GM_getValue(name, defaultValue);
}
if (typeof GM !== "undefined" && typeof GM.getValue === "function") {
return await GM.getValue(name, defaultValue);
}
throw new Error("Not found: GM_getValue or GM.getValue!");
}
async function _GM_deleteValue(name) {
if (typeof GM_deleteValue === "function") {
return GM_deleteValue(name);
}
if (typeof GM !== "undefined" && typeof GM.deleteValue === "function") {
return await GM.deleteValue(name);
}
throw new Error("Not found: GM_deleteValue or GM.deleteValue!");
}
/***/ }),
/***/ "./src/lib/attachments.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Ld: () => (/* binding */ putAttachmentClassCache),
/* harmony export */ VJ: () => (/* binding */ getRandomName),
/* harmony export */ _s: () => (/* binding */ getAttachmentClassCache),
/* harmony export */ an: () => (/* binding */ getExt),
/* harmony export */ "if": () => (/* binding */ getAttachment),
/* harmony export */ rd: () => (/* binding */ clearAttachmentClassCache)
/* harmony export */ });
/* harmony import */ var _main_Attachment__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/main/Attachment.ts");
/* harmony import */ var _hash__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/hash.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _misc__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/misc.ts");
/* harmony import */ var magic_bytes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/magic-bytes.js/dist/index.js");
/* harmony import */ var magic_bytes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(magic_bytes_js__WEBPACK_IMPORTED_MODULE_0__);
let attachmentClassCache = [];
function getAttachmentClassCache(url) {
return attachmentClassCache.find((attachmentClass) => attachmentClass.url === url);
}
function putAttachmentClassCache(attachmentClass) {
attachmentClassCache.push(attachmentClass);
return true;
}
function clearAttachmentClassCache() {
attachmentClassCache = [];
}
async function getAttachment(url, mode, prefix = "", noMD5 = false, comments = getRandomName(), options) {
if (mode === "naive") {
const u = new URL(url);
if (document.location.protocol === "https:" && u.protocol === "http:") {
u.protocol = document.location.protocol;
url = u.href;
}
}
const imgClassCache = getAttachmentClassCache(url);
if (imgClassCache) {
return imgClassCache;
}
const imgClass = new _main_Attachment__WEBPACK_IMPORTED_MODULE_1__/* .AttachmentClass */ .q(url, comments, mode, options?.referrerMode, options?.customReferer);
imgClass.comments = comments;
const blob = await imgClass.init();
if (blob) {
if (noMD5) {
imgClass.name = getLastPart(url);
}
else {
const hash = await (0,_hash__WEBPACK_IMPORTED_MODULE_2__/* .calculateSha1 */ .Q)(blob);
const ext = await getExt(blob, url);
imgClass.name = [prefix, hash, ".", ext].join("");
}
}
putAttachmentClassCache(imgClass);
_log__WEBPACK_IMPORTED_MODULE_3___default().debug(`[attachment]下载附件完成! url:${imgClass.url}, name: ${imgClass.name}`);
return imgClass;
}
function getRandomName() {
return `__${(0,_misc__WEBPACK_IMPORTED_MODULE_4__/* .randomUUID */ .N4)()}__`;
}
async function getExt(b, u) {
const ext = (0,magic_bytes_js__WEBPACK_IMPORTED_MODULE_0__.filetypeextension)(new Uint8Array(await b.arrayBuffer()));
if (ext.length !== 0) {
return ext[0];
}
const contentType = b.type.split(";")[0].split("/")[1];
const contentTypeBlackList = ["octet-stream"];
if (contentTypeBlackList.includes(contentType)) {
return getExtFromUrl(u);
}
else {
return contentType;
}
}
function getExtFromUrl(u) {
const _u = new URL(u);
const p = _u.pathname;
return p.substring(p.lastIndexOf(".") + 1);
}
function getLastPart(u) {
const _u = new URL(u);
const p = _u.pathname;
return p.substring(p.lastIndexOf("/") + 1);
}
/***/ }),
/***/ "./src/lib/cleanDOM.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ N0: () => (/* binding */ convertFixWidth),
/* harmony export */ U9: () => (/* binding */ convertBr),
/* harmony export */ WF: () => (/* binding */ convertFixWidthText),
/* harmony export */ an: () => (/* binding */ cleanDOM),
/* harmony export */ eu: () => (/* binding */ isFixWidth),
/* harmony export */ is: () => (/* binding */ htmlTrim)
/* harmony export */ });
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _attachments__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
const BlockElements = [
"address",
"article",
"aside",
"blockquote",
"details",
"dialog",
"dd",
"div",
"dl",
"dt",
"fieldset",
"figcaption",
"figure",
"footer",
"form",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"header",
"hgroup",
"hr",
"li",
"main",
"nav",
"ol",
"p",
"pre",
"section",
"table",
"ul",
];
const InlineElements = [
"a",
"abbr",
"acronym",
"audio",
"b",
"bdi",
"bdo",
"big",
"br",
"button",
"canvas",
"cite",
"code",
"data",
"datalist",
"del",
"dfn",
"em",
"embed",
"i",
"iframe",
"img",
"input",
"ins",
"kbd",
"label",
"map",
"mark",
"meter",
"noscript",
"object",
"output",
"picture",
"progress",
"q",
"ruby",
"s",
"samp",
"script",
"select",
"slot",
"small",
"span",
"font",
"strong",
"sub",
"sup",
"svg",
"template",
"textarea",
"time",
"u",
"tt",
"var",
"video",
"wbr",
];
const keepElements = [
"aside",
"blockquote",
"details",
"figure",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"hr",
"ul",
"ol",
"li",
"pre",
];
const IgnoreElements = [
"#comment",
"fieldset",
"legend",
"input",
"label",
"form",
"button",
"canvas",
"datalist",
"embed",
"iframe",
"map",
"meter",
"noscript",
"object",
"output",
"progress",
"script",
"style",
"link",
"select",
"slot",
"svg",
"template",
"video",
"wbr",
];
function isBaseElem(node) {
const nodeName = node.nodeName.toLowerCase();
if (node instanceof Text) {
return true;
}
if (node.childElementCount === 0) {
return true;
}
if (InlineElements.includes(nodeName)) {
return true;
}
return Array.from(node.children).every((child) => {
const n = child.nodeName.toLowerCase();
return InlineElements.includes(n);
});
}
function isBaseElemWithKeep(node) {
const nodeName = node.nodeName.toLowerCase();
if (keepElements.includes(nodeName)) {
return true;
}
return isBaseElem(node);
}
function* findBase(elem, withKeep = true) {
let is;
if (withKeep) {
is = isBaseElemWithKeep;
}
else {
is = isBaseElem;
}
const childNodes = Array.from(elem.childNodes).filter((node) => {
if (node instanceof Text) {
const textContent = node.textContent;
if (textContent === null) {
return false;
}
if (textContent.trim() === "") {
return false;
}
}
return true;
});
for (const child of childNodes) {
const childNodeName = child.nodeName.toLowerCase();
if (!IgnoreElements.includes(childNodeName)) {
if (is(child)) {
yield child;
}
else {
yield* findBase(child, withKeep);
}
}
}
}
async function cleanDOM(elem, imgMode, options) {
const baseNodes = [...findBase(elem)];
const _obj = await loop(baseNodes, document.createElement("div"));
const obj = await awaitAttachments(_obj);
return postHook(obj);
async function blockElement(element) {
const map = new Map();
const divList = [
"article",
"dialog",
"div",
"footer",
"header",
"main",
"section",
"hgroup",
];
function div(elem) {
if (elem instanceof HTMLElement) {
const nodes = [...findBase(elem)];
return loop(nodes, document.createElement("div"));
}
return null;
}
divList.forEach((n) => map.set(n, div));
const pList = ["address", "p", "dd", "dt", "figcaption", "dl"];
function p(elem) {
if (elem instanceof HTMLElement) {
const nodes = [...findBase(elem)];
return loop(nodes, document.createElement("p"));
}
return null;
}
pList.forEach((n) => map.set(n, p));
const blockquoteList = ["aside", "blockquote"];
async function blockquote(elem) {
if (elem instanceof HTMLElement) {
const nodes = [...findBase(elem)];
const { dom, text, images } = await loop(nodes, document.createElement("blockquote"));
const outText = text
.split("\n")
.map((l) => l.replace(/^/, "> "))
.join("\n");
return {
dom,
text: outText,
images,
};
}
return null;
}
blockquoteList.forEach((n) => map.set(n, blockquote));
const headerList = ["h1", "h2", "h3", "h4", "h5", "h6"];
function header(elem) {
if (elem instanceof HTMLElement) {
const nodeName = elem.nodeName.toLowerCase();
const n = parseInt(nodeName.substring(1));
const dom = document.createElement(nodeName);
dom.innerHTML = elem.innerHTML;
const text = "#".repeat(n) + " " + elem.innerText;
const images = [];
return {
dom,
text,
images,
};
}
return null;
}
headerList.forEach((n) => map.set(n, header));
const preList = ["pre", "textarea"];
function pre(elem) {
if (elem instanceof HTMLElement) {
const dom = document.createElement("pre");
dom.innerHTML = elem.innerHTML;
const text = "```\n" + elem.innerText + "\n```";
const images = [];
return {
dom,
text,
images,
};
}
return null;
}
preList.forEach((n) => map.set(n, pre));
function hr(elem) {
if (elem instanceof HTMLHRElement) {
const dom = document.createElement("hr");
const text = "-".repeat(20);
const images = [];
return {
dom,
text,
images,
};
}
return null;
}
map.set("hr", hr);
async function common1(boldName, baseName, elem) {
const bold = elem.querySelector(boldName);
let s;
let sText = "";
if (bold instanceof HTMLElement) {
s = document.createElement(boldName);
s.innerHTML = bold.innerHTML;
sText = "**" + bold.innerText + "**";
bold.remove();
}
const base = document.createElement(baseName);
if (s)
base.appendChild(s);
const nodes = [...findBase(elem)];
const { dom, text, images } = await loop(nodes, base);
const outText = sText + "\n\n" + text;
return {
dom,
text: outText,
images,
};
}
function details(elem) {
return common1("summary", "details", elem);
}
map.set("details", details);
function figure(elem) {
return common1("figcaption", "figure", elem);
}
map.set("figure", figure);
function listItem(elem) {
if (elem instanceof HTMLLIElement) {
const dom = document.createElement("li");
dom.innerHTML = elem.innerHTML;
let prefix = "- ";
const parent = elem.parentNode;
if (parent instanceof HTMLOListElement) {
const start = parent.getAttribute("start");
const index = Array.prototype.indexOf.call(parent.children, elem);
prefix = (start ? Number(start) + index : index + 1) + ". ";
}
const text = prefix + elem.innerText;
const images = [];
return {
dom,
text,
images,
};
}
return null;
}
map.set("li", listItem);
const listList = ["ul", "ol"];
function list(elem) {
const nodeName = elem.nodeName.toLowerCase();
if (elem instanceof HTMLUListElement ||
elem instanceof HTMLOListElement) {
const tdom = document.createElement(nodeName);
const nodes = [...findBase(elem)];
return loop(nodes, tdom);
}
return null;
}
listList.forEach((n) => map.set(n, list));
function table(elem) {
if (elem instanceof HTMLTableElement) {
const dom = elem.cloneNode(true);
const text = processTable(elem);
const images = [];
return { dom, text, images };
}
return null;
function fixText(text) {
return text.trim().replaceAll("\t", "");
}
function processTable(tableDom) {
let markdown_string = "";
let table_header = "|";
let table_header_footer = "|";
let table_rows = "";
let table_header_found = false;
let table_header_cell_count = 0;
let prev_row_cell_count = 0;
Array.from(tableDom.querySelectorAll("thead > tr > td")).forEach((td) => {
table_header_cell_count++;
table_header = table_header + fixText(td.innerText) + "|";
table_header_footer = table_header_footer + "--- |";
table_header_found = true;
});
Array.from(tableDom.querySelectorAll("tr")).forEach((tr) => {
if (!table_header_found) {
Array.from(tr.querySelectorAll("th")).forEach((th) => {
table_header_cell_count++;
table_header = table_header + fixText(th.innerText) + "|";
table_header_footer = table_header_footer + "--- |";
table_header_found = true;
});
}
let table_row = "";
let curr_row_cell_count = 0;
Array.from(tr.querySelectorAll("td"))
.filter((td) => !Array.from(tableDom.querySelectorAll("thead > tr > td")).includes(td))
.forEach((td) => {
curr_row_cell_count++;
table_row = table_row + fixText(td.innerText) + "|";
});
if (prev_row_cell_count != 0 &&
curr_row_cell_count != prev_row_cell_count) {
markdown_string =
"ERROR: Your HTML table rows don't have the same number of cells. Colspan not supported.";
return false;
}
if (curr_row_cell_count) {
table_rows += "|" + table_row + "\n";
prev_row_cell_count = curr_row_cell_count;
}
});
if (markdown_string == "") {
if (table_header_found) {
if (table_header_cell_count != prev_row_cell_count) {
throw new Error("ERROR: The number of cells in your header doesn't match the number of cells in your rows.");
}
}
else {
for (let i = 0; i < prev_row_cell_count; i++) {
table_header = table_header + "|";
table_header_footer = table_header_footer + "--- |";
}
}
markdown_string += table_header + "\n";
markdown_string += table_header_footer + "\n";
markdown_string += table_rows;
}
return markdown_string;
}
}
map.set("table", table);
const nodeName = element.nodeName.toLowerCase();
const fn = map.get(nodeName) ?? p;
const obj = await fn(element);
if (!obj) {
return null;
}
const { dom, text, images } = obj;
if (element.getAttribute("data-keep")) {
const dk = element.getAttribute("data-keep");
const keeps = dk.split(",").map((k) => k.trim());
keeps.forEach((k) => {
if (dom instanceof HTMLElement && element.getAttribute(k)) {
dom.setAttribute(k, element.getAttribute(k));
}
});
}
return { dom, text, images };
}
async function inlineElement(element) {
const map = new Map();
const defaultList = [
"abbr",
"acronym",
"bdi",
"bdo",
"cite",
"data",
"dfn",
"span",
"font",
"time",
"u",
"tt",
"#text",
];
async function defaultHandler(elem) {
if ((elem instanceof HTMLElement && elem.childElementCount === 0) ||
elem instanceof Text) {
let text;
if (elem instanceof HTMLElement) {
text = elem.innerText.trim();
}
if (elem instanceof Text) {
text = elem.textContent?.trim() ?? "";
}
if (typeof text === "string") {
const dom = new Text(text);
const images = [];
return {
dom,
text: text.replaceAll("\n", ""),
images,
};
}
}
if (elem instanceof HTMLElement && elem.childElementCount !== 0) {
const nodes = [...findBase(elem)];
const { dom, text, images } = await loop(nodes, document.createElement(elem.nodeName.toLowerCase()));
return {
dom,
text,
images,
};
}
return null;
}
defaultList.forEach((n) => map.set(n, defaultHandler));
async function a(elem) {
if (elem instanceof HTMLAnchorElement) {
if (elem.childElementCount === 0) {
if (elem.href.startsWith("https://") ||
elem.href.startsWith("http://")) {
const { href, textContent } = elem;
const dom = document.createElement("a");
if (elem.getAttribute("href")?.startsWith("#")) {
dom.href = elem.getAttribute("href");
}
else {
dom.href = href;
}
dom.textContent = textContent;
const text = `[${textContent}](${href})`;
const images = [];
return {
dom,
text,
images,
};
}
}
else {
const outterA = document.createElement("a");
if (elem.href.startsWith("https://") ||
elem.href.startsWith("http://")) {
outterA.href = elem.href;
}
const nodes = [...findBase(elem)];
const { dom, text, images } = await loop(nodes, outterA);
return {
dom,
text,
images,
};
}
}
return null;
}
map.set("a", a);
function getImg(url) {
const imgClassCache = (0,_attachments__WEBPACK_IMPORTED_MODULE_0__/* .getAttachmentClassCache */ ._s)(url);
if (imgClassCache) {
const dom = document.createElement("img");
dom.setAttribute("data-src-address", imgClassCache.name);
dom.alt = url;
dom.title = url;
const text = `![${url}](${imgClassCache.name})`;
const images = [imgClassCache];
return {
dom,
text,
images,
};
}
else {
const comments = (0,_attachments__WEBPACK_IMPORTED_MODULE_0__/* .getRandomName */ .VJ)();
const noMd5 = options?.keepImageName ?? false;
const imgOptions = {
referrerMode: options?.referrerMode,
customReferer: options?.customReferer,
};
const imgClass = (0,_attachments__WEBPACK_IMPORTED_MODULE_0__/* .getAttachment */ ["if"])(url, imgMode, "chapter-", noMd5, comments, imgOptions);
const dom = document.createElement("img");
dom.setAttribute("data-src-address", comments);
dom.alt = url;
dom.title = url;
const text = `![${url}](${comments})`;
const images = [imgClass];
return {
dom,
text,
images,
};
}
}
function img(elem) {
if (elem instanceof HTMLImageElement) {
const url = elem.src;
return getImg(url);
}
return null;
}
map.set("img", img);
function audio(elem) {
if (elem instanceof HTMLAudioElement) {
const url = elem.src;
const attachmentCache = (0,_attachments__WEBPACK_IMPORTED_MODULE_0__/* .getAttachmentClassCache */ ._s)(url);
if (attachmentCache) {
const dom = document.createElement("audio");
dom.innerText = "Your browser does not support the audio element.";
dom.setAttribute("data-src-address", attachmentCache.name);
dom.setAttribute("controls", "");
dom.setAttribute("preload", "metadata");
dom.title = url;
const text = dom.outerHTML;
const images = [attachmentCache];
return {
dom,
text,
images,
};
}
else {
const comments = (0,_attachments__WEBPACK_IMPORTED_MODULE_0__/* .getRandomName */ .VJ)();
const noMd5 = options?.keepImageName ?? false;
const attachmentOptions = {
referrerMode: options?.referrerMode,
customReferer: options?.customReferer,
};
const attachment = (0,_attachments__WEBPACK_IMPORTED_MODULE_0__/* .getAttachment */ ["if"])(url, imgMode, "chapter-", noMd5, comments, attachmentOptions);
const dom = document.createElement("audio");
dom.innerText = "Your browser does not support the audio element.";
dom.setAttribute("data-src-address", comments);
dom.setAttribute("controls", "");
dom.setAttribute("preload", "metadata");
dom.title = url;
const text = dom.outerHTML;
const images = [attachment];
return {
dom,
text,
images,
};
}
}
return null;
}
map.set("audio", audio);
function picture(elem) {
if (elem instanceof HTMLPictureElement) {
const img = elem.querySelector("img");
if (img) {
const url = img.src;
return getImg(url);
}
else {
_log__WEBPACK_IMPORTED_MODULE_1___default().warn("[cleanDom][picture]未发现 img", elem);
return null;
}
}
return null;
}
map.set("picture", picture);
function ruby(elem) {
if (elem instanceof HTMLElement) {
const nodeArray = Array.from(elem.childNodes).map((node) => {
if (node instanceof Text && node.textContent?.trim()) {
const rb = document.createElement("rb");
rb.innerText = node.textContent.trim();
return rb;
}
else {
return node.cloneNode(true);
}
});
const dom = document.createElement("ruby");
nodeArray.forEach((node) => dom.appendChild(node));
let text;
if (nodeArray.some((node) => node.nodeName.toLowerCase() === "rt") &&
nodeArray.some((node) => node.nodeName.toLowerCase() === "rb")) {
text =
nodeArray
.filter((node) => node.nodeName.toLowerCase() === "rb")
.map((n) => n.innerText)
.join() +
"(" +
nodeArray
.filter((node) => node.nodeName.toLowerCase() === "rt")
.map((n) => n.innerText)
.join() +
")";
}
else {
text = elem.innerText;
}
const images = [];
return {
dom,
text,
images,
};
}
return null;
}
map.set("ruby", ruby);
function br() {
const dom = document.createElement("br");
const text = "\n";
const images = [];
return {
dom,
text,
images,
};
}
map.set("br", br);
async function common(nodeName, getText, elem) {
if (elem instanceof HTMLElement) {
if (elem.childElementCount === 0) {
const textContent = elem.innerText.trim();
const dom = document.createElement(nodeName);
dom.innerText = textContent;
const text = getText(textContent);
const images = [];
return {
dom,
text,
images,
};
}
else {
const nodes = [...findBase(elem)];
const { dom, text, images } = await loop(nodes, document.createElement(nodeName));
return {
dom,
text,
images,
};
}
}
return null;
}
const strongList = ["b", "big", "mark", "samp", "strong"];
function strong(elem) {
return common("strong", (textContent) => `**${textContent.replaceAll("\n", "**\n**")}**`, elem);
}
strongList.forEach((n) => map.set(n, strong));
const codeList = ["code", "kbd"];
function code(elem) {
return common("code", (textContent) => `\`${textContent}\``, elem);
}
codeList.forEach((n) => map.set(n, code));
const sList = ["del", "s"];
function s(elem) {
return common("s", (textContent) => `~~${textContent}~~`, elem);
}
sList.forEach((n) => map.set(n, s));
const emList = ["em", "i", "q", "var"];
function em(elem) {
return common("em", (textContent) => `*${textContent}*`, elem);
}
emList.forEach((n) => map.set(n, em));
function ins(elem) {
return common("ins", (textContent) => `++${textContent}++`, elem);
}
map.set("ins", ins);
function small(elem) {
return common("small", (textContent) => `<small>${textContent}</small>`, elem);
}
map.set("small", small);
function sup(elem) {
return common("sup", (textContent) => `<sup>${textContent}</sup>`, elem);
}
map.set("sup", sup);
function sub(elem) {
return common("sub", (textContent) => `<sub>${textContent}</sub>`, elem);
}
map.set("sub", sub);
const nodeName = element.nodeName.toLowerCase();
const fn = map.get(nodeName);
if (fn) {
const obj = await fn(element);
if (!obj) {
return null;
}
const { dom, text, images } = obj;
if (element instanceof Element && element.getAttribute("data-keep")) {
const dk = element.getAttribute("data-keep");
const keeps = dk.split(",").map((k) => k.trim());
keeps.forEach((k) => {
if (dom instanceof HTMLElement && element.getAttribute(k)) {
dom.setAttribute(k, element.getAttribute(k));
}
});
}
return { dom, text, images };
}
else {
const output = defaultHandler(element);
_log__WEBPACK_IMPORTED_MODULE_1___default().warn("[cleanDom]发现未知行内元素!");
_log__WEBPACK_IMPORTED_MODULE_1___default().warn([element.nodeName.toLowerCase(), element]);
return output;
}
}
async function loop(nodes, _outDom) {
let _outText = "";
let _outImages = [];
for (const node of nodes) {
const bNname = node.nodeName.toLowerCase();
if (bNname === "textarea" || BlockElements.includes(bNname)) {
if (node instanceof HTMLElement) {
const tobj = await blockElement(node);
if (tobj) {
const { dom: tdom, text: ttext, images: timages } = tobj;
_outDom.appendChild(tdom);
_outText = _outText + "\n" + ttext + "\n";
_outImages = _outImages.concat(timages);
continue;
}
}
}
if (node instanceof Text || InlineElements.includes(bNname)) {
const tobj = await inlineElement(node);
if (tobj) {
const { dom: tdom, text: ttext, images: timages } = tobj;
_outDom.appendChild(tdom);
_outText = _outText + ttext;
_outImages = _outImages.concat(timages);
continue;
}
}
}
return {
dom: _outDom,
text: _outText,
images: _outImages,
};
}
async function awaitAttachments({ dom, text, images, }) {
const attachments = await Promise.all(images);
attachments.forEach((attach) => {
if (attach.comments) {
dom.innerHTML = dom.innerHTML.replaceAll(attach.comments, attach.name);
text = text.replaceAll(attach.comments, attach.name);
}
});
return {
dom,
text,
images: attachments,
};
}
function postHook({ dom, text, images, }) {
htmlTrim(dom);
dom = convertBr(dom);
Array.from(dom.children).forEach((child) => child.replaceWith(convertBr(child)));
convertBlankParagraphElement(dom);
text = text.trim();
return {
dom,
text,
images,
};
}
}
function htmlTrim(dom) {
const childNodes = Array.from(dom.childNodes);
remove(childNodes);
const childNodesR = Array.from(dom.childNodes).reverse();
remove(childNodesR);
function remove(nodes) {
for (const node of nodes) {
if (node instanceof Text) {
if (node.textContent?.trim() === "") {
node.remove();
continue;
}
else {
break;
}
}
if (node instanceof HTMLBRElement) {
node.remove();
continue;
}
if (node instanceof HTMLParagraphElement && isBlankParagraph(node)) {
node.remove();
continue;
}
if (node instanceof HTMLElement && node.nodeName.toLowerCase() !== "br") {
break;
}
}
}
}
function isBlankParagraph(node) {
return (node instanceof HTMLParagraphElement &&
node.innerText.trim() === "" &&
Array.from(node.childNodes).every((n) => n instanceof Text));
}
function convertBr(dom, force = false) {
if (onlyTextAndBr(dom) && (countBr(dom) > 4 || force)) {
const outDom = document.createElement("div");
const childNodes = dom.childNodes;
let brCount = 0;
let buffer = [];
for (const node of Array.from(childNodes)) {
if (node instanceof HTMLBRElement) {
if (brCount === 0 && buffer.length !== 0) {
const p = document.createElement("p");
buffer.forEach((n) => p.appendChild(n));
outDom.appendChild(p);
buffer = [];
}
brCount++;
continue;
}
if (node instanceof HTMLHRElement) {
brCount = 0;
if (buffer.length !== 0) {
const p = document.createElement("p");
buffer.forEach((n) => p.appendChild(n));
outDom.appendChild(p);
buffer = [];
}
const hr = document.createElement("hr");
outDom.appendChild(hr);
continue;
}
if (brCount === 0) {
buffer.push(node);
continue;
}
else {
if (brCount > 2) {
let brRemainder = brCount - 2;
const brp = document.createElement("p");
while (brRemainder > 0) {
brRemainder--;
const br = document.createElement("br");
brp.appendChild(br);
}
outDom.appendChild(brp);
}
brCount = 0;
buffer.push(node);
continue;
}
}
brCount = 0;
if (buffer.length !== 0) {
const p = document.createElement("p");
buffer.forEach((n) => p.appendChild(n));
outDom.appendChild(p);
buffer = [];
}
return outDom;
}
else {
return dom;
}
function countBr(d) {
return Array.from(d.childNodes).filter((n) => n instanceof HTMLBRElement)
.length;
}
function onlyTextAndBr(d) {
return Array.from(d.childNodes)
.map((n) => n.nodeName.toLowerCase())
.every((nn) => ["#text", "hr", ...InlineElements].includes(nn));
}
}
function convertBlankParagraphElement(dom) {
const nodes = Array.from(dom.children);
let count = 0;
let buffer = [];
for (const node of nodes) {
if (isBlankParagraph(node)) {
count++;
buffer.push(node);
}
else if (count !== 0) {
const p = document.createElement("p");
while (count > 0) {
count--;
const br = document.createElement("br");
p.appendChild(br);
}
buffer[0].replaceWith(p);
buffer.forEach((n) => n.remove());
count = 0;
buffer = [];
}
}
}
function convertFixWidthText(node, width = 35, out = document.createElement("div")) {
const ns = node.textContent?.split("\n") ?? [];
let text = "";
for (const n of ns) {
if (n === "") {
out.appendChild(new Text(text));
out.appendChild(document.createElement("br"));
text = "";
continue;
}
if ((0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(n) > width - 5 && (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(n) < width + 5) {
text = text + n;
continue;
}
else {
if (text !== "") {
text = text + n;
out.appendChild(new Text(text));
out.appendChild(document.createElement("br"));
text = "";
continue;
}
else {
out.appendChild(new Text(n));
out.appendChild(document.createElement("br"));
continue;
}
}
}
if (text !== "") {
out.appendChild(new Text(text));
out.appendChild(document.createElement("br"));
text = "";
}
htmlTrim(out);
return convertBr(out);
}
function convertFixWidth(node, width = 35) {
Array.from(node.querySelectorAll("br")).forEach((node) => {
const previous = node.previousSibling;
const next = node.nextSibling;
if (previous instanceof Text &&
next instanceof Text &&
(previous.textContent ? (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(previous.textContent) : 0) >
width - 5 &&
(previous.textContent ? (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(previous.textContent) : 0) <
width + 5) {
node.remove();
}
});
const group = (texts) => {
const out = [];
let group = [];
let whole = "";
for (const text of texts) {
const w = text.wholeText;
if (whole !== w) {
if (group.length !== 0) {
out.push(group);
}
whole = w;
group = [text];
}
else {
group.push(text);
}
}
if (group.length !== 0) {
out.push(group);
}
return out;
};
const merge = (groups) => {
for (const g of groups) {
const old = g[0];
const newText = new Text(old.wholeText);
old.replaceWith(newText);
g.forEach((t) => t.remove());
}
};
const ts = Array.from(node.childNodes).filter((node) => node instanceof Text && node.wholeText !== node.textContent);
const gts = group(ts);
merge(gts);
Array.from(node.childNodes)
.filter((node) => node instanceof Text)
.forEach((text) => {
const p = convertFixWidthText(text, width);
text.replaceWith(p);
});
Array.from(node.querySelectorAll("p"))
.filter((p) => p.innerText.trim() === "" &&
(0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .getPreviousSibling */ .UN)(p) instanceof HTMLElement &&
(0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .getNextSibling */ .wX)(p) instanceof HTMLElement)
.forEach((p) => p.remove());
Array.from(node.querySelectorAll("p"))
.filter((p) => (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .getPreviousBrCount */ .Jw)(p) === 2)
.forEach((p) => (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .removePreviousBr */ .S0)(p));
if (isFixWidthP(node)) {
const ps = Array.from(node.querySelectorAll("p"));
let text = "";
for (const node of ps) {
const n = node.innerText.trim();
if ((0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(n) > width - 5 && (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(n) < width + 5) {
text = text + n;
node.remove();
continue;
}
else {
if (text !== "") {
text = text + n;
const newP = document.createElement("p");
newP.innerText = text;
node.replaceWith(newP);
text = "";
continue;
}
else {
continue;
}
}
}
}
function isFixWidthP(node) {
const lengths = Array.from(node.querySelectorAll("p")).map((p) => (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(p.innerText.trim()));
const lt = lengths.filter((i) => i > width + 5).length;
return lt < 5;
}
}
function isFixWidth(node, width = 35) {
let ns;
if (node instanceof Text) {
ns = node.textContent?.split("\n").map((n) => n.trim()) ?? [];
}
if (node instanceof HTMLElement) {
const reducer = (out, cur) => {
if (cur instanceof Text) {
const t = cur.textContent?.trim() ?? "";
if (t.includes("\n")) {
t.split("\n")
.map((n) => n.trim())
.forEach((n) => out.push(n));
return out;
}
else {
out.push(t);
return out;
}
}
else {
return out;
}
};
ns = Array.from(node.childNodes).reduce(reducer, []);
}
if (!ns) {
throw new Error("ns is null");
}
const lengths = ns.map((l) => (0,_dom__WEBPACK_IMPORTED_MODULE_2__/* .fullWidthLength */ .QJ)(l));
const lt = lengths.filter((i) => i > width + 5).length;
return lt < 5;
}
/***/ }),
/***/ "./src/lib/dom.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Fv: () => (/* binding */ childNodesCopy),
/* harmony export */ Jw: () => (/* binding */ getPreviousBrCount),
/* harmony export */ K4: () => (/* binding */ getNodeTextLength),
/* harmony export */ Md: () => (/* binding */ insertBrBeforeText),
/* harmony export */ QJ: () => (/* binding */ fullWidthLength),
/* harmony export */ S0: () => (/* binding */ removePreviousBr),
/* harmony export */ Sf: () => (/* binding */ rm2),
/* harmony export */ UN: () => (/* binding */ getPreviousSibling),
/* harmony export */ Zn: () => (/* binding */ escapeHTML),
/* harmony export */ _r: () => (/* binding */ createStyle),
/* harmony export */ a_: () => (/* binding */ createEl),
/* harmony export */ d6: () => (/* binding */ sandboxed),
/* harmony export */ dK: () => (/* binding */ isHidden),
/* harmony export */ e_: () => (/* binding */ getMaxDepth),
/* harmony export */ j3: () => (/* binding */ rms),
/* harmony export */ pI: () => (/* binding */ convertHTMLtoXHTML),
/* harmony export */ rm: () => (/* binding */ rm),
/* harmony export */ wX: () => (/* binding */ getNextSibling)
/* harmony export */ });
/* unused harmony export getCookie */
function rm(selector, all = false, dom) {
if (all) {
const rs = dom.querySelectorAll(selector);
rs.forEach((e) => e.remove());
}
else {
const r = dom.querySelector(selector);
if (r) {
r.remove();
}
}
}
function rm2(filters, dom) {
function doRemove(nodes) {
Array.from(nodes.childNodes).forEach((node) => {
let text;
if (node.nodeName === "#text") {
text = node.textContent ?? "";
}
else {
text = node.innerText ?? "";
}
if (text.length < 200 || node instanceof Text) {
for (const filter of filters) {
if (filter instanceof RegExp) {
if (filter.test(text)) {
node.remove();
}
}
if (typeof filter === "string") {
if (text.includes(filter)) {
node.remove();
}
}
}
}
else {
doRemove(node);
}
});
}
doRemove(dom);
}
function rms(filters, dom) {
for (const ad of filters) {
if (typeof ad === "string") {
dom.innerHTML = dom.innerHTML.replaceAll(ad, "");
}
else if (ad instanceof RegExp) {
dom.innerHTML = dom.innerHTML.replace(ad, "");
}
}
return dom;
}
function childNodesCopy(src, dest) {
const childrens = Array.from(src.childNodes);
childrens.forEach((node) => dest.appendChild(node));
}
function getMaxDepth(element) {
const descendants = element.querySelectorAll("*");
const depths = Array.from(descendants)
.filter((elem) => elem.childElementCount === 0)
.map((elem) => getDepth(elem, 0));
return Math.max(...depths);
function getDepth(elem, depth) {
if (element.isSameNode(elem)) {
return depth;
}
else {
const parentElement = elem.parentElement;
if (parentElement) {
return getDepth(parentElement, depth + 1);
}
else {
return depth;
}
}
}
}
function getNodeTextLength(element) {
return Array.from(element.childNodes)
.filter((node) => node.nodeName === "#text")
.reduce((sum, curNode) => {
if (!sum) {
sum = 0;
}
sum = sum + (curNode.textContent?.trim().length ?? 0);
return sum;
}, 0);
}
function sandboxed(code) {
const frame = document.createElement("iframe");
document.body.appendChild(frame);
const argVerify = /^[$A-Z_][0-9A-Z_$]*$/i;
if (frame.contentWindow) {
const F = frame.contentWindow.Function;
const args = Object.keys(frame.contentWindow)
.filter((it) => argVerify.test(it))
.join();
document.body.removeChild(frame);
return F(args, code)();
}
}
function getCookie(name) {
const reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
const arr = document.cookie.match(reg);
if (arr) {
return arr[2];
}
else {
return null;
}
}
function createEl(el) {
const _el = document.createElement("div");
_el.innerHTML = el;
if (_el.childElementCount === 1 && _el.firstElementChild) {
return _el.firstElementChild;
}
else {
throw new Error("Create HTMLElement Failed!");
}
}
function createStyle(style, id) {
const el = createEl(`<style>${style}</style>`);
if (id) {
el.id = id;
}
return el;
}
function getNextSibling(node) {
if (node.nextSibling instanceof HTMLElement) {
return node.nextSibling;
}
if (node.nextSibling instanceof Text) {
if (node.nextSibling.textContent?.trim() !== "") {
return node.nextSibling;
}
else {
return node.nextSibling.nextSibling;
}
}
}
function getPreviousSibling(node) {
if (node.previousSibling instanceof HTMLElement) {
return node.previousSibling;
}
if (node.previousSibling instanceof Text) {
if (node.previousSibling.textContent?.trim() !== "") {
return node.previousSibling;
}
else {
return node.previousSibling.previousSibling;
}
}
}
function getPreviousBrCount(node) {
const previous = getPreviousSibling(node);
if (previous instanceof HTMLBRElement) {
return getPreviousBrCount(previous) + 1;
}
else {
return 0;
}
}
function removePreviousBr(node) {
const previous = getPreviousSibling(node);
if (node instanceof HTMLBRElement) {
node.remove();
}
if (previous instanceof HTMLBRElement) {
return removePreviousBr(previous);
}
else {
return;
}
}
function fullWidthLength(input) {
const length = Array.from(input).reduce((p, c) => {
const code = c.codePointAt(0);
if (code === undefined) {
return p;
}
if (code < 128) {
return p + 0.5;
}
else {
return p + 1;
}
}, 0);
return length;
}
function convertHTMLtoXHTML(input) {
let doc;
if (typeof input === "string") {
doc = new DOMParser().parseFromString(input, "text/html");
}
if (input instanceof Document) {
doc = input;
}
if (doc instanceof Document) {
return new XMLSerializer().serializeToString(doc);
}
else {
throw new Error("input format error!");
}
}
function insertBrBeforeText(elem) {
for (const node of Array.from(elem.childNodes)) {
if (node instanceof Text && node.textContent?.trim() !== "") {
node.parentElement?.insertBefore(document.createElement("br"), node);
}
}
}
function isHidden(el) {
return el.offsetParent === null;
}
function escapeHTML(str) {
const p = document.createElement("p");
p.appendChild(document.createTextNode(str));
return p.innerHTML;
}
/***/ }),
/***/ "./src/lib/hash.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Q: () => (/* binding */ calculateSha1)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("crypto-js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
async function calculateSha1(blob) {
if (typeof crypto?.subtle?.digest === "function") {
const arrayBuffer = await blob.arrayBuffer();
const hashBuffer = await crypto.subtle.digest("SHA-1", arrayBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
return hashHex;
}
else {
return new Promise((resolve, rejects) => {
const reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onloadend = () => {
if (reader.result) {
const wordArray = crypto_js__WEBPACK_IMPORTED_MODULE_0__.lib.WordArray.create(reader.result);
const hash = crypto_js__WEBPACK_IMPORTED_MODULE_0__.SHA1(wordArray).toString();
resolve(hash);
}
else {
rejects(Error("计算MD5值出错"));
return;
}
};
});
}
}
/***/ }),
/***/ "./src/lib/http.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ J5: () => (/* binding */ fetchWithRetry),
/* harmony export */ Q2: () => (/* binding */ getFrameContentConditionWithWindow),
/* harmony export */ _V: () => (/* binding */ gfetch),
/* harmony export */ bx: () => (/* binding */ ggetText),
/* harmony export */ eF: () => (/* binding */ getFrameContentCondition),
/* harmony export */ kP: () => (/* binding */ getHtmlDomWithRetry),
/* harmony export */ n6: () => (/* binding */ getFrameContentEvent),
/* harmony export */ pG: () => (/* binding */ ggetHtmlDOM),
/* harmony export */ q4: () => (/* binding */ getText),
/* harmony export */ wA: () => (/* binding */ getHtmlDOM)
/* harmony export */ });
/* unused harmony exports fetchWithTimeout, ggetHtmlDomWithRetry */
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _setting__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/setting.ts");
/* harmony import */ var _GM__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/GM.ts");
/* harmony import */ var _misc__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/misc.ts");
globalThis.fetch = new Proxy(globalThis.fetch, {
apply(target, thisArg, argArray) {
_log__WEBPACK_IMPORTED_MODULE_0___default().debug("[debug]fetch:");
_log__WEBPACK_IMPORTED_MODULE_0___default().debug(argArray);
return Reflect.apply(target, thisArg, argArray);
},
});
async function fetchWithRetry(input, init) {
let retry = _setting__WEBPACK_IMPORTED_MODULE_1__/* .retryLimit */ .Iz;
while (retry > 0) {
const resp = await fetch(input, init);
if (resp.ok) {
return resp;
}
else {
await (0,_misc__WEBPACK_IMPORTED_MODULE_2__/* .sleep */ .yy)(1000 * (_setting__WEBPACK_IMPORTED_MODULE_1__/* .retryLimit */ .Iz - retry));
retry--;
}
}
throw new Error(`Fetch with retry failed! Url: ${input}`);
}
async function fetchWithTimeout(input, options = {}, timeout = 8000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const response = await fetch(input, {
...options,
signal: controller.signal,
});
clearTimeout(id);
return response;
}
function gfetch(url, { method = "GET", headers, data, cookie, binary, nocache, revalidate, timeout, context, responseType, overrideMimeType, anonymous, user, password, } = {}) {
return new Promise((resolve, reject) => {
_log__WEBPACK_IMPORTED_MODULE_0___default().debug("[debug]gfetch:");
_log__WEBPACK_IMPORTED_MODULE_0___default().debug(Array.from(arguments));
(0,_GM__WEBPACK_IMPORTED_MODULE_3__/* ._GM_xmlhttpRequest */ .nV)({
url,
method,
headers,
data,
cookie,
binary,
nocache,
revalidate,
timeout,
context,
responseType,
overrideMimeType,
anonymous,
user,
password,
onload: (obj) => {
resolve(obj);
},
onerror: (err) => {
reject(err);
},
});
});
}
async function getText(input, charset, init, test = (response) => Promise.resolve(false)) {
if (typeof input === "string") {
const _url = new URL(input);
if (document.location.protocol === "https:" && _url.protocol === "http:") {
_url.protocol = "https:";
input = _url.toString();
}
}
if (charset === undefined) {
return fetch(input, init)
.then(async (response) => {
if (response.ok || (await test(response))) {
return response.text();
}
else {
throw new Error(`Bad response! ${input}`);
}
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_0___default().error(error));
}
else {
return fetch(input, init)
.then(async (response) => {
if (response.ok || (await test(response))) {
return response.arrayBuffer();
}
else {
throw new Error(`Bad response! ${input}`);
}
})
.then((buffer) => {
const decoder = new TextDecoder(charset);
const text = decoder.decode(buffer);
return text;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_0___default().error(error));
}
}
async function getHtmlDOM(input, charset, init, test = (response) => Promise.resolve(false)) {
const htmlText = await getText(input, charset, init, test);
if (!htmlText) {
throw new Error("Fetch Content failed!");
}
const doc = new DOMParser().parseFromString(htmlText, "text/html");
if (!doc.querySelector("base")) {
const base = doc.createElement("base");
if (typeof input === "string") {
base.href = input;
}
else {
base.href = input.url;
}
doc.head.appendChild(base);
}
return doc;
}
async function getHtmlDomWithRetry(input, charset, init, test = (response) => Promise.resolve(false)) {
let retry = _setting__WEBPACK_IMPORTED_MODULE_1__/* .retryLimit */ .Iz;
let doc = null;
while (retry > 0) {
try {
doc = await getHtmlDOM(input, charset, init, test);
retry = 0;
}
catch (error) {
_log__WEBPACK_IMPORTED_MODULE_0___default().error(`抓取${input}失败,重试第${_setting__WEBPACK_IMPORTED_MODULE_1__/* .retryLimit */ .Iz - retry}次。`);
_log__WEBPACK_IMPORTED_MODULE_0___default().error(error);
retry--;
await (0,_misc__WEBPACK_IMPORTED_MODULE_2__/* .sleep */ .yy)(1000 * (_setting__WEBPACK_IMPORTED_MODULE_1__/* .retryLimit */ .Iz - retry));
}
}
return doc;
}
async function ggetText(url, charset, init, test = (response) => Promise.resolve(false)) {
let _init = init ? (0,_misc__WEBPACK_IMPORTED_MODULE_2__/* .deepcopy */ .OJ)(init) : undefined;
if (charset === undefined) {
return gfetch(url, init)
.then(async (response) => {
if ((response.status >= 200 && response.status <= 299) ||
(await test(response))) {
return response.responseText;
}
else {
throw new Error(`Bad response! ${url}`);
}
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_0___default().error(error));
}
else {
if (_init) {
_init.responseType = "arraybuffer";
}
else {
_init = { responseType: "arraybuffer" };
}
return gfetch(url, _init)
.then(async (response) => {
if ((response.status >= 200 && response.status <= 299) ||
(await test(response))) {
return response.response;
}
else {
throw new Error(`Bad response! ${url}`);
}
})
.then((buffer) => {
const decoder = new TextDecoder(charset);
const text = decoder.decode(buffer);
return text;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_0___default().error(error));
}
}
async function ggetHtmlDOM(url, charset, init, test = (response) => Promise.resolve(false)) {
const htmlText = await ggetText(url, charset, init, test);
if (!htmlText) {
throw new Error("Fetch Content failed!");
}
const doc = new DOMParser().parseFromString(htmlText, "text/html");
if (!doc.querySelector("base")) {
const base = doc.createElement("base");
base.href = url;
doc.head.appendChild(base);
}
return doc;
}
async function ggetHtmlDomWithRetry(url, charset, init, test = (response) => Promise.resolve(false)) {
let retry = retryLimit;
let doc = null;
while (retry > 0) {
try {
doc = await ggetHtmlDOM(url, charset, init, test);
retry = 0;
}
catch (error) {
log.error(`抓取${url}失败,重试第${retryLimit - retry}次。`);
retry--;
await sleep(1000 * (retryLimit - retry));
}
}
return doc;
}
function getFrameContentEvent(url, timeout = 0, eventType = "load", sandboxs) {
const frame = document.createElement("iframe");
frame.src = url;
frame.width = "1";
frame.height = "1";
sandboxs?.forEach((s) => frame.sandbox.add(s));
frame.addEventListener("error", (error) => _log__WEBPACK_IMPORTED_MODULE_0___default().error(error));
const promise = new Promise((resolve, reject) => {
frame.addEventListener(eventType, function (event) {
const frameSelf = event.target;
setTimeout(() => {
if (!frameSelf) {
reject(new Error("EventTarget Not Found!"));
}
const doc = frameSelf.contentWindow?.document ?? null;
frameSelf.remove();
resolve(doc);
}, timeout);
});
});
_log__WEBPACK_IMPORTED_MODULE_0___default().debug("[debug]getFrameContent:" + url);
document.body.appendChild(frame);
return promise;
}
async function getFrameContentCondition(url, stopCondition, sandboxs) {
const frame = document.createElement("iframe");
frame.src = url;
frame.width = "1";
frame.height = "1";
sandboxs?.forEach((s) => frame.sandbox.add(s));
frame.addEventListener("error", (error) => _log__WEBPACK_IMPORTED_MODULE_0___default().error(error));
_log__WEBPACK_IMPORTED_MODULE_0___default().debug("[debug]getFrameContent:" + url);
const promise = new Promise((resolve, reject) => {
if (!frame) {
reject(new Error("Frame Not Found!"));
}
let timerId = 0;
const loopFunc = () => {
if (stopCondition(frame)) {
const doc = frame.contentWindow?.document ?? null;
frame.remove();
window.clearInterval(timerId);
resolve(doc);
}
};
timerId = window.setInterval(loopFunc, 1000);
setTimeout(() => {
frame.remove();
window.clearInterval(timerId);
reject(new Error("Frame Timeout!"));
}, 30 * 1000);
});
document.body.appendChild(frame);
return promise;
}
async function getFrameContentConditionWithWindow(url, stopCondition, sandboxs) {
const frame = document.createElement("iframe");
frame.src = url;
frame.width = "1";
frame.height = "1";
sandboxs?.forEach((s) => frame.sandbox.add(s));
frame.addEventListener("error", (error) => _log__WEBPACK_IMPORTED_MODULE_0___default().error(error));
_log__WEBPACK_IMPORTED_MODULE_0___default().debug("[debug]getFrameContent:" + url);
const promise = new Promise((resolve, reject) => {
if (!frame) {
reject(new Error("Frame Not Found!"));
}
let timerId = 0;
const loopFunc = () => {
if (stopCondition(frame)) {
const doc = frame.contentWindow ?? null;
frame.remove();
window.clearInterval(timerId);
resolve(doc);
}
};
timerId = window.setInterval(loopFunc, 1000);
setTimeout(() => {
frame.remove();
window.clearInterval(timerId);
reject(new Error("Frame Timeout!"));
}, 30 * 1000);
});
document.body.appendChild(frame);
return promise;
}
/***/ }),
/***/ "./src/lib/misc.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ N4: () => (/* binding */ randomUUID),
/* harmony export */ OH: () => (/* binding */ mimetyepToCompressible),
/* harmony export */ OJ: () => (/* binding */ deepcopy),
/* harmony export */ ZA: () => (/* binding */ saveToArchiveOrg),
/* harmony export */ dB: () => (/* binding */ extensionToMimetype),
/* harmony export */ rr: () => (/* binding */ concurrencyRun),
/* harmony export */ y1: () => (/* binding */ range),
/* harmony export */ yy: () => (/* binding */ sleep)
/* harmony export */ });
/* unused harmony exports regexpEscape, mean, sd */
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _GM__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/GM.ts");
/* harmony import */ var mime_db__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/mime-db/index.js");
function concurrencyRun(list, limit, asyncHandle, options = {}) {
const { signal, reason } = options;
const listCopy = [...list];
const asyncList = [];
while (limit--) {
asyncList.push(recursion(listCopy));
}
return Promise.all(asyncList);
async function recursion(arr) {
if (signal?.aborted) {
if (reason) {
throw new _main_main__WEBPACK_IMPORTED_MODULE_1__/* .ExpectError */ .K5(reason);
}
else {
throw new _main_main__WEBPACK_IMPORTED_MODULE_1__/* .ExpectError */ .K5("concurrencyRun was aborted!");
}
}
await asyncHandle(arr.shift());
if (arr.length !== 0) {
return recursion(arr);
}
else {
return "finish!";
}
}
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function deepcopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
function regexpEscape(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
async function saveToArchiveOrg(url) {
const req = await fetch("https://save.bgme.bid/save", {
body: JSON.stringify({
url,
}),
headers: {
"content-type": "application/json; charset=utf-8",
"x-requested-with": `novel-downloader ${_GM__WEBPACK_IMPORTED_MODULE_2__/* ._GM_info */ .JX.script.version}; ${_GM__WEBPACK_IMPORTED_MODULE_2__/* ._GM_info */ .JX.scriptHandler} ${_GM__WEBPACK_IMPORTED_MODULE_2__/* ._GM_info */ .JX.version}`,
},
method: "POST",
});
return await req.json();
}
function mean(list) {
if (list.length === 0) {
return 0;
}
const sum = list.reduce((p, c) => p + c);
return sum / list.length;
}
function sd(list) {
if (list.length === 0) {
return 0;
}
const m = mean(list);
const variance = list.map((x) => Math.pow(x - m, 2)).reduce((p, c) => p + c) / list.length;
const sd = Math.sqrt(variance);
return sd;
}
function createUUID() {
const s = new Array(36);
const hexDigits = "0123456789abcdef";
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
const uuid = s.join("");
return uuid;
}
function randomUUID() {
if (typeof crypto.randomUUID === "function") {
return crypto.randomUUID();
}
else {
return createUUID();
}
}
function extensionToMimetype(ext) {
for (const [mimetype, entry] of Object.entries(mime_db__WEBPACK_IMPORTED_MODULE_0__)) {
if (entry.extensions?.includes(ext)) {
return mimetype;
}
}
return "application/octet-stream";
}
function mimetyepToCompressible(mimeType) {
if (mime_db__WEBPACK_IMPORTED_MODULE_0__[mimeType]) {
const entry = mime_db__WEBPACK_IMPORTED_MODULE_0__[mimeType];
if (entry["compressible"]) {
return entry["compressible"];
}
}
return false;
}
function range(size, startAt = 0) {
return [...Array(size).keys()].map((i) => i + startAt);
}
/***/ }),
/***/ "./src/lib/readability.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ fetchAndParse: () => (/* binding */ fetchAndParse),
/* harmony export */ gfetchAndParse: () => (/* binding */ gfetchAndParse),
/* harmony export */ parse: () => (/* binding */ parse)
/* harmony export */ });
/* harmony import */ var _mozilla_readability__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/@mozilla/readability/index.js");
/* harmony import */ var _mozilla_readability__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_mozilla_readability__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _http__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/http.ts");
function parse(doc, options) {
const obj = new _mozilla_readability__WEBPACK_IMPORTED_MODULE_0__.Readability(doc, options).parse();
if (obj) {
if (typeof obj.content === "string") {
obj.content = (0,_dom__WEBPACK_IMPORTED_MODULE_1__/* .createEl */ .a_)(obj.content);
}
}
return obj;
}
async function fetchAndParse(url, charset, init, patch, options) {
let doc = await (0,_http__WEBPACK_IMPORTED_MODULE_2__/* .getHtmlDOM */ .wA)(url, charset, init);
if (typeof patch === "function") {
doc = patch(doc);
}
return parse(doc, options);
}
async function gfetchAndParse(url, charset, init, patch, options) {
let doc = await (0,_http__WEBPACK_IMPORTED_MODULE_2__/* .ggetHtmlDOM */ .pG)(url, charset, init);
if (typeof patch === "function") {
doc = patch(doc);
}
return parse(doc, options);
}
/***/ }),
/***/ "./src/lib/rule.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ $l: () => (/* binding */ chapterHiddenFix),
/* harmony export */ HV: () => (/* binding */ introDomHandle),
/* harmony export */ hR: () => (/* binding */ deDuplicate),
/* harmony export */ lq: () => (/* binding */ getSectionName),
/* harmony export */ sy: () => (/* binding */ centerDetct),
/* harmony export */ u1: () => (/* binding */ nextPageParse)
/* harmony export */ });
/* unused harmony export reIndex */
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _cleanDOM__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _http__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var p_limit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/p-limit/index.js");
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/main.ts");
async function introDomHandle(introDom, domPatch) {
if (introDom === null) {
return [null, null, null];
}
else {
if (domPatch) {
introDom = domPatch(introDom.cloneNode(true));
}
const { dom: introCleanDom, text: introCleantext, images: introCleanimages, } = await (0,_cleanDOM__WEBPACK_IMPORTED_MODULE_1__/* .cleanDOM */ .an)(introDom, "TM");
return [introCleantext, introCleanDom, introCleanimages];
}
}
async function nextPageParse({ chapterName, chapterUrl, charset, selector, domPatch, contentPatch, getNextPage, continueCondition, enableCleanDOM, getHtmlDomFunc = _http__WEBPACK_IMPORTED_MODULE_2__/* .getHtmlDOM */ .wA, }) {
_log__WEBPACK_IMPORTED_MODULE_3___default().debug(`[Chapter]请求 ${chapterUrl}`);
let nowUrl = chapterUrl;
let doc = await getHtmlDomFunc(chapterUrl, charset);
const content = document.createElement("div");
let flag = false;
do {
if (domPatch) {
doc = await domPatch(doc);
}
let _content = doc.querySelector(selector);
const nextLink = getNextPage(doc);
if (continueCondition(_content, nextLink)) {
if (nextLink !== nowUrl) {
flag = true;
}
else {
_log__WEBPACK_IMPORTED_MODULE_3___default().error("网站页面出错,URL: " + nowUrl);
flag = false;
}
}
else {
flag = false;
}
_content = contentPatch(_content, doc);
for (const _c of Array.from(_content.childNodes)) {
content.appendChild(_c.cloneNode(true));
}
if (flag) {
_log__WEBPACK_IMPORTED_MODULE_3___default().debug(`[Chapter]请求 ${nextLink}`);
nowUrl = nextLink;
doc = await getHtmlDomFunc(nextLink, charset);
}
} while (flag);
let dom, text, images;
if (enableCleanDOM || enableCleanDOM === undefined) {
const obj = await (0,_cleanDOM__WEBPACK_IMPORTED_MODULE_1__/* .cleanDOM */ .an)(content, "TM");
dom = obj.dom;
text = obj.text;
images = obj.images;
}
else {
dom = null;
text = null;
images = null;
}
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
function getSectionName(chapterElement, sections, getName) {
const _sections = Array.from(sections);
let sectionName = null;
for (const sElem of _sections) {
const position = chapterElement.compareDocumentPosition(sElem);
if (position & Node.DOCUMENT_POSITION_DISCONNECTED) {
return null;
}
if (position & Node.DOCUMENT_POSITION_PRECEDING) {
sectionName = getName(sElem);
}
if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
break;
}
}
return sectionName;
}
function centerDetct(element) {
const docEl = document.documentElement;
const bodyEl = document.body;
const vw = Math.min(docEl.clientWidth, window.innerWidth);
const vh = Math.min(docEl.clientHeight, window.innerHeight);
const tolx = vw * 0.15;
const toly = Math.min(bodyEl.scrollHeight * 0.1, vh * 0.3);
const rect = element.getBoundingClientRect();
const distanceToTop = window.scrollY + rect.top;
const distanceToBottom = bodyEl.scrollHeight - distanceToTop - element.scrollHeight;
const distanceToRight = vw - rect.right;
const percentY = element.scrollHeight / bodyEl.scrollHeight;
if (rect.left < tolx ||
distanceToRight < tolx ||
distanceToTop < toly ||
distanceToBottom < toly) {
return [false, element, percentY];
}
return [true, element, percentY];
}
function reIndex(chapters) {
chapters = chapters.sort((a, b) => a.chapterNumber - b.chapterNumber);
let i = 0;
let sectionName = "";
let s = 0;
let si = 0;
for (const chapter of chapters) {
i++;
chapter.chapterNumber = i;
if (chapter.sectionName) {
if (chapter.sectionName !== sectionName) {
sectionName = chapter.sectionName;
s++;
si = 0;
}
si++;
chapter.sectionNumber = s;
chapter.sectionChapterNumber = si;
}
}
return chapters;
}
function deDuplicate(chapters) {
const obj = chapters.reduce((obj, cur) => {
const url = cur.chapterUrl;
if (obj[url] === undefined) {
obj[url] = cur;
}
else if (Array.isArray(obj[url])) {
obj[url].push(cur);
}
else {
obj[url] = [obj[url], cur];
}
return obj;
}, {});
const reducer = (out, cur) => {
if (Array.isArray(cur)) {
const url = cur[0].chapterUrl;
if (url === "") {
out.push(...cur);
}
else {
out.push(cur.sort((a, b) => a.chapterNumber - b.chapterNumber).slice(-1)[0]);
}
}
else {
out.push(cur);
}
return out;
};
const results = Object.values(obj).reduce(reducer, []);
reIndex(results);
return results;
}
async function chapterHiddenFix(book, invalidTest, getPrevHref, concurrencyLimit, sleepTime = 500, getHtmlDomFunc = _http__WEBPACK_IMPORTED_MODULE_2__/* .getHtmlDOM */ .wA) {
const { chapters } = book;
const invalidChapterList = chapters.filter(invalidTest);
if (concurrencyLimit === 1) {
for (const ic of invalidChapterList) {
fix(ic, chapters);
await new Promise(resolve => setTimeout(resolve, Math.random() * 100 + sleepTime));
}
}
else {
const limit = (0,p_limit__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A)(concurrencyLimit);
const tasks = invalidChapterList.map((ic) => {
return limit(() => fix(ic, chapters));
});
await Promise.all(tasks);
}
async function fix(invalidChapter, chapterList) {
const no = invalidChapter.chapterNumber;
const nextChapter = chapterList.filter((c) => c.chapterNumber === no + 1)?.[0];
if (nextChapter) {
const nextChapterUrl = nextChapter.chapterUrl;
const doc = await getHtmlDomFunc(nextChapterUrl, nextChapter.charset);
const href = getPrevHref(doc);
if (href) {
invalidChapter.chapterUrl = href;
invalidChapter.status = _main_main__WEBPACK_IMPORTED_MODULE_4__/* .Status */ .nW.pending;
}
return invalidChapter;
}
}
}
/***/ }),
/***/ "./src/log.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ M6: () => (/* binding */ saveLogTextToFile),
/* harmony export */ gh: () => (/* binding */ getLogText),
/* harmony export */ kc: () => (/* binding */ logText)
/* harmony export */ });
/* harmony import */ var file_saver__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/file-saver/dist/FileSaver.min.js");
/* harmony import */ var file_saver__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(file_saver__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var loglevel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var loglevel__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(loglevel__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _setting__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/setting.ts");
if (_setting__WEBPACK_IMPORTED_MODULE_2__/* .enableDebug */ .Nw.value) {
loglevel__WEBPACK_IMPORTED_MODULE_1___default().setLevel("trace");
}
else {
loglevel__WEBPACK_IMPORTED_MODULE_1___default().setLevel("info");
}
let logText = "";
function getLogText() {
return logText;
}
const originalFactory = (loglevel__WEBPACK_IMPORTED_MODULE_1___default().methodFactory);
(loglevel__WEBPACK_IMPORTED_MODULE_1___default().methodFactory) = (methodName, logLevel, loggerName) => {
const rawMethod = originalFactory(methodName, logLevel, loggerName);
return (message) => {
try {
if (typeof message === "object") {
if (message instanceof Error) {
logText += message.name;
logText += message.message;
logText += message.stack;
}
else {
logText += JSON.stringify(message, undefined, 2) + "\n";
}
}
else {
logText += message + "\n";
}
}
catch (error) {
loglevel__WEBPACK_IMPORTED_MODULE_1___default().error(error);
}
rawMethod(message);
};
};
loglevel__WEBPACK_IMPORTED_MODULE_1___default().setLevel(loglevel__WEBPACK_IMPORTED_MODULE_1___default().getLevel());
function saveLogTextToFile() {
(0,file_saver__WEBPACK_IMPORTED_MODULE_0__.saveAs)(new Blob([logText], { type: "text/plain; charset=UTF-8" }), `novel-downloader-${Date.now().toString()}.log`);
}
/***/ }),
/***/ "./src/main/Attachment.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ q: () => (/* binding */ AttachmentClass)
/* harmony export */ });
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_misc__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/misc.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _setting__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/setting.ts");
/* harmony import */ var _main__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/main/main.ts");
class AttachmentClass {
url;
name;
mode;
status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.pending;
retryTime = 0;
Blob;
comments;
referrerMode;
_init;
_TMinit;
constructor(url, name, mode, referrerMode = _main__WEBPACK_IMPORTED_MODULE_0__/* .ReferrerMode */ .ls.keep, customReferer = "", init) {
this.url = url;
this.name = name;
this.mode = mode;
this.referrerMode = referrerMode;
const defaultInit = {
init: {
referrerPolicy: "strict-origin-when-cross-origin",
},
TMinit: {
headers: { Referer: document.location.origin },
responseType: "blob",
},
};
if (!init) {
({ init: this._init, TMinit: this._TMinit } = defaultInit);
if (this.referrerMode === _main__WEBPACK_IMPORTED_MODULE_0__/* .ReferrerMode */ .ls.none) {
this._init.referrerPolicy = "no-referrer";
this._TMinit.headers = {};
}
if (this.referrerMode === _main__WEBPACK_IMPORTED_MODULE_0__/* .ReferrerMode */ .ls.self) {
this._TMinit.headers = { Referer: new URL(url).origin };
}
if (this.referrerMode === _main__WEBPACK_IMPORTED_MODULE_0__/* .ReferrerMode */ .ls.custom &&
customReferer.startsWith("http")) {
this._TMinit.headers = { Referer: customReferer };
}
}
else {
({ init: this._init, TMinit: this._TMinit } = (0,_lib_misc__WEBPACK_IMPORTED_MODULE_1__/* .deepcopy */ .OJ)(init));
this._TMinit.responseType = "blob";
if (this._init.responseType) {
delete this._init.responseType;
}
}
}
async init() {
if (this.mode === "naive") {
this.Blob = await this.download();
}
else {
this.Blob = await this.tmDownload();
}
if (this.Blob) {
_log__WEBPACK_IMPORTED_MODULE_2___default().info(`[attachment] ${this.url} 下载完成。`);
}
return this.Blob;
}
download() {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.downloading;
return fetch(this.url, this._init)
.then((response) => {
if (response.ok) {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.finished;
return response.blob();
}
else {
if (response.status === 404) {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed;
}
throw new Error(`Bad response!\nRequest url: ${this.url}\nStatus code: ${response.status}`);
}
})
.catch(async (err) => {
this.retryTime++;
_log__WEBPACK_IMPORTED_MODULE_2___default().error(`[attachment]下载 ${this.url} 出错,第${this.retryTime}次重试,下载模式:${this.mode}`);
if (this.status !== _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed && this.retryTime < _setting__WEBPACK_IMPORTED_MODULE_3__/* .retryLimit */ .Iz) {
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_1__/* .sleep */ .yy)(this.retryTime * 1500);
return this.download();
}
else {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed;
_log__WEBPACK_IMPORTED_MODULE_2___default().error(err);
_log__WEBPACK_IMPORTED_MODULE_2___default().trace(err);
return null;
}
});
}
tmDownload() {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.downloading;
return (0,_lib_http__WEBPACK_IMPORTED_MODULE_4__/* .gfetch */ ._V)(this.url, this._TMinit)
.then((response) => {
if (response.status >= 200 && response.status <= 299) {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.finished;
return response.response;
}
else {
if (response.status === 404) {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed;
}
throw new Error(`Bad response!\nRequest url: ${this.url}\nStatus code: ${response.status}`);
}
})
.catch(async (err) => {
this.retryTime++;
_log__WEBPACK_IMPORTED_MODULE_2___default().error(`[attachment]下载 ${this.url} 出错,第${this.retryTime}次重试,下载模式:${this.mode}`);
if (this.status !== _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed && this.retryTime < _setting__WEBPACK_IMPORTED_MODULE_3__/* .retryLimit */ .Iz) {
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_1__/* .sleep */ .yy)(this.retryTime * 1000);
return this.tmDownload();
}
else {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed;
_log__WEBPACK_IMPORTED_MODULE_2___default().error(err);
_log__WEBPACK_IMPORTED_MODULE_2___default().trace(err);
return null;
}
});
}
toJSON() {
return {
url: this.url,
name: this.name,
mode: this.mode,
status: this.status,
retryTime: this.retryTime,
};
}
}
/***/ }),
/***/ "./src/main/Book.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
E: () => (/* binding */ Book)
});
;// ./src/lib/removeTrackParam.ts
const general = [
"nx_source",
"_zucks_suid",
"cmpid",
"asgtbndr",
"guccounter",
"guce_referrer",
"guce_referrer_sig",
"_openstat",
"action_object_map",
"action_ref_map",
"action_type_map",
"fb_action_ids",
"fb_action_types",
"fb_comment_id",
"fb_ref",
"fb_source",
"fbclid",
"xtor",
"utm_campaign",
"utm_channel",
"utm_cid",
"utm_content",
"utm_id",
"utm_medium",
"utm_name",
"utm_place",
"utm_pubreferrer",
"utm_reader",
"utm_referrer",
"utm_serial",
"utm_social",
"utm_social-type",
"utm_source",
"utm_swu",
"utm_term",
"utm_userid",
"utm_viz_id",
"utm_product",
"utm_campaignid",
"utm_ad",
"utm_brand",
"utm_emcid",
"utm_emmid",
"utm_umguk",
"gbraid",
"wbraid",
"gclsrc",
"gclid",
"yclid",
"dpg_source",
"dpg_campaign",
"dpg_medium",
"dpg_content",
"admitad_uid",
"adjust_tracker",
"adjust_adgroup",
"adjust_campaign",
"bsft_clkid",
"bsft_eid",
"bsft_mid",
"bsft_uid",
"bsft_aaid",
"bsft_ek",
"mtm_campaign",
"mtm_cid",
"mtm_content",
"mtm_group",
"mtm_keyword",
"mtm_medium",
"mtm_placement",
"mtm_source",
"pk_campaign",
"pk_medium",
"pk_source",
"_branch_match_id",
"vc_lpp",
"ml_subscriber",
"ml_subscriber_hash",
"rb_clickid",
"oly_anon_id",
"oly_enc_id",
"dt_dapp",
"dt_platform",
"spm",
"scm",
];
const specific = {
"bilibili.com": [
"from",
"seid",
"share_source",
"spm_id_from",
"from_spm_id",
"share_medium",
"share_plat",
"share_session_id",
"share_source",
"share_tag",
"timestamp",
"unique_k",
"from_source",
"refer_from",
],
};
function findSpecial(host) {
let lastPos = 0;
let domain = host;
while (lastPos >= 0) {
if (specific[domain]) {
return specific[domain];
}
lastPos = host.indexOf(".", lastPos + 1);
domain = host.slice(lastPos + 1);
}
}
function removeTrackParm(_url) {
const url = new URL(_url);
const host = url.hostname;
const search = url.searchParams;
general.forEach((s) => search.delete(s));
const special = findSpecial(host);
if (special) {
special.forEach((s) => search.delete(s));
}
url.hash = "";
return url.href;
}
// EXTERNAL MODULE: ./node_modules/loglevel/lib/loglevel.js
var loglevel = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
var loglevel_default = /*#__PURE__*/__webpack_require__.n(loglevel);
;// ./src/main/Book.ts
class Book {
saveType = {
epub: true,
txt: true,
raw: false,
};
bookname;
author;
introduction;
introductionHTML;
additionalMetadate;
chapters;
saveOptions;
constructor({ bookUrl, bookname, author, introduction, introductionHTML, additionalMetadate, chapters, }) {
this.bookUrl = bookUrl;
this.bookname = bookname;
this.author = author;
this.introduction = introduction;
this.introductionHTML = introductionHTML;
this.additionalMetadate = additionalMetadate;
this.chapters = chapters;
loglevel_default().debug("[Book]初始化完成");
}
_bookUrl = "";
get bookUrl() {
return this._bookUrl;
}
set bookUrl(v) {
this._bookUrl = removeTrackParm(v);
}
_ToCUrl;
get ToCUrl() {
return this._ToCUrl;
}
set ToCUrl(v) {
if (v) {
this._ToCUrl = removeTrackParm(v);
}
}
toJSON() {
return {
bookUrl: this.bookUrl,
ToCUrl: this.ToCUrl,
bookname: this.bookname,
author: this.author,
introduction: this.introduction,
introductionHTML: this.introductionHTML
? this.introductionHTML.outerHTML
: this.introductionHTML,
additionalMetadate: this.additionalMetadate,
};
}
}
/***/ }),
/***/ "./src/main/Chapter.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ I: () => (/* binding */ Chapter)
/* harmony export */ });
/* harmony import */ var _lib_misc__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/misc.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _setting__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/setting.ts");
/* harmony import */ var _main__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/main/main.ts");
class Chapter {
bookUrl;
bookname;
chapterUrl;
chapterNumber;
chapterName;
isVIP;
isPaid;
sectionName;
sectionNumber;
sectionChapterNumber;
chapterParse;
charset;
options;
status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.pending;
retryTime = 0;
contentRaw;
contentText;
contentHTML;
contentImages;
additionalMetadate;
chapterHtmlFileName;
book;
constructor({ bookUrl, bookname, chapterUrl, chapterNumber, chapterName, isVIP, isPaid, sectionName, sectionNumber, sectionChapterNumber, chapterParse, charset, options, }) {
this.bookUrl = bookUrl;
this.bookname = bookname;
this.chapterUrl = chapterUrl;
this.chapterNumber = chapterNumber;
this.chapterName = chapterName;
this.isVIP = isVIP;
this.isPaid = isPaid;
this.sectionName = sectionName;
this.sectionNumber = sectionNumber;
this.sectionChapterNumber = sectionChapterNumber;
this.chapterParse = chapterParse;
this.charset = charset;
this.options = options;
}
async init() {
const { chapterName, contentRaw, contentText, contentHTML, contentImages, additionalMetadate, } = await this.parse();
this.chapterName = chapterName;
this.contentRaw = contentRaw;
this.contentText = contentText;
this.contentHTML = contentHTML;
this.contentImages = contentImages;
this.additionalMetadate = additionalMetadate;
if (this.status === _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed) {
_log__WEBPACK_IMPORTED_MODULE_1___default().error(`[Chapter]章节名:${this.chapterName}, \
分卷名:${this.sectionName}, URL:${this.chapterUrl}, \
VIP:${this.isVIP}, Paid:${this.isPaid}, \
isNull:${!this.contentHTML} 解析出错。`);
}
else {
_log__WEBPACK_IMPORTED_MODULE_1___default().info(`[Chapter]章节名:${this.chapterName}, \
分卷名:${this.sectionName}, URL:${this.chapterUrl}, \
VIP:${this.isVIP}, Paid:${this.isPaid}, \
isNull:${!this.contentHTML} 解析成功。`);
}
return this;
}
async parse() {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.downloading;
return this.chapterParse(this.chapterUrl, this.chapterName, this.isVIP, this.isPaid, this.charset, this.options)
.then(async (obj) => {
const contentImages = obj.contentImages;
if (contentImages) {
let downloadingImages = contentImages.filter((imgObj) => imgObj.status === _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.downloading);
while (downloadingImages.length) {
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_2__/* .sleep */ .yy)(500);
downloadingImages = contentImages.filter((imgObj) => imgObj.status === _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.downloading);
}
}
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.finished;
return obj;
})
.catch(async (err) => {
this.retryTime++;
_log__WEBPACK_IMPORTED_MODULE_1___default().error(`[Chapter]${this.chapterName}解析出错,第${this.retryTime}次重试,章节地址:${this.chapterUrl}`);
if (this.status !== _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed && this.retryTime < _setting__WEBPACK_IMPORTED_MODULE_3__/* .retryLimit */ .Iz) {
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_2__/* .sleep */ .yy)(this.retryTime * 1500);
return this.parse();
}
else {
this.status = _main__WEBPACK_IMPORTED_MODULE_0__/* .Status */ .nW.failed;
_log__WEBPACK_IMPORTED_MODULE_1___default().error(err);
_log__WEBPACK_IMPORTED_MODULE_1___default().trace(err);
window.failedCount++;
return {
chapterName: this.chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
});
}
toJSON() {
return {
bookUrl: this.bookUrl,
bookname: this.bookname,
chapterUrl: this.chapterUrl,
chapterNumber: this.chapterNumber,
chapterName: this.chapterName,
isVIP: this.isPaid,
isPaid: this.isPaid,
sectionName: this.sectionName,
sectionNumber: this.sectionNumber,
sectionChapterNumber: this.sectionChapterNumber,
status: this.status,
retryTime: this.retryTime,
chapterHtmlFileName: this.chapterHtmlFileName,
};
}
}
/***/ }),
/***/ "./src/main/main.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ K5: () => (/* binding */ ExpectError),
/* harmony export */ ls: () => (/* binding */ ReferrerMode),
/* harmony export */ nW: () => (/* binding */ Status)
/* harmony export */ });
var Status;
(function (Status) {
Status[Status["pending"] = 0] = "pending";
Status[Status["downloading"] = 1] = "downloading";
Status[Status["failed"] = 2] = "failed";
Status[Status["finished"] = 3] = "finished";
Status[Status["aborted"] = 4] = "aborted";
Status[Status["saved"] = 5] = "saved";
})(Status || (Status = {}));
var ReferrerMode;
(function (ReferrerMode) {
ReferrerMode[ReferrerMode["keep"] = 0] = "keep";
ReferrerMode[ReferrerMode["none"] = 1] = "none";
ReferrerMode[ReferrerMode["self"] = 2] = "self";
ReferrerMode[ReferrerMode["custom"] = 3] = "custom";
})(ReferrerMode || (ReferrerMode = {}));
class ExpectError extends Error {
}
/***/ }),
/***/ "./src/rules.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
Q: () => (/* binding */ BaseRuleClass)
});
// EXTERNAL MODULE: ./src/lib/attachments.ts
var attachments = __webpack_require__("./src/lib/attachments.ts");
// EXTERNAL MODULE: ./src/lib/misc.ts
var misc = __webpack_require__("./src/lib/misc.ts");
// EXTERNAL MODULE: ./node_modules/loglevel/lib/loglevel.js
var loglevel = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
var loglevel_default = /*#__PURE__*/__webpack_require__.n(loglevel);
// EXTERNAL MODULE: ./src/log.ts
var log = __webpack_require__("./src/log.ts");
// EXTERNAL MODULE: ./src/main/main.ts
var main = __webpack_require__("./src/main/main.ts");
// EXTERNAL MODULE: ./node_modules/file-saver/dist/FileSaver.min.js
var FileSaver_min = __webpack_require__("./node_modules/file-saver/dist/FileSaver.min.js");
// EXTERNAL MODULE: ./src/setting.ts
var setting = __webpack_require__("./src/setting.ts");
// EXTERNAL MODULE: ./src/save/sgc-toc.css
var sgc_toc = __webpack_require__("./src/save/sgc-toc.css");
// EXTERNAL MODULE: ./src/save/web.css
var web = __webpack_require__("./src/save/web.css");
// EXTERNAL MODULE: ./src/lib/GM.ts
var GM = __webpack_require__("./src/lib/GM.ts");
;// external "fflate"
const external_fflate_namespaceObject = fflate;
// EXTERNAL MODULE: ./node_modules/streamsaver/StreamSaver.js
var StreamSaver = __webpack_require__("./node_modules/streamsaver/StreamSaver.js");
var StreamSaver_default = /*#__PURE__*/__webpack_require__.n(StreamSaver);
;// ./src/lib/zip.ts
async function setStreamSaverSetting() {
const rawMitm = new URL(streamSaver.mitm);
const mitm = new URL("https://cors.bgme.bid/");
mitm.pathname = rawMitm.origin + rawMitm.pathname;
streamSaver.mitm = mitm.href;
streamSaver.supported =
streamSupport() && (await mitmPageAvailability(mitm.href));
}
class FflateZip {
filename;
stream;
zcount = 0;
count = 0;
filenameList = [];
zipOut = new Blob([], { type: "application/zip" });
savedZip;
constructor(filename, stream, mimetype = "application/zip") {
loglevel_default().info(`[fflateZip] filename: ${filename}, stream: ${stream}, streamSaver.supported: ${(StreamSaver_default()).supported}`);
const self = this;
this.filename = filename;
this.stream = false;
let writer;
if (this.stream) {
const fileStream = StreamSaver_default().createWriteStream(self.filename);
writer =
fileStream.getWriter();
}
this.savedZip = new external_fflate_namespaceObject.Zip((err, dat, final) => {
if (err) {
loglevel_default().error(err);
loglevel_default().trace(err);
if (self.stream) {
writer.abort();
}
throw err;
}
if (self.stream) {
writer.write(dat);
}
else {
self.zipOut = new Blob([self.zipOut, dat], { type: mimetype });
}
if (final) {
if (self.stream) {
writer.close();
loglevel_default().info("[fflateZip] ZIP生成完毕");
}
else {
nonStream();
}
}
function nonStream() {
loglevel_default().info("[fflateZip] ZIP生成完毕,文件大小:" + self.zipOut.size);
try {
(0,FileSaver_min.saveAs)(self.zipOut, self.filename);
self.zipOut = new Blob([], { type: "application/zip" });
}
catch (error) {
loglevel_default().error("[fflateZip]" + error);
loglevel_default().trace(error);
}
}
});
}
async file(filename, fileBlob, nocompress = false) {
if (this.filenameList.includes(filename)) {
loglevel_default().warn(`filename ${filename} has existed on zip.`);
return;
}
this.filenameList.push(filename);
this.count++;
const buffer = await fileBlob.arrayBuffer();
const chunk = new Uint8Array(buffer);
if (!((0,misc/* mimetyepToCompressible */.OH)((0,misc/* extensionToMimetype */.dB)(filename.split(".").slice(-1)[0])) || (0,misc/* mimetyepToCompressible */.OH)(fileBlob.type)) ||
nocompress) {
const nonStreamingFile = new external_fflate_namespaceObject.ZipPassThrough(filename);
this.savedZip.add(nonStreamingFile);
nonStreamingFile.push(chunk, true);
this.zcount++;
}
else {
const nonStreamingFile = new external_fflate_namespaceObject.AsyncZipDeflate(filename, {
level: 9,
});
this.savedZip.add(nonStreamingFile);
nonStreamingFile.push(chunk, true);
this.zcount++;
}
}
async generateAsync() {
while (this.count !== this.zcount) {
await (0,misc/* sleep */.yy)(100);
}
this.savedZip.end();
}
}
// EXTERNAL MODULE: ./src/save/main.css
var save_main = __webpack_require__("./src/save/main.css");
// EXTERNAL MODULE: ./src/save/toc.css
var toc = __webpack_require__("./src/save/toc.css");
// EXTERNAL MODULE: ./src/lib/dom.ts
var dom = __webpack_require__("./src/lib/dom.ts");
;// ./src/save/options.ts
class Common {
genMetaDateTxt(book) {
let metaDateText = `题名:${book.bookname}\n作者:${book.author}`;
if (book.additionalMetadate.tags) {
metaDateText += `\nTag列表:${book.additionalMetadate.tags.join("、")}`;
}
metaDateText += `\n原始网址:${book.bookUrl}`;
if (book.additionalMetadate.cover) {
metaDateText += `\n封面图片地址:${book.additionalMetadate.cover.url}`;
}
if (book.introduction) {
metaDateText += `\n简介:${book.introduction}`;
}
metaDateText += `\n下载时间:${new Date().toISOString()}\n本文件由小说下载器生成,软件地址:https://github.com/404-novel-project/novel-downloader\n\n`;
return metaDateText;
}
getChapterNumberToSave(chapter, chapters) {
return `${"0".repeat(Math.max(chapters.length.toString().length, 5) -
Math.trunc(chapter.chapterNumber).toString().length)}${chapter.chapterNumber.toString()}`;
}
}
function saveOptionsValidate(data) {
const keyNamesS = ["mainStyleText", "tocStyleText"];
const keyNamesF = [
"getchapterName",
"genSectionText",
"genChapterText",
"genChapterEpub",
"chapterSort",
];
function keyNametest(keyname) {
const keyList = [...keyNamesS, ...keyNamesF];
return keyList.includes(keyname);
}
function keyNamesStest(keyname) {
if (keyNamesS.includes(keyname)) {
if (typeof data[keyname] === "string") {
return true;
}
}
return false;
}
function keyNamesFtest(keyname) {
if (keyNamesF.includes(keyname)) {
if (typeof data[keyname] === "function") {
return true;
}
}
return false;
}
if (typeof data !== "object") {
return false;
}
if (Object.keys(data).length === 0) {
return false;
}
for (const keyname in data) {
if (Object.prototype.hasOwnProperty.call(data, keyname)) {
if (!keyNametest(keyname)) {
return false;
}
if (!(keyNamesStest(keyname) || keyNamesFtest(keyname))) {
return false;
}
}
}
return true;
}
class Options extends Common {
mainStyleText = save_main/* default */.A;
tocStyleText = toc/* default */.A;
getchapterName(chapter) {
if (chapter.chapterName) {
return chapter.chapterName;
}
else {
return chapter.chapterNumber.toString();
}
}
genSectionText(sectionName) {
return (`${"=".repeat(20)}\n\n\n\n# ${sectionName}\n\n\n\n${"=".repeat(20)}` +
"\n\n");
}
genChapterText(chapterName, contentText) {
return `${chapterName}\n${"=".repeat((0,dom/* fullWidthLength */.QJ)(chapterName) * 2 + 10)}\n\n${contentText}\n\n`;
}
genChapterEpub(contentXHTML) {
return contentXHTML;
}
chapterSort(a, b) {
return a.chapterNumber - b.chapterNumber;
}
}
// EXTERNAL MODULE: ./src/save/misc.ts
var save_misc = __webpack_require__("./src/save/misc.ts");
;// ./src/save/chapter.html.j2
// Module
var code = "<!DOCTYPE html>\n<html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n <meta name=\"referrer\" content=\"same-origin\">\n <meta name=\"generator\" content=\"https://github.com/404-novel-project/novel-downloader\">\n <meta name=\"source\" content=\"{{ chapterUrl }}\">\n <link href=\"style.css\" type=\"text/css\" rel=\"stylesheet\">\n <title>{{ chapterName }}</title>\n </head>\n <body>\n <div class=\"main\">\n <h2>{{ chapterName }}</h2>\n {{ outerHTML }}\n </div>\n <!-- <" + "script type=\"text/javascript\" src=\"web.js\"><" + "/script> -->\n </body>\n</html>\n";
// Exports
/* harmony default export */ const chapter_html = (code);
;// ./src/save/index.html.j2
// Module
var index_html_code = "<!DOCTYPE html>\n<html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n <meta name=\"referrer\" content=\"same-origin\">\n <meta name=\"generator\" content=\"https://github.com/404-novel-project/novel-downloader\">\n <meta name=\"date-creation\" content=\"{{ creationDate }}\">\n <link href=\"style.css\" type=\"text/css\" rel=\"stylesheet\">\n <link href=\"web.css\" type=\"text/css\" rel=\"stylesheet\">\n <link href=\"toc.css\" type=\"text/css\" rel=\"stylesheet\">\n <title>{{ bookname }}</title>\n </head>\n <body>\n <div class=\"main\">\n <h1>{{ bookname }}</h1>\n <h3 class=\"author\">{{ author }}</h3>\n <div class=\"info\">\n {% if cover -%}\n <img class=\"cover\" data-src-address=\"{{ cover.name }}\">\n {%- endif %} \n {% if introductionHTML -%}\n <div>\n <h3>简介</h3>\n <div class=\"introduction\">{{ introductionHTML }}</div>\n </div>\n {%- endif %}\n </div>\n <div class=\"bookurl\">\n <a href=\"{{ bookUrl }}\">打开原始网站</a>\n </div>\n <hr>\n {% for sectionObj in sectionsObj -%}\n <div id=\"section{{ sectionObj.sectionNumber }}\" class=\"section\">\n {% if sectionObj.sectionName %}\n <h2 class=\"section-label\">{{ sectionObj.sectionName }}</h2>\n {% endif %}\n {% for chapter in sectionObj.chpaters -%}\n <div class=\"chapter\">\n {% if not (chapter.contentHTML or chapter.status === Status.saved) -%}\n <a class=\"disabled\" href=\"{{ chapter.chapterHtmlFileName }}\">{{ chapter.chapterName }}</a>\n {%- else -%}\n <a href=\"{{ chapter.chapterHtmlFileName }}\">{{ chapter.chapterName }}</a>\n {%- endif %}\n </div>\n {%- endfor %}\n </div>\n {%- endfor %} \n </div>\n </body>\n</html>";
// Exports
/* harmony default export */ const index_html = (index_html_code);
;// ./src/save/section.html.j2
// Module
var section_html_code = "<!DOCTYPE html>\n<html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n <meta name=\"referrer\" content=\"same-origin\">\n <meta name=\"generator\" content=\"https://github.com/404-novel-project/novel-downloader\">\n <link href=\"style.css\" type=\"text/css\" rel=\"stylesheet\">\n <title>{{ sectionName }}</title>\n </head>\n <body>\n <div class=\"main\"><h1>{{ sectionName }}</h1></div>\n </body>\n</html>\n";
// Exports
/* harmony default export */ const section_html = (section_html_code);
;// external "nunjucks"
const external_nunjucks_namespaceObject = nunjucks;
;// ./src/save/epub.ts
const env = new external_nunjucks_namespaceObject.Environment(undefined, { autoescape: false });
const section = new external_nunjucks_namespaceObject.Template(section_html, env, undefined, true);
const chapterTemplt = new external_nunjucks_namespaceObject.Template(chapter_html, env, undefined, true);
const index = new external_nunjucks_namespaceObject.Template(index_html, env, undefined, true);
function getDateString() {
const date = new Date();
const year = date.getFullYear();
const _monty = new Date().getMonth() + 1;
const monty = _monty < 10 ? `0${_monty}` : _monty;
const _day = date.getDate();
const day = _day < 10 ? `0${_day}` : _day;
return `${year}-${monty}-${day}`;
}
const uuid = (0,misc/* randomUUID */.N4)();
const content_opf = `<?xml version="1.0" encoding="utf-8"?>
<package version="3.0" unique-identifier="BookId" prefix="rendition: http://www.idpf.org/vocab/rendition/#" xmlns="http://www.idpf.org/2007/opf">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:opf="http://www.idpf.org/2007/opf">
<dc:identifier id="BookId">urn:uuid:${uuid}</dc:identifier>
<meta content="${GM/* _GM_info */.JX.script.version}" name="novel-downloader version"/>
<meta content="https://github.com/404-novel-project/novel-downloader" name="generator"/>
<meta property="dcterms:created">${getDateString()}</meta>
<meta property="dcterms:modified">${new Date()
.toISOString()
.replace(/\.\d\d\dZ$/, "Z")}</meta>
</metadata>
<manifest>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
<item id="navid" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="sgc-toc.css" href="sgc-toc.css" media-type="text/css"/>
<item id="style.css" href="style.css" media-type="text/css"/>
<item id="cover.xhtml" href="cover.xhtml" media-type="application/xhtml+xml" properties="svg"/>
<item id="info.xhtml" href="info.xhtml" media-type="application/xhtml+xml"/>
<item id="message.xhtml" href="message.xhtml" media-type="application/xhtml+xml"/>
<item id="TOC.xhtml" href="TOC.xhtml" media-type="application/xhtml+xml"/>
</manifest>
<spine toc="ncx">
<itemref idref="cover.xhtml"/>
<itemref idref="info.xhtml"/>
<itemref idref="message.xhtml"/>
<itemref idref="TOC.xhtml"/>
</spine>
<guide>
<reference type="cover" title="Cover" href="cover.xhtml"/>
<reference type="toc" title="Table of Contents" href="TOC.xhtml"/>
</guide>
</package>`;
const toc_ncx = `<?xml version="1.0" encoding="utf-8" ?>
<ncx version="2005-1" xmlns="http://www.daisy.org/z3986/2005/ncx/">
<head>
<meta content="urn:uuid:${uuid}" name="dtb:uid"/>
<meta content="2" name="dtb:depth"/>
<meta content="0" name="dtb:totalPageCount"/>
<meta content="0" name="dtb:maxPageNumber"/>
</head>
<docTitle>
<text></text>
</docTitle>
<navMap>
</navMap>
</ncx>`;
const TOC_xhtml = `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<title>Table of Contents</title>
<link href="sgc-toc.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div class="sgc-toc-title">
目录
</div>
</body>
</html>`;
const nav_xhtml = `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<meta charset="utf-8"/>
<title>ePub Nav</title>
<style type="text/css">
ol { list-style-type: none; }
</style>
</head>
<body epub:type="frontmatter">
<nav epub:type="toc" id="toc" role="doc-toc">
<h1>Table of Contents</h1>
</nav>
<nav epub:type="landmarks" id="landmarks" hidden=""><h2>Guide</h2>
<ol>
<li><a epub:type="cover" href="cover.xhtml">Cover</a></li>
<li><a epub:type="toc" href="TOC.xhtml">Table of Contents</a></li>
</ol>
</nav>
</body>
</html>`;
const getCoverXhtml = (coverName) => `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<title>Cover</title>
</head>
<body>
<div style="text-align: center; padding: 0pt; margin: 0pt;">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" preserveAspectRatio="xMidYMid meet" version="1.1" viewBox="0 0 368 460" width="100%" xmlns:xlink="http://www.w3.org/1999/xlink"><image width="368" height="460" xlink:href="${coverName}"/></svg>
</div>
</body>
</html>`;
const getInfoXhtml = (title, author) => `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<title>信息页</title>
<link href="style.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<div class="main">
<h1>${title}</h1>
${author ? `<h2>作者:${author}</h2>` : ""}
</div>
</body>
</html>`;
const getMessageXhtml = (book) => `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<title>信息页</title>
<link href="style.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<div class="main">
<div><strong>制作信息</strong></div>
<hr/>
<div>题名:${book.bookname}</div>
<div>作者:${book.author}</div>
<div>原始地址:<a href="${book.bookUrl}">${book.bookUrl}</a></div>
<div>本文件由<a href="https://github.com/404-novel-project/novel-downloader">小说下载器</a>生成。</div>
${book.introductionHTML
? `<hr/><span>简介:</span>${book.introductionHTML.outerHTML}`
: ""}
${book.additionalMetadate.tags
? `<hr/><div>Tag列表:${book.additionalMetadate.tags.join("、")}</div>`
: ""}
</div>
</body>
</html>`;
class EPUB extends Options {
contentOpf = new DOMParser().parseFromString(content_opf, "application/xml");
metadata = this.contentOpf.querySelector("metadata");
manifest = this.contentOpf.querySelector("manifest");
spine = this.contentOpf.querySelector("spine");
guide = this.contentOpf.querySelector("guide");
ncx = new DOMParser().parseFromString(toc_ncx, "application/xml");
navMap = this.ncx.querySelector("navMap");
navHtml = new DOMParser().parseFromString(nav_xhtml, "application/xhtml+xml");
navHtmlToc = this.navHtml.getElementById("toc");
toc = new DOMParser().parseFromString(TOC_xhtml, "application/xhtml+xml");
tocBody = this.toc.body;
book;
epubZip;
constructor(book, streamZip, options) {
super();
const self = this;
this.book = book;
const zipFilename = `[${this.book.author}]${this.book.bookname}.epub`;
this.epubZip = new FflateZip(zipFilename, streamZip, "application/epub+zip");
loglevel_default().debug("[save-epub]保存epub基本文件");
saveEpubMimetype();
if (options) {
Object.assign(this, options);
}
async function saveEpubMimetype() {
await self.epubZip.file("mimetype", new Blob(["application/epub+zip"]), true);
await self.epubZip.file("META-INF/container.xml", new Blob([
`<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>`,
]));
}
}
genChapterHtmlFile(chapterObj) {
const _htmlText = chapterTemplt.render({
chapterUrl: chapterObj.chapterUrl,
chapterName: chapterObj.chapterName,
outerHTML: chapterObj.contentHTML?.outerHTML ?? "",
});
let htmlText = (0,dom/* convertHTMLtoXHTML */.pI)(_htmlText);
htmlText = this.genChapterEpub(htmlText);
return new Blob([
`<?xml version="1.0" encoding="utf-8"?>`,
htmlText
.replaceAll("data-src-address", "src")
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, "")
.replace('<html xmlns="http://www.w3.org/1999/xhtml">', '<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">'),
], {
type: "application/xhtml+xml",
});
}
async saveEpub() {
const self = this;
loglevel_default().debug("[save-epub]保存样式文件");
await saveStyle();
loglevel_default().debug("[save-epub]更新Metadata");
await updateMetadata();
if (this.book.additionalMetadate.attachments) {
loglevel_default().debug("[save]保存书籍附件");
for (const bookAttachment of this.book.additionalMetadate.attachments) {
await this.addAttachment(bookAttachment);
}
}
loglevel_default().debug("[save-epub]保存仅标题章节文件");
await saveStubChapters(this.book.chapters);
loglevel_default().debug("[save-epub]保存目录文件");
await saveToC();
await saveZipFiles();
await this.epubZip.generateAsync();
async function saveStyle() {
await self.epubZip.file("OEBPS/style.css", new Blob([self.mainStyleText]));
await self.epubZip.file("OEBPS/sgc-toc.css", new Blob([sgc_toc/* default */.A]));
}
async function updateMetadata() {
const title = self.contentOpf.createElement("dc:title");
title.textContent = self.book.bookname;
self.metadata.appendChild(title);
self.ncx.querySelector("docTitle > text").innerHTML =
(0,dom/* escapeHTML */.Zn)(self.book.bookname);
const author = self.contentOpf.createElement("dc:creator");
author.setAttribute("id", "cre");
author.textContent = self.book.author;
self.metadata.appendChild(author);
const authorMeta = self.contentOpf.createElement("meta");
authorMeta.setAttribute("refines", "#cre");
authorMeta.setAttribute("property", "role");
authorMeta.setAttribute("scheme", "marc:relators");
authorMeta.textContent = "aut";
self.metadata.appendChild(authorMeta);
const source = self.contentOpf.createElement("dc:source");
source.textContent = self.book.bookUrl;
self.metadata.appendChild(source);
const language = self.contentOpf.createElement("dc:language");
language.textContent = self.book.additionalMetadate.language ?? "zh";
self.metadata.appendChild(language);
if (self.book.introduction) {
const introduction = self.contentOpf.createElement("dc:description");
introduction.textContent = self.book.introduction;
self.metadata.appendChild(introduction);
}
if (self.book.additionalMetadate.cover) {
await self.addAttachment(self.book.additionalMetadate.cover);
const cover = self.contentOpf.createElement("meta");
cover.setAttribute("name", "cover");
cover.setAttribute("content", self.book.additionalMetadate.cover.name);
self.metadata.appendChild(cover);
await self.epubZip.file("OEBPS/cover.xhtml", new Blob([getCoverXhtml(self.book.additionalMetadate.cover.name)], {
type: "application/xhtml+xml",
}));
}
else {
self.manifest.querySelector('item[id="cover.xhtml"]')?.remove();
self.spine.querySelector('itemref[idref="cover.xhtml"]')?.remove();
self.guide.querySelector('reference[type="cover"]')?.remove();
}
if (self.book.additionalMetadate.tags) {
for (const _tag of self.book.additionalMetadate.tags) {
const tag = self.contentOpf.createElement("dc:subject");
tag.textContent = _tag;
self.metadata.appendChild(tag);
}
}
await self.epubZip.file("OEBPS/info.xhtml", new Blob([
getInfoXhtml(self.book.bookname, self.book.author)
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, ""),
], {
type: "application/xhtml+xml",
}));
await self.epubZip.file("OEBPS/message.xhtml", new Blob([
(0,dom/* convertHTMLtoXHTML */.pI)(getMessageXhtml(self.book))
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, ""),
], {
type: "application/xhtml+xml",
}));
}
async function saveStubChapters(chapters) {
chapters = chapters.filter((c) => c.status !== main/* Status */.nW.saved);
for (const c of chapters) {
if (c.status === main/* Status */.nW.finished) {
await self.addChapter(c);
}
else {
await self.addChapter(c, "Stub");
}
}
}
async function saveToC() {
loglevel_default().debug("[save-epub]对 chapters 排序");
self.book.chapters.sort(self.chapterSort);
const sectionsListObj = (0,save_misc/* getSectionsObj */.e)(self.book.chapters, self.chapterSort);
let i = 0;
let sectionNumberG = null;
let sectionNavPoint;
let sectionTOCDiv;
const navHtmlTocOl = self.navHtml.createElement("ol");
self.navHtmlToc.appendChild(navHtmlTocOl);
let sectionNavOl;
for (const sectionObj of sectionsListObj) {
const { sectionName, sectionNumber, chpaters } = sectionObj;
if (sectionNumber !== sectionNumberG) {
const sectionNumberToSave = self.getChapterNumberToSave(chpaters[0], self.book.chapters);
const sectionHtmlFileName = `No${sectionNumberToSave}Section.xhtml`;
if (sectionName) {
sectionNumberG = sectionNumber;
loglevel_default().debug(`[save-epub]保存卷HTML文件:${sectionName}`);
const sectionHTMLBlob = genSectionHtmlFile(sectionName);
await self.epubZip.file(`OEBPS/${sectionHtmlFileName}`, sectionHTMLBlob);
appendManifest(sectionHtmlFileName);
appendSpine(sectionHtmlFileName);
i++;
const navPoint = genNavPoint(i, sectionName, sectionHtmlFileName);
if (sectionNavPoint) {
self.navMap.appendChild(sectionNavPoint);
}
sectionNavPoint = navPoint;
const li = genNavHtmlLi(sectionName, sectionHtmlFileName);
sectionNavOl = self.navHtml.createElement("ol");
li.appendChild(sectionNavOl);
navHtmlTocOl.appendChild(li);
const div = genTocDiv("sgc-toc-level-1", sectionName, sectionHtmlFileName);
if (sectionTOCDiv) {
self.tocBody.appendChild(sectionTOCDiv);
}
sectionTOCDiv = div;
}
}
for (const chpater of chpaters) {
const chapterHtmlFileName = chpater.chapterHtmlFileName;
if (sectionName) {
appendSpine(chapterHtmlFileName);
i++;
const navPoint = genNavPoint(i, chpater.chapterName ?? "", chapterHtmlFileName);
sectionNavPoint?.appendChild(navPoint);
sectionNavOl?.appendChild(genNavHtmlLi(chpater.chapterName ?? "", chapterHtmlFileName));
const div = genTocDiv("sgc-toc-level-2", chpater.chapterName ?? "", chapterHtmlFileName);
sectionTOCDiv?.appendChild(div);
}
else {
appendSpine(chapterHtmlFileName);
i++;
const navPoint = genNavPoint(i, chpater.chapterName ?? "", chapterHtmlFileName);
self.navMap.appendChild(navPoint);
navHtmlTocOl.appendChild(genNavHtmlLi(chpater.chapterName ?? "", chapterHtmlFileName));
const div = genTocDiv("sgc-toc-level-2", chpater.chapterName ?? "", chapterHtmlFileName);
self.tocBody.appendChild(div);
}
}
}
if (sectionNavPoint) {
self.navMap.appendChild(sectionNavPoint);
}
if (sectionTOCDiv) {
self.tocBody.appendChild(sectionTOCDiv);
}
await self.epubZip.file("OEBPS/content.opf", new Blob([
new XMLSerializer()
.serializeToString(self.contentOpf)
.replaceAll('xmlns=""', "")
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, ""),
], { type: "application/oebps-package+xml" }));
await self.epubZip.file("OEBPS/toc.ncx", new Blob([
new XMLSerializer()
.serializeToString(self.ncx)
.replaceAll('xmlns=""', "")
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, ""),
], { type: "application/x-dtbncx+xml" }));
await self.epubZip.file("OEBPS/nav.xhtml", new Blob([
new XMLSerializer()
.serializeToString(self.navHtml)
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, ""),
], {
type: "application/xhtml+xml",
}));
await self.epubZip.file("OEBPS/TOC.xhtml", new Blob([
new XMLSerializer()
.serializeToString(self.toc)
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, ""),
], { type: "application/xhtml+xml" }));
function appendManifest(htmlFileName) {
const item = self.contentOpf.createElement("item");
item.id = htmlFileName;
item.setAttribute("href", htmlFileName);
item.setAttribute("media-type", "application/xhtml+xml");
if (!self.manifest.querySelector(`itme[id="${htmlFileName}"]`)) {
self.manifest.appendChild(item);
}
}
function appendSpine(htmlFileName) {
const itemref = self.contentOpf.createElement("itemref");
itemref.setAttribute("idref", htmlFileName);
self.spine.appendChild(itemref);
}
function genNavPoint(num, name, htmlFileName) {
const navPoint = self.ncx.createElement("navPoint");
navPoint.id = `navPoint-${num}`;
navPoint.setAttribute("playOrder", num.toString());
const navLabel = self.ncx.createElement("navLabel");
const text = self.ncx.createElement("text");
text.textContent = name;
const content = self.ncx.createElement("content");
content.setAttribute("src", htmlFileName);
navLabel.appendChild(text);
navPoint.appendChild(navLabel);
navPoint.appendChild(content);
return navPoint;
}
function genNavHtmlLi(name, htmlFileName) {
const li = self.navHtml.createElement("li");
const a = self.navHtml.createElement("a");
a.textContent = name;
a.href = htmlFileName;
li.appendChild(a);
return li;
}
function genTocDiv(className, name, htmlFileName) {
const div = self.toc.createElement("div");
div.className = className;
const a = self.toc.createElement("a");
a.href = htmlFileName;
a.innerText = name;
div.appendChild(a);
return div;
}
function genSectionHtmlFile(sectionName) {
const _htmlText = section.render({ sectionName: sectionName });
const htmlText = (0,dom/* convertHTMLtoXHTML */.pI)(_htmlText);
return new Blob([
`<?xml version="1.0" encoding="utf-8"?>`,
htmlText
.replaceAll("data-src-address", "src")
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, "")
.replace('<html xmlns="http://www.w3.org/1999/xhtml">', '<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">'),
], {
type: "application/xhtml+xml",
});
}
}
async function saveZipFiles() {
loglevel_default().debug("[save-zip]保存元数据文本");
const metaDateText = self.genMetaDateTxt(self.book);
await self.epubZip.file("OEBPS/info.txt", new Blob([metaDateText], { type: "text/plain;charset=utf-8" }));
loglevel_default().debug("[save-zip]保存web样式");
await self.epubZip.file("OEBPS/web.css", new Blob([web/* default */.A], { type: "text/css;charset=utf-8" }));
modifyTocStyleText();
await self.epubZip.file("OEBPS/toc.css", new Blob([self.tocStyleText], { type: "text/css;charset=utf-8" }));
await self.epubZip.file("OEBPS/web.js", new Blob([
`if (typeof fetch === "function" && !navigator.userAgent.includes("calibre-viewer") && navigator.userAgent.startsWith("Mozilla/5.0")) {
const link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = "web.css";
document.head.append(link);
}`,
], { type: "application/javascript" }));
loglevel_default().debug("[save-zip]开始生成并保存 index.html");
await saveIndex();
loglevel_default().debug("[save-zip]开始保存 Meta Data Json");
await saveMetaJson();
function modifyTocStyleText() {
if (self.book.additionalMetadate.cover) {
self.tocStyleText = `${self.tocStyleText}
.info {
display: grid;
grid-template-columns: 30% 70%;
}`;
}
else {
self.tocStyleText = `${self.tocStyleText}
.info {
display: grid;
grid-template-columns: 100%;
}`;
}
}
async function saveIndex() {
loglevel_default().debug("[save]对 chapters 排序");
self.book.chapters.sort(self.chapterSort);
const sectionsListObj = (0,save_misc/* getSectionsObj */.e)(self.book.chapters, self.chapterSort);
const _indexHtmlText = index.render({
creationDate: Date.now(),
bookname: self.book.bookname,
author: self.book.author,
cover: self.book.additionalMetadate.cover,
introductionHTML: self.book.introductionHTML?.outerHTML,
bookUrl: self.book.bookUrl,
sectionsObj: Object.values(sectionsListObj),
Status: main/* Status */.nW,
});
const indexHtmlText = (0,dom/* convertHTMLtoXHTML */.pI)(_indexHtmlText);
await self.epubZip.file("OEBPS/index.xhtml", new Blob([
indexHtmlText
.replaceAll("data-src-address", "src")
.replaceAll(/[\u{0000}-\u{001f}]/gu, "")
.replaceAll(/[\u{007f}-\u{009f}]/gu, ""),
], {
type: "application/xhtml+xml; charset=UTF-8",
}));
}
async function saveMetaJson() {
await self.epubZip.file("OEBPS/book.json", new Blob([JSON.stringify(self.book)], {
type: "application/json; charset=utf-8",
}));
await self.epubZip.file("OEBPS/chapters.json", new Blob([JSON.stringify(self.book.chapters)], {
type: "application/json; charset=utf-8",
}));
}
}
}
async addChapter(chapter, suffix = "") {
const chapterName = this.getchapterName(chapter);
const chapterNumberToSave = this.getChapterNumberToSave(chapter, this.book.chapters);
const chapterHtmlFileName = `No${chapterNumberToSave}Chapter${suffix}.xhtml`;
chapter.chapterHtmlFileName = chapterHtmlFileName;
loglevel_default().debug(`[save-epub]保存章HTML文件:${chapterName}`);
const chapterHTMLBlob = this.genChapterHtmlFile(chapter);
await this.epubZip.file(`OEBPS/${chapterHtmlFileName}`, chapterHTMLBlob);
const item = this.contentOpf.createElement("item");
item.id = chapterHtmlFileName;
item.setAttribute("href", chapterHtmlFileName);
item.setAttribute("media-type", "application/xhtml+xml");
if (!this.manifest.querySelector(`item[id="${chapterHtmlFileName}"]`)) {
this.manifest.appendChild(item);
}
if (chapter.contentImages && chapter.contentImages.length !== 0) {
loglevel_default().debug(`[save-epub]保存章节附件:${chapterName}`);
for (const attachment of chapter.contentImages) {
await this.addAttachment(attachment);
}
}
}
async addAttachment(attachment) {
if (attachment.status === main/* Status */.nW.finished && attachment.Blob) {
loglevel_default().debug(`[save-epub]添加附件,文件名:${attachment.name},对象`, attachment.Blob);
await this.epubZip.file(`OEBPS/${attachment.name}`, attachment.Blob);
const item = this.contentOpf.createElement("item");
item.id = attachment.name;
item.setAttribute("href", attachment.name);
const mimetype = (0,misc/* extensionToMimetype */.dB)(attachment.name.substring(attachment.name.lastIndexOf(".") + 1));
item.setAttribute("media-type", mimetype);
if (!this.manifest.querySelector(`item[id="${attachment.name}"]`)) {
this.manifest.appendChild(item);
}
}
else if (attachment.status === main/* Status */.nW.saved) {
loglevel_default().debug(`[save-epub]附件${attachment.name}已添加`);
}
else {
loglevel_default().warn(`[save-epub]添加附件${attachment.name}失败,该附件未完成或内容为空。`);
loglevel_default().warn(attachment);
}
}
}
;// ./src/save/txt.ts
class TXT extends Options {
book;
savedTextArray = [];
saveFileNameBase;
constructor(book, options) {
super();
this.book = book;
this.saveFileNameBase = `[${this.book.author}]${this.book.bookname}`;
if (options) {
Object.assign(this, options);
}
}
saveTxt() {
const chapters = this.book.chapters;
const metaDateText = this.genMetaDateTxt(this.book);
this.savedTextArray.push(metaDateText);
loglevel_default().debug("[save]对 chapters 排序");
chapters.sort(this.chapterSort);
const sections = [];
for (const chapterTemp of chapters) {
const chapterName = this.getchapterName(chapterTemp);
if (chapterTemp.sectionName &&
!sections.includes(chapterTemp.sectionName)) {
sections.push(chapterTemp.sectionName);
const sectionText = this.genSectionText(chapterTemp.sectionName);
this.savedTextArray.push(sectionText);
}
const chapterText = this.genChapterText(chapterName, chapterTemp.contentText ?? "");
this.savedTextArray.push(chapterText);
if (!setting/* enableDebug */.Nw.value) {
chapterTemp.contentText = null;
}
}
loglevel_default().info("[save]保存TXT文件");
const savedText = this.savedTextArray.join("\n").replaceAll("\n", "\r\n");
(0,FileSaver_min.saveAs)(new Blob([savedText], { type: "text/plain;charset=utf-8" }), `${this.saveFileNameBase}.txt`);
}
}
;// ./src/save/raw.ts
class Raw {
book;
epubZip;
constructor(book) {
this.book = book;
if (this.book.saveType.raw instanceof Object) {
const zipFilename = `[${this.book.author}]${this.book.bookname}.${this.book.saveType.raw.ext}`;
this.epubZip = new FflateZip(zipFilename, false, (0,misc/* extensionToMimetype */.dB)(this.book.saveType.raw.ext));
}
else {
throw new Error("init raw save zip failed!");
}
}
async saveRaw() {
const attachments = this.book.additionalMetadate.attachments;
const tasks = attachments?.map(async (attach) => {
if (attach.Blob) {
await this.epubZip.file(attach.name, attach.Blob, attach.comments === "nocompress");
}
}) ?? [];
await Promise.all(tasks);
await this.epubZip.generateAsync();
}
}
;// ./src/save/save.ts
class SaveBook {
saveType;
txt;
epub;
raw;
constructor(book, streamZip, options) {
const _options = {};
if (options !== undefined) {
Object.assign(_options, options);
}
if (book.saveOptions !== undefined) {
Object.assign(_options, book.saveOptions);
}
this.saveType = book.saveType;
this.txt = new TXT(book, _options);
this.epub = new EPUB(book, streamZip, _options);
if (this.saveType.raw instanceof Object) {
this.raw = new Raw(book);
}
}
static saveLog() {
(0,FileSaver_min.saveAs)(new Blob([log/* logText */.kc], { type: "text/plain; charset=UTF-8" }), "debug.log");
}
async addChapter(chapter) {
await this.epub.addChapter(chapter);
if (!setting/* enableDebug */.Nw.value) {
chapter.contentRaw = null;
chapter.contentHTML = null;
chapter.contentImages = null;
}
if (chapter.contentImages && chapter.contentImages.length !== 0) {
for (const attachment of chapter.contentImages) {
attachment.status = main/* Status */.nW.saved;
if (!setting/* enableDebug */.Nw.value) {
attachment.Blob = null;
}
}
}
chapter.status = main/* Status */.nW.saved;
}
async save() {
if (setting/* TxtDownload */.Jv.value && this.saveType.txt) {
this.saveTxt();
}
if (setting/* enableDebug */.Nw.value) {
SaveBook.saveLog();
}
if (setting/* EpubDownload */.Zz.value && this.saveType.epub) {
await this.saveEpub();
}
if (this.saveType.raw instanceof Object) {
await this.saveRaw();
}
}
saveTxt() {
this.txt.saveTxt();
}
async saveEpub() {
await this.epub.saveEpub();
}
async saveRaw() {
await this.raw.saveRaw();
}
}
;// ./src/stat.ts
const statKeyName = "novel-downloader-22932304826849026";
const domain = document.location.hostname;
async function getStatData() {
const _data = (await (0,GM/* _GM_getValue */.er)(statKeyName));
let statData;
if (_data) {
statData = JSON.parse(_data);
}
else {
statData = { success: {}, failed: {} };
}
return statData;
}
const saveData = async (statData) => {
const dataJSON = JSON.stringify(statData);
await (0,GM/* _GM_setValue */.mN)(statKeyName, dataJSON);
return statData;
};
const dataPlus = async (key) => {
const statData = await getStatData();
const tmpData = statData[key];
if (tmpData[domain]) {
tmpData[domain] = tmpData[domain] + 1;
}
else {
tmpData[domain] = 1;
}
return saveData(statData);
};
const successPlus = () => {
return dataPlus("success");
};
const failedPlus = () => {
return dataPlus("failed");
};
const printStat = async () => {
const statData = await getStatData();
loglevel_default().info("[stat]小说下载器脚本运行情况统计:");
loglevel_default().info(statData);
for (const k in statData) {
if (Object.prototype.hasOwnProperty.call(statData, k)) {
loglevel_default().info(`[stat]${k}:`);
const subData = statData[k];
for (const j in subData) {
if (Object.prototype.hasOwnProperty.call(subData, j)) {
loglevel_default().info(` ${j}: ${subData[j]}`);
}
}
}
}
};
const resetStat = () => {
const statData = { success: {}, failed: {} };
return saveData(statData);
};
// EXTERNAL MODULE: ./src/ui/progress.ts + 1 modules
var progress = __webpack_require__("./src/ui/progress.ts");
;// ./src/rules.ts
class BaseRuleClass {
attachmentMode = "TM";
charset = document.characterSet;
concurrencyLimit = 10;
sleepTime = 50;
maxSleepTime = 500;
streamZip = false;
needLogin = false;
nsfw = false;
maxRunLimit;
saveOptions;
book;
saveType;
bcWorker = new BroadcastChannel("novel-downloader-worker");
bcWorkerMessages = [];
audio;
constructor() {
const broadcastChannelWorker = this.bcWorker;
const messages = this.bcWorkerMessages;
broadcastChannelWorker.onmessage = (ev) => {
const message = ev.data;
if (message.type === "ping") {
const pong = {
type: "pong",
src: message.workerId,
workerId: window.workerId,
url: document.location.href,
};
broadcastChannelWorker.postMessage(pong);
}
if (message.type === "pong") {
messages.push(message);
}
if (message.type === "close") {
loglevel_default().debug(`${window.workerId} has closed!`);
}
};
}
async run() {
loglevel_default().info(`[run]下载开始`);
const self = this;
try {
await self.preHook();
await initBook();
const saveBookObj = initSave(self.book);
initDownload();
await saveHook();
await self.initChapters(self.book, saveBookObj).catch((error) => {
if (error instanceof main/* ExpectError */.K5) {
console.warn(error);
}
else {
throw error;
}
});
await save(saveBookObj);
self.postHook();
return self.book;
}
catch (error) {
self.catchError(error);
}
function initDownload() {
if (setting/* customDownload */.WZ.value) {
loglevel_default().info("[run]发现自定义下载设置,将进行覆盖");
self.concurrencyLimit = setting/* concurrencyLimit */.ri.value;
self.sleepTime = setting/* sleepTime */.Xl.value;
self.maxSleepTime = setting/* maxSleepTime */.Fe.value;
}
}
async function initBook() {
if (window._book &&
window._url === document.location.href) {
self.book = window._book;
}
else {
self.book = await self.bookParse();
window._book = self.book;
window._url = document.location.href;
}
loglevel_default().debug("[book]Book object:\n" + JSON.stringify(self.book));
}
function initSave(book) {
loglevel_default().debug("[run]保存数据");
if (setting/* enableCustomSaveOptions */.k8 &&
typeof unsafeWindow.saveOptions === "object" &&
saveOptionsValidate(unsafeWindow.saveOptions)) {
const saveOptions = unsafeWindow.saveOptions;
if (saveOptions) {
loglevel_default().info("[run]发现自定义保存参数,内容如下\n", saveOptions);
return new SaveBook(book, self.streamZip, saveOptions);
}
}
return new SaveBook(book, self.streamZip);
}
async function saveHook() {
if (setting/* enableSaveToArchiveOrg */.KV &&
!self.needLogin &&
self.book?.bookUrl &&
window.localStorageExpired.get(`${self.book.bookUrl}_saveToArchiveOrg`) === undefined &&
(await (0,setting/* getCustomEnableSaveToArchiveOrg */.BV)())) {
console.log("[saveToArchiveOrg]保存当前书页至 archive.org");
try {
window.localStorageExpired.set(`${self.book.bookUrl}_saveToArchiveOrg`, true, 86400);
}
catch (error) {
}
(0,misc/* saveToArchiveOrg */.ZA)(self.book.bookUrl).then((r) => loglevel_default().info(r));
if (self.book.ToCUrl) {
(0,misc/* saveToArchiveOrg */.ZA)(self.book.ToCUrl).then((r) => loglevel_default().info(r));
}
}
}
async function save(saveObj) {
loglevel_default().debug("[run]开始保存文件");
await saveObj.save();
}
}
async preHook() {
const self = this;
if (!(await preTest())) {
const alertText = `当前网站目前最多允许${self.maxRunLimit}个下载任务同时进行。\n请待其它下载任务完成后,再行尝试。`;
alert(alertText);
loglevel_default().info(`[run]${alertText}`);
throw new main/* ExpectError */.K5(alertText);
}
self.audio = new Audio("data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcxLjEwMAAAAAAAAAAAAAAA/+M4wAAAAAAAAAAAAEluZm8AAAAPAAAAEAAABVgANTU1NTU1Q0NDQ0NDUFBQUFBQXl5eXl5ea2tra2tra3l5eXl5eYaGhoaGhpSUlJSUlKGhoaGhoaGvr6+vr6+8vLy8vLzKysrKysrX19fX19fX5eXl5eXl8vLy8vLy////////AAAAAExhdmM1Ny44OQAAAAAAAAAAAAAAACQCgAAAAAAAAAVY82AhbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+MYxAALACwAAP/AADwQKVE9YWDGPkQWpT66yk4+zIiYPoTUaT3tnU487uNhOvEmQDaCm1Yz1c6DPjbs6zdZVBk0pdGpMzxF/+MYxA8L0DU0AP+0ANkwmYaAMkOKDDjmYoMtwNMyDxMzDHE/MEsLow9AtDnBlQgDhTx+Eye0GgMHoCyDC8gUswJcMVMABBGj/+MYxBoK4DVpQP8iAtVmDk7LPgi8wvDzI4/MWAwK1T7rxOQwtsItMMQBazAowc4wZMC5MF4AeQAGDpruNuMEzyfjLBJhACU+/+MYxCkJ4DVcAP8MAO9J9THVg6oxRMGNMIqCCTAEwzwwBkINOPAs/iwjgBnMepYyId0PhWo+80PXMVsBFzD/AiwwfcKGMEJB/+MYxDwKKDVkAP8eAF8wMwIxMlpU/OaDPLpNKkEw4dRoBh6qP2FC8jCJQFcweQIPMHOBtTBoAVcwOoCNMYDI0u0Dd8ANTIsy/+MYxE4KUDVsAP8eAFBVpgVVPjdGeTEWQr0wdcDtMCeBgDBkgRgwFYB7Pv/zqx0yQQMCCgKNgonHKj6RRVkxM0GwML0AhDAN/+MYxF8KCDVwAP8MAIHZMDDA3DArAQo3K+TF5WOBDQw0lgcKQUJxhT5sxRcwQQI+EIPWMA7AVBoTABgTgzfBN+ajn3c0lZMe/+MYxHEJyDV0AP7MAA4eEwsqP/PDmzC/gNcwXUGaMBVBIwMEsmB6gaxhVuGkpoqMZMQjooTBwM0+S8FTMC0BcjBTgPwwOQDm/+MYxIQKKDV4AP8WADAzAKQwI4CGPhWOEwCFAiBAYQnQMT+uwXUeGzjBWQVkwTcENMBzA2zAGgFEJfSPkPSZzPXgqFy2h0xB/+MYxJYJCDV8AP7WAE0+7kK7MQrATDAvQRIwOADKMBuA9TAYQNM3AiOSPjGxowgHMKFGcBNMQU1FMy45OS41VVU/31eYM4sK/+MYxKwJaDV8AP7SAI4y1Yq0MmOIADGwBZwwlgIJMztCM0qU5TQPG/MSkn8yEROzCdAxECVMQU1FMy45OS41VTe7Ohk+Pqcx/+MYxMEJMDWAAP6MADVLDFUx+4J6Mq7NsjN2zXo8V5fjVJCXNOhwM0vTCDAxFpMYYQU+RlVMQU1FMy45OS41VVVVVVVVVVVV/+MYxNcJADWAAP7EAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxOsJwDWEAP7SAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxPMLoDV8AP+eAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV/+MYxPQL0DVcAP+0AFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV");
self.audio.loop = true;
await self.audio.play();
window.onbeforeunload = (e) => {
e.preventDefault();
const confirmationText = "您正尝试离开本页面,当前页面有下载任务正在运行,是否确认离开?";
return (e.returnValue = confirmationText);
};
window.downloading = true;
async function preTest() {
const broadcastChannelWorker = self.bcWorker;
const messages = self.bcWorkerMessages;
const ping = {
type: "ping",
workerId: window.workerId,
url: document.location.href,
};
broadcastChannelWorker.postMessage(ping);
await (0,misc/* sleep */.yy)(300);
const workers = messages
.filter((m) => m.type === "pong" &&
m.src === window.workerId &&
m.workerId !== window.workerId)
.map((m) => ({
id: m.workerId,
url: m.url,
}));
loglevel_default().info(JSON.stringify(workers, undefined, 4));
const nowRunning = workers.length;
loglevel_default().info(`[preTest]nowRunning: ${nowRunning}`);
if (self.maxRunLimit) {
return nowRunning < self.maxRunLimit;
}
else {
return true;
}
}
}
async initChapters(book, saveBookObj) {
const self = this;
loglevel_default().info(`[initChapters]开始初始化章节`);
Object.entries(self).forEach((kv) => loglevel_default().info(`[initChapters] ${kv[0]}: ${kv[1]}`));
const chapters = getChapters(book);
if (chapters.length === 0) {
loglevel_default().error(`[initChapters]初始化章节出错,未找到需初始化章节`);
return [];
}
progress.vm.totalChapterNumber = chapters.length;
if (self.concurrencyLimit === 1) {
let chapteri = -1;
for (const chapter of chapters) {
if (window.failedCount > 10) {
if (!window.stopFlag.aborted) {
window.stopController.abort();
console.error("连续十章下载失败,放弃本次下载。\n请附上相关日志至支持地址进行反馈。\n支持地址:https://github.com/404-novel-project/novel-downloader");
alert("连续十章下载失败,放弃本次下载。\n请附上相关日志至支持地址进行反馈。\n支持地址:https://github.com/404-novel-project/novel-downloader");
(0,log/* saveLogTextToFile */.M6)();
}
}
if (window.stopFlag.aborted) {
throw new main/* ExpectError */.K5("[chapter]收到停止信号,停止继续下载。");
}
try {
chapteri++;
await (0,misc/* sleep */.yy)(Math.min(self.maxSleepTime, chapteri * self.sleepTime) + Math.round(Math.random() * 1000));
let chapterObj = await chapter.init();
chapterObj = await postChapterParseHook(chapterObj, saveBookObj);
}
catch (error) {
loglevel_default().error(error);
loglevel_default().trace(error);
}
}
}
else {
const asyncHandle = async (curChapter) => {
if (window.failedCount > 10) {
if (!window.stopFlag.aborted) {
window.stopController.abort();
console.error("连续十章下载失败,放弃本次下载。\n请附上相关日志至支持地址进行反馈。\n支持地址:https://github.com/404-novel-project/novel-downloader");
alert("连续十章下载失败,放弃本次下载。\n请附上相关日志至支持地址进行反馈。\n支持地址:https://github.com/404-novel-project/novel-downloader");
(0,log/* saveLogTextToFile */.M6)();
}
}
if (curChapter === undefined) {
return null;
}
try {
let chapterObj = await curChapter.init();
chapterObj = await postChapterParseHook(chapterObj, saveBookObj);
return chapterObj;
}
catch (error) {
loglevel_default().error(error);
loglevel_default().trace(error);
}
};
await (0,misc/* concurrencyRun */.rr)(chapters, self.concurrencyLimit, asyncHandle, {
signal: window.stopFlag,
reason: "[chapter]收到停止信号,停止继续下载。",
});
}
loglevel_default().info(`[initChapters]章节初始化完毕`);
return chapters;
function getChapters(_book) {
function isEnable() {
if (setting/* enableCustomChapterFilter */.U5 &&
typeof unsafeWindow.chapterFilter === "function") {
let text = "[initChapters]发现自定义筛选函数,自定义筛选函数内容如下:\n";
text += unsafeWindow.chapterFilter?.toString();
loglevel_default().info(text);
return true;
}
else {
return false;
}
}
function _filter(chapter) {
let b = true;
try {
const u = unsafeWindow.chapterFilter?.(chapter);
if (typeof u === "boolean") {
b = u;
}
}
catch (error) {
loglevel_default().error("运行自定义筛选函数时出错。", error);
loglevel_default().trace(error);
}
return b;
}
let _chapters = _book.chapters.filter((chapter) => chapter.status === main/* Status */.nW.pending);
const enabled = isEnable();
if (enabled) {
loglevel_default().debug("[initChapters]筛选需下载章节");
_chapters = _chapters.filter((chapter) => _filter(chapter));
}
_book.chapters = _chapters;
return _chapters;
}
async function postChapterParseHook(chapter, saveObj) {
if (chapter.contentHTML !== undefined) {
await saveObj.addChapter(chapter);
progress.vm.finishedChapterNumber++;
}
return chapter;
}
}
postHook() {
const self = this;
(0,attachments/* clearAttachmentClassCache */.rd)();
self.audio?.pause();
self.audio?.remove();
const closeMessage = {
type: "close",
workerId: window.workerId,
url: document.location.href,
};
self.bcWorker.postMessage(closeMessage);
self.bcWorker.onmessage = null;
self.bcWorker.close();
self.bcWorkerMessages.splice(0, self.bcWorkerMessages.length);
window.onbeforeunload = null;
window.downloading = false;
progress.vm.reset();
window._book = undefined;
window._url = undefined;
postCallback();
successPlus().then(() => {
printStat();
});
function postCallback() {
if (setting/* enableCustomFinishCallback */.zb &&
typeof unsafeWindow.customFinishCallback ===
"function") {
const customFinishCallback = unsafeWindow
.customFinishCallback;
if (customFinishCallback) {
loglevel_default().info(`发现自定义结束回调函数,内容如下:\n${customFinishCallback.toString()}`);
customFinishCallback();
}
}
}
}
catchError(error) {
const self = this;
loglevel_default().error(error);
loglevel_default().trace(error);
self.postHook();
if (!(error instanceof main/* ExpectError */.K5)) {
document.getElementById("button-div")?.remove();
loglevel_default().error("运行过程出错,请附上相关日志至支持地址进行反馈。\n支持地址:https://github.com/404-novel-project/novel-downloader");
failedPlus();
alert("运行过程出错,请附上相关日志至支持地址进行反馈。\n支持地址:https://github.com/404-novel-project/novel-downloader");
window.open("https://github.com/404-novel-project/novel-downloader/issues");
(0,log/* saveLogTextToFile */.M6)();
}
}
}
/***/ }),
/***/ "./src/rules/biquge/mht.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ mht: () => (/* binding */ mht)
/* harmony export */ });
/* harmony import */ var _onePage_template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules/biquge/template.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/lib/cleanDOM.ts");
const mht = () => (0,_onePage_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
...(0,_template__WEBPACK_IMPORTED_MODULE_1__/* .baseOnePage */ .Tm)((introDom) => introDom, 5),
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const ngetHtmlDOM = (input, charset, init) => {
const test = async (response) => {
const resp = response.clone();
const text = await resp.text();
return text.includes('<div id="content">');
};
return (0,_lib_http__WEBPACK_IMPORTED_MODULE_2__/* .getHtmlDOM */ .wA)(input, charset, init, test);
};
const { contentRaw } = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_3__/* .nextPageParse */ .u1)({
chapterName,
chapterUrl,
charset,
selector: "#content",
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_4__.rm)("p[data-id]", true, content);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_5__/* .htmlTrim */ .is)(content);
return content;
},
getNextPage: (doc) => doc.querySelector(".bottem2 > a:nth-child(4)")
.href,
continueCondition: (_content, nextLink) => new URL(nextLink).pathname.includes("_"),
enableCleanDOM: false,
getHtmlDomFunc: ngetHtmlDOM,
});
return contentRaw;
},
contentPatch: (dom) => dom,
});
/***/ }),
/***/ "./src/rules/biquge/multiIndexNextPage.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ c226ks: () => (/* binding */ c226ks),
/* harmony export */ znlzd: () => (/* binding */ znlzd)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/biquge/template.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
const znlzd = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkBiqugeMultiIndexNextPage */ .FN)((dom) => dom, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("div", true, content);
return content;
}, (doc) => doc.querySelector("div.section-opt:nth-child(1) > a:nth-child(5)")?.href ?? "", (_content, nextLink) => {
if (nextLink === "") {
return false;
}
const pathname = nextLink.split("/").slice(-1)[0];
return pathname.includes("_");
}, 3);
const c226ks = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkBiqugeMultiIndexNextPage */ .FN)((introDom) => introDom, (content) => content, (doc) => doc.querySelector("section.g-content-nav > a:nth-child(3)").href, (_content, nextLink) => {
const pathname = nextLink.split("/").slice(-1)[0];
return pathname.includes("_");
});
/***/ }),
/***/ "./src/rules/biquge/nextPage.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ mijiashe: () => (/* binding */ mijiashe),
/* harmony export */ xinwanben: () => (/* binding */ xinwanben),
/* harmony export */ ywggzy: () => (/* binding */ ywggzy)
/* harmony export */ });
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/biquge/template.ts");
const xinwanben = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkBiqugeNextPage */ .uk)((introDom) => {
const _bookname = introDom.innerHTML.match(/《(.*)》/);
let bookname;
if (_bookname?.length === 2) {
bookname = _bookname[1];
}
const adList = [
"还不错的话请不要忘记向您QQ群和微博里的朋友推荐哦!",
"小说免费阅读地址:",
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rm2 */ .Sf)(adList, introDom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)([`${bookname}小说简介:`], introDom);
return introDom;
}, (content) => {
const filters = [
"手机用户输入地址",
"提示:浏览器搜索",
"把本站分享那些需要的小伙伴!找不到书请留言!",
"【完本神站】",
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rm2 */ .Sf)(filters, content);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_2__/* .htmlTrim */ .is)(content);
return content;
}, (doc) => doc.querySelector("#next_url").href, (_content, nextLink) => new URL(nextLink).pathname.includes("_"));
const mijiashe = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkBiqugeNextPage */ .uk)((introDom) => {
const _bookname = introDom.innerHTML.match(/《(.*)》/);
let bookname;
if (_bookname?.length === 2) {
bookname = _bookname[1];
}
const adList = [
"还不错的话请不要忘记向您QQ群和微博里的朋友推荐哦!",
"小说免费阅读地址:",
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rm2 */ .Sf)(adList, introDom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)([`${bookname}小说简介:`], introDom);
return introDom;
}, (content) => {
const filters = [
"谨记我们的网址,祝大家阅读愉快!别忘了多多宣传宣传。",
"【提示】:如果觉得此文不错,请推荐给更多小伙伴吧!分享也是一种享受。",
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rm2 */ .Sf)(filters, content);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_2__/* .htmlTrim */ .is)(content);
return content;
}, (doc) => doc.querySelector("#next_url").href, (_content, nextLink) => new URL(nextLink).pathname.includes("_"));
const ywggzy = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkBiqugeNextPage */ .uk)((initroDom) => initroDom, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".posterror", false, content);
return content;
}, (doc) => doc.querySelector("div.section-opt:nth-child(1) > a:nth-child(5)")?.href ?? "", (_content, nextLink) => new URL(nextLink).pathname.includes("_"));
/***/ }),
/***/ "./src/rules/biquge/onePage.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ b5200: () => (/* binding */ b5200),
/* harmony export */ biquwx: () => (/* binding */ biquwx),
/* harmony export */ bqu9: () => (/* binding */ bqu9),
/* harmony export */ bxwx333: () => (/* binding */ bxwx333),
/* harmony export */ c25zw: () => (/* binding */ c25zw),
/* harmony export */ common: () => (/* binding */ common),
/* harmony export */ dijiubook: () => (/* binding */ dijiubook),
/* harmony export */ gebiqu: () => (/* binding */ gebiqu),
/* harmony export */ la42zw: () => (/* binding */ la42zw),
/* harmony export */ lewenn: () => (/* binding */ lewenn),
/* harmony export */ luoqiuzw: () => (/* binding */ luoqiuzw),
/* harmony export */ lusetxt: () => (/* binding */ lusetxt),
/* harmony export */ ranwen: () => (/* binding */ ranwen),
/* harmony export */ shuquge: () => (/* binding */ shuquge),
/* harmony export */ tycqxs: () => (/* binding */ tycqxs),
/* harmony export */ xbiquge: () => (/* binding */ xbiquge),
/* harmony export */ xbiqugeLa: () => (/* binding */ xbiqugeLa),
/* harmony export */ xyb3: () => (/* binding */ xyb3),
/* harmony export */ yqxs: () => (/* binding */ yqxs),
/* harmony export */ yruan: () => (/* binding */ yruan)
/* harmony export */ });
/* harmony import */ var _lib_misc__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/misc.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules/biquge/template.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/cleanDOM.ts");
const commonContentPatch = (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("script", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div[style]", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div[align]", true, content);
return content;
};
const common = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, commonContentPatch);
const gebiqu = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([/如果您喜欢.+,别忘记分享给朋友/g], introDom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)('a[href^="http://down.gebiqu.com"]', false, introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([/"www.gashuw.com"/g], content);
return content;
});
const bqu9 = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([/如果您喜欢.+,别忘记分享给朋友/g], introDom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)('a[href^="http://down.gebiqu.com"]', false, introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(['请收藏本站:https://www.bqu9.cc。笔趣阁手机版:https://m.bqu9.cc/'], content);
return content;
}, "#chaptercontent");
const luoqiuzw = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, (content) => {
const ad = content.firstElementChild;
if (ad.innerText.includes("天才一秒记住本站地址:")) {
ad.remove();
}
const ads = ["记住网址m.luoqiuxzw.com"];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)(ads, content);
return content;
});
const biquwx = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([
/本站提示:各位书友要是觉得《.+》还不错的话请不要忘记向您QQ群和微博里的朋友推荐哦!/,
], introDom);
return introDom;
}, (content) => content, undefined, 1);
const tycqxs = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("a", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)(["推荐都市大神老施新书:"], content);
return content;
});
const dijiubook = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)(["本书网址:"], introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("a", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)('img[src$="alipay.png"]', true, content);
return content;
}, undefined, 1, 50, 3000, (classThis) => {
classThis.maxRunLimit = 1;
const chapterParse = classThis.chapterParse;
classThis.chapterParse = async (...args) => {
const obj = await chapterParse(...args);
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_2__/* .sleep */ .yy)(3000 * Math.random());
return obj;
};
return classThis;
}, (chapter) => {
const url = new URL(chapter.chapterUrl);
if (url.host === "m.dijiuben.com" || url.href.endsWith(".apk")) {
return;
}
else {
return chapter;
}
});
const c25zw = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
introDom.querySelector("font")?.parentElement?.remove();
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)(["简介:"], introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)(".bottem", false, content);
return content;
});
const xbiquge = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([/笔趣阁 www.xbiquge.tw,最快更新.+ !/], content);
return content;
});
const yruan = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["本站提示:各位书友要是觉得"], introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("b", true, content);
return content;
}, undefined, 3);
const ranwen = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["还不错的话请不要忘记向您QQ群和微博里的朋友推荐哦!"], introDom);
return introDom;
}, (content) => content);
const b5200 = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, (content) => content, undefined, 1);
const bxwx333 = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, (content) => {
content.querySelector("#xuanchuan")?.parentElement?.remove();
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div[style]", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)(".bottem2", true, content);
return content;
}, "#zjneirong");
const xbiqugeLa = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
introDom.querySelector("font")?.parentElement?.remove();
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["手机站全新改版升级地址"], content);
return content;
}, undefined, 1);
const shuquge = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
document.querySelector(".noshow")?.classList.remove("noshow");
if (document.querySelector(".showall")) {
document.querySelector(".showall").innerHTML = "";
}
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([
/作者:.+所写的《.+》无弹窗免费全文阅读为转载作品,章节由网友发布。/,
/推荐地址:https?:\/\/www\.ishuquge\.org\/txt\/\d+\/index\.html/g,
], introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["请记住本书首发域名:", "www.ishuquge.org"], content);
return content;
}, undefined, 1);
const lusetxt = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["无弹窗免费全文阅读为转载作品", "无弹窗推荐地址", "简介:"], introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("script", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div[style]", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div[align]", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["https://www.lvsewx.com/books", "请记住本书首发域名"], content);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_3__/* .htmlTrim */ .is)(content);
return content;
});
const yqxs = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)(["<span>简介:</span>"], introDom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["推荐地址:"], introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("script", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)('div[align="center"]', false, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["//www.yqxsge.cc/html/", "请记住本书首发域名"], content);
return content;
});
const lewenn = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([
/各位书友要是觉得《.*》还不错的话请不要忘记向您QQ群和微博里的朋友推荐哦!/,
], introDom);
return introDom;
}, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("script", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)('div[align="center"]', false, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)(["//www.lewenn.net/lw", "1秒记住乐文小说网"], content);
return content;
});
const xyb3 = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("script", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div[style]", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div[align]", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rm2 */ .Sf)([
"由于各种问题yb3.cc地址更改为xyb3.net请大家收藏新地址避免迷路",
"网页版章节内容慢,请下载好阅小说app阅读最新内容",
"请退出转码页面,请下载好阅小说app 阅读最新章节。",
"https://www.xyb3.net",
], content);
return content;
});
const la42zw = () => (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkBiquge */ .Wt)((introDom) => introDom, (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("div#content > p:first-child", false, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__/* .rms */ .j3)([
"首发网址https://m.42zw.la",
"记住网址m.42zw.la",
"一秒记住https://m.42zw.la"
], content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_0__.rm)("br", true, content);
return content;
});
/***/ }),
/***/ "./src/rules/biquge/template.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ FN: () => (/* binding */ mkBiqugeMultiIndexNextPage),
/* harmony export */ Tm: () => (/* binding */ baseOnePage),
/* harmony export */ Wt: () => (/* binding */ mkBiquge),
/* harmony export */ uk: () => (/* binding */ mkBiqugeNextPage)
/* harmony export */ });
/* unused harmony exports baseMultiIndex, mkBiqugeMultiIndex */
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _onePage_template__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _onePageWithMultiIndexPage_template__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/rules/onePageWithMultiIndexPage/template.ts");
function base(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook) {
return {
bookUrl: document.location.href,
bookname: document.querySelector("#info h1, .info h2, .info h1").innerText
.trim()
.replace(/最新章节$/, ""),
author: document.querySelector("#info > p:nth-child(2), #info > div:nth-child(2), .info .author, .small > span:nth-child(1), .info .fix > p:nth-child(1)").innerText
.replace(/作(\s+)?者[::]/, "")
.trim(),
introDom: document.querySelector("#intro, .intro, .book-intro, .desc"),
introDomPatch,
coverUrl: document.querySelector("#fmimg > img, .info > .cover > img, .book-boxs > .img > img, .imgbox > img")?.src ?? null,
postHook: (chapter) => {
if (chapter.sectionName) {
if (chapter.sectionName.includes("《")) {
chapter.sectionName = chapter.sectionName
.replace(`《${chapter.bookname}》`, "")
.trim();
}
else {
chapter.sectionName = chapter.sectionName
.replace(chapter.bookname, "")
.trim();
}
}
if (postHook) {
return postHook(chapter);
}
return chapter;
},
concurrencyLimit,
sleepTime,
maxSleepTime,
overrideConstructor: (classThis) => {
const rawBookParse = classThis.bookParse;
classThis.bookParse = async () => {
const book = (await Reflect.apply(rawBookParse, classThis, []));
const chapters = book.chapters;
book.chapters = (0,_lib_rule__WEBPACK_IMPORTED_MODULE_0__/* .deDuplicate */ .hR)(chapters);
return book;
};
if (overRide) {
overRide(classThis);
}
return classThis;
},
};
}
function baseOnePage(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook) {
return {
...base(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook),
aList: document.querySelectorAll("#list a, .listmain a, .book-item a"),
sections: document.querySelectorAll("#list dt, .listmain dt, .layout-tit"),
getSName: (sElem) => {
const b = sElem.querySelector("b");
if (b) {
return b.innerText;
}
return sElem.innerText;
},
};
}
function baseMultiIndex(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook) {
return {
...base(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook),
getIndexUrls: () => Array.from(document.querySelectorAll('select[name="pageselect"] > option')).map((o) => document.location.origin + o.getAttribute("value")),
getAList: (doc) => {
const sectionList = Array.from(doc.querySelectorAll("ul.section-list.fix, ul.list")).slice(-1)[0];
if (!sectionList) {
throw new Error("获取章节列表失败!");
}
return sectionList.querySelectorAll("li > a");
},
};
}
function mkBiquge(introDomPatch, contentPatch, chapterContentSelector, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook) {
let chapterContenSelector = "#content";
if (typeof chapterContentSelector == "string") {
chapterContenSelector = chapterContentSelector;
}
return (0,_onePage_template__WEBPACK_IMPORTED_MODULE_1__/* .mkRuleClass */ .N)({
...baseOnePage(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook),
getContent: (doc) => doc.querySelector(chapterContenSelector),
contentPatch,
});
}
function mkBiqugeNextPage(introDomPatch, contentPatch, getNextPage, continueCondition, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook, chapterContenSelector = "#content") {
return (0,_onePage_template__WEBPACK_IMPORTED_MODULE_1__/* .mkRuleClass */ .N)({
...baseOnePage(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook),
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const { contentRaw } = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_0__/* .nextPageParse */ .u1)({
chapterName,
chapterUrl,
charset,
selector: chapterContenSelector,
contentPatch,
getNextPage,
continueCondition,
enableCleanDOM: false,
});
return contentRaw;
},
contentPatch: (dom) => dom,
});
}
function mkBiqugeMultiIndexNextPage(introDomPatch, contentPatch, getNextPage, continueCondition, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook, chapterContenSelector = "#content") {
return (0,_onePageWithMultiIndexPage_template__WEBPACK_IMPORTED_MODULE_2__/* .mkRuleClass */ .N)({
...baseMultiIndex(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook),
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const { contentRaw } = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_0__/* .nextPageParse */ .u1)({
chapterName,
chapterUrl,
charset,
selector: chapterContenSelector,
contentPatch,
getNextPage,
continueCondition,
enableCleanDOM: false,
});
return contentRaw;
},
contentPatch: (dom) => dom,
});
}
function mkBiqugeMultiIndex(introDomPatch, contentPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook, chapterContenSelector = "#content") {
return mkRuleClassMultiIndex({
...baseMultiIndex(introDomPatch, concurrencyLimit, sleepTime, maxSleepTime, overRide, postHook),
getContent: (doc) => doc.querySelector(chapterContenSelector),
contentPatch,
});
}
/***/ }),
/***/ "./src/rules/mbtxt/mbtxt.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ mbtxt: () => (/* binding */ mbtxt)
/* harmony export */ });
/* harmony import */ var _onePage_template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
const mbtxt = () => (0,_onePage_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".booktitle").innerText.trim(),
author: document.querySelector("a.red").innerText.trim(),
introDom: document.querySelector(".bookintro"),
introDomPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".visible-xs", true, dom);
return dom;
},
coverUrl: document.querySelector(".bookcover > img")?.src,
aList: document.querySelectorAll("#list-chapterAll > dd > a"),
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const { contentRaw } = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_2__/* .nextPageParse */ .u1)({
chapterName,
chapterUrl,
charset,
selector: ".readcontent",
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".kongwen", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".readmiddle", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".text-danger.text-center", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)(["-->>"], content);
return content;
},
getNextPage: (doc) => doc.querySelector("#linkNext")?.href ?? "",
continueCondition: (content, nextLink) => {
if (nextLink === "") {
return false;
}
return nextLink.includes("_");
},
enableCleanDOM: false,
});
return contentRaw;
},
contentPatch: (dom) => dom,
});
/***/ }),
/***/ "./src/rules/mbtxt/quanshuzhai.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ quanshuzhai: () => (/* binding */ quanshuzhai)
/* harmony export */ });
/* harmony import */ var _onePage_template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const quanshuzhai = () => (0,_onePage_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".booktitle").innerText.trim(),
author: document.querySelector("a.red").innerText.trim(),
introDom: document.querySelector(".bookintro"),
introDomPatch: (dom) => dom,
coverUrl: null,
aList: document.querySelectorAll("#list-chapterAll > dd > a"),
getContent: (doc) => doc.querySelector(".readcontent"),
contentPatch: (dom) => dom,
});
/***/ }),
/***/ "./src/rules/onePage/256wxc.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ c256wxc: () => (/* binding */ c256wxc)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const c256wxc = (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".art_tit").innerText.trim(),
author: (document.querySelector("span.bookinfo:nth-child(1) > a") ??
document.querySelector("span.bookinfo:nth-child(1)")).innerText
.replace(/^作者:/, "")
.trim(),
introDom: document.querySelector(".infotype > p"),
introDomPatch: (introDom) => introDom,
coverUrl: null,
aList: document.querySelectorAll(".catalog > li > a"),
getContent: (doc) => doc.querySelector(".book_con"),
contentPatch: (content) => content,
});
/***/ }),
/***/ "./src/rules/onePage/60ksw.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ i60ksw: () => (/* binding */ i60ksw)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const i60ksw = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("div.booktitle > h1").innerText.trim(),
author: document.querySelector("#author").innerText.trim(),
introDom: document.querySelector("#bookintro"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector("#bookimg img").src,
aList: document.querySelectorAll("#chapterlist li > a"),
sections: undefined,
getSName: (dom) => dom.innerText.trim(),
getContent: (doc) => doc.querySelector("#content"),
contentPatch: (dom) => dom,
});
/***/ }),
/***/ "./src/rules/onePage/630shu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ c630shu: () => (/* binding */ c630shu)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const c630shu = (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("#info > h1").innerText.trim(),
author: document.querySelector("div.options > span.item:nth-child(1) > a").innerText.trim(),
introDom: document.querySelector("#intro"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector(".img_in > img").src,
aList: document.querySelectorAll(".zjlist > dd > a"),
getContent: (doc) => doc.querySelector("#content"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)([/恋上你看书网 WWW.630SHU.NET ,最快更新.+最新章节!/], content);
return content;
},
});
/***/ }),
/***/ "./src/rules/onePage/aixdzs.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ aixdzs: () => (/* binding */ aixdzs)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const aixdzs = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".d_info > h1").innerText.trim(),
author: document.querySelector(".d_ac > ul:nth-child(1) > li:nth-child(1) > a:nth-child(2)").innerText.trim(),
introDom: document.querySelector(".d_co"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector(".d_af > img").src,
aList: document.querySelectorAll("#i-chapter li.chapter > a"),
sections: document.querySelectorAll("#i-chapter li.volume"),
getSName: (dom) => dom.innerText.trim(),
getContent: (doc) => doc.querySelector(".content"),
contentPatch: (dom) => dom,
});
/***/ }),
/***/ "./src/rules/onePage/boqugew.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ boqugew: () => (/* binding */ boqugew)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const boqugew = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("h1.bookTitle").innerText.trim(),
author: document.querySelector("p.booktag > a:first-child").innerText.replace(/作(\s+)?者[::]/, "").trim(),
introDom: document.querySelector("p#bookIntro"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector("img.img-thumbnail").src,
aList: document.querySelectorAll("div#list-chapterAll > dl > dd > a"),
getContent: (doc) => doc.querySelector("div#htmlContent"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)([
"记住网址m.boqugew.com",
"一秒记住http://m.boqugew.com",
"首发网址http://m.boqugew.com"
], content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("br", true, content);
return content;
},
});
/***/ }),
/***/ "./src/rules/onePage/colorful-fantasybooks.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ fantasybooks: () => (/* binding */ fantasybooks)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const fantasybooks = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".works-intro-title > strong").innerText.trim(),
author: document.querySelector(".works-intro-digi > span:nth-child(1) > em:nth-child(1)").innerText.trim(),
introDom: document.querySelector(".works-intro-short"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector(".works-cover > img")
.src,
aList: document.querySelectorAll(".works-chapter-list .works-chapter-item > a"),
sections: document.querySelectorAll(".vloume"),
getSName: (sElem) => sElem.innerText.trim(),
getContent: (doc) => doc.querySelector("#content_cust"),
contentPatch: (content) => {
Array.from(content.children)
.filter((node) => node.nodeName === "SPAN" && node.childNodes.length > 15)
.map((span) => {
const div = document.createElement("div");
div.innerHTML = span.innerHTML;
Array.from(div.querySelectorAll("p"))
.filter((node) => node.childElementCount === 1 &&
node.children[0].nodeName === "BR")
.forEach((pbrp) => pbrp.remove());
span.replaceWith(div);
});
return content;
},
concurrencyLimit: 3,
nsfw: true,
});
/***/ }),
/***/ "./src/rules/onePage/czbooks.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ czbooks: () => (/* binding */ czbooks)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const czbooks = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("div.info > span.title").innerText.trim(),
author: document.querySelector("div.info > span.author").innerText.trim(),
introDom: document.querySelector("div.description"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector("div.novel-detail .thumbnail > img").src,
aList: document.querySelectorAll("#chapter-list li > a"),
sections: document.querySelectorAll("#chapter-list li.volume"),
getSName: (dom) => dom.innerText.trim(),
getContent: (doc) => doc.querySelector("div.content"),
contentPatch: (dom) => dom,
});
/***/ }),
/***/ "./src/rules/onePage/dizishu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ dizishu: () => (/* binding */ dizishu)
/* harmony export */ });
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
const dizishu = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".book-text > h1").innerText.trim(),
author: document.querySelector(".book-text > span").innerText
.replace("著", "")
.trim(),
introDom: document.querySelector(".intro"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector("#fengmian img")
?.src,
aList: document.querySelectorAll("#list > .book-chapter-list .cf li > a"),
sections: document.querySelectorAll("#list > .book-chapter-list > h3"),
getSName: (sElem) => sElem.innerText.trim(),
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
if (chapterUrl.includes("dizishu")) {
const script1 = Array.from(doc.querySelectorAll("script"))
.filter((s) => s.innerHTML.includes("chapterid="))?.[0]
?.innerHTML.split("\n")
.filter((line) => !(line.includes("cpstr=") ||
line.includes("get_content()") ||
line.includes("xid=")))
.join("\n");
const script2 = Array.from(doc.querySelectorAll("script"))
.filter((s) => s.innerHTML.includes("ssid"))?.[0]
?.innerHTML.split("\n")
.filter((line) => line.includes("var ssid") || line.includes("var hou"))
.join("\n");
const request = new Function(`${script2};${script1};
const xid=Math.floor(bookid/1000);
const url = \`${document.location.origin}/files/article/html\${ssid}/\${xid}/\${bookid}/\${chapterid}\${hou}\`;
return new Request(url, {
headers: {
accept: "text/plain, */*; q=0.01",
"x-requested-with": "XMLHttpRequest",
},
referrer: "${document.location.origin}",
method: "GET",
mode: "cors",
credentials: "include",
});`)();
const text = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getText */ .q4)(request, charset);
const cctxt = new Function(`${text};return cctxt;`)();
if (cctxt) {
const contentRaw = document.createElement("div");
contentRaw.innerHTML = cctxt;
return contentRaw;
}
else {
return null;
}
}
else {
const contentDom = doc.querySelector("div#txt");
if (contentDom) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("a", true, contentDom);
return contentDom;
}
else {
return null;
}
}
},
contentPatch: (content) => content,
overrideConstructor: (classThis) => {
const rawBookParse = classThis.bookParse;
classThis.bookParse = async () => {
const book = (await Reflect.apply(rawBookParse, classThis, []));
const chapters = book.chapters;
book.chapters = (0,_lib_rule__WEBPACK_IMPORTED_MODULE_3__/* .deDuplicate */ .hR)(chapters);
return book;
};
return classThis;
},
});
/***/ }),
/***/ "./src/rules/onePage/fuxiaoshu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ fuxiaoshu: () => (/* binding */ fuxiaoshu)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const fuxiaoshu = (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".con_box h1").innerText.trim(),
author: document.querySelector(".con_box .tits strong a").innerText
.trim(),
introDom: undefined,
coverUrl: null,
aList: Array.from(document.querySelectorAll(".alt_page li > a")).slice(2),
getContent: (doc) => doc.querySelector("div.co-bay"),
contentPatch: (content) => content,
});
/***/ }),
/***/ "./src/rules/onePage/guidaye.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ guidaye: () => (/* binding */ guidaye)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_0__);
const guidaye = async () => {
const getAList = async () => {
const num = +document.querySelector("div.pager > span:nth-child(1)").innerText
.replace(/页次:.+\//g, "")
.trim();
const sid = document.querySelector("div#bookiddata").dataset.sid ||
"";
const api = "https://b.guidaye.com/e/extend/bookpage/pages.php?id=" + sid;
const htm = document.createElement("div");
_log__WEBPACK_IMPORTED_MODULE_0___default().info("[guidaye]" + "作品编号: " + sid + ", 列表页数: " + num);
for (let i = 0; i < num; i++) {
_log__WEBPACK_IMPORTED_MODULE_0___default().info("获取列表:" + i);
const resp = await fetch(api, {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
},
body: "pageNum=" + i,
});
if (!resp.ok) {
_log__WEBPACK_IMPORTED_MODULE_0___default().error("获取列表错误:" + resp.status);
}
const result = (await resp.json());
result.list.forEach((list) => {
const ul = document.createElement("a");
ul.href = list.pic;
ul.innerText = list.title;
htm.appendChild(ul);
return;
});
}
_log__WEBPACK_IMPORTED_MODULE_0___default().info("[guidaye]列表生成完毕");
return htm.querySelectorAll("a");
};
return (0,_template__WEBPACK_IMPORTED_MODULE_1__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("div.book-describe > h1").innerText.trim(),
author: document.querySelector("div.book-describe > p").innerText
.trim()
.replace(/作者:|作品集/g, ""),
introDom: document.querySelector("div.describe-html"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector("div.book-img > img")
.src,
aList: await getAList(),
getContent: (doc) => doc.querySelector("div#nr1"),
contentPatch: (content) => {
return content;
},
});
};
/***/ }),
/***/ "./src/rules/onePage/hongxiuzhao.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
hongxiuzhao: () => (/* binding */ hongxiuzhao)
});
// EXTERNAL MODULE: ./src/rules/onePage/template.ts
var template = __webpack_require__("./src/rules/onePage/template.ts");
// EXTERNAL MODULE: ./src/lib/dom.ts
var lib_dom = __webpack_require__("./src/lib/dom.ts");
;// ./src/rules/lib/hongxiuzhao.ts
const table = {
"\ue2a9": "\u5634",
"\ue2ba": "\u4e0b",
"\ue2bb": "\u5934",
"\ue2d1": "\u4f53",
"\ue321": "\u515a",
"\ue2a5": "\u5165",
"\ue2b4": "\u7c97",
"\ue2c4": "\u63a8",
"\ue316": "\u6237",
"\ue310": "\u9017",
"\ue2a1": "\u5598",
"\ue2a8": "\u8ff7",
"\ue2cd": "\u94bb",
"\ue307": "\u542e",
"\ue30c": "\u7684",
"\ue315": "\u8482",
"\ue298": "\u9053",
"\ue2ca": "\u5e72",
"\ue2ad": "\u803b",
"\ue2ef": "\u817f",
"\ue294": "\u786c",
"\ue2c9": "\u4e73",
"\ue2c5": "\u7cbe",
"\ue2fc": "\u7f69",
"\ue317": "\u80a5",
"\ue309": "\u8131",
"\ue2e4": "\u6f0f",
"\ue320": "\u5171",
"\ue2ae": "\u88f8",
"\ue2b7": "\u6d41",
"\ue2b1": "\u8179",
"\ue313": "\u80c0",
"\ue2b0": "\u81c0",
"\ue2e0": "\u8272",
"\ue2d0": "\u9a9a",
"\ue312": "\u6d1e",
"\ue2c7": "\u54ac",
"\ue2de": "\u6839",
"\ue304": "\u5c3b",
"\ue2a7": "\u7fd8",
"\ue2f0": "\u7231",
"\ue2db": "\u830e",
"\ue2ed": "\u6c9f",
"\ue2a2": "\u7ffb",
"\ue29a": "\u6345",
"\ue2e7": "\u5c3f",
"\ue2d3": "\u638f",
"\ue2b8": "\u6deb",
"\ue2ea": "\u60c5",
"\ue2ce": "\u6f6e",
"\ue2c1": "\u9634",
"\ue2b3": "\u8089",
"\ue2d8": "\u88e4",
"\ue2bc": "\u63d2",
"\ue290": "\u64cd",
"\ue29d": "\u634f",
"\ue322": "\u4e60",
"\ue29c": "\u8eab",
"\ue2d6": "\u53c9",
"\ue30b": "\u53e3",
"\ue2e5": "\u75d2",
"\ue30d": "\u889c",
"\ue2a3": "\u63e1",
"\ue2ff": "\u8f6f",
"\ue2f3": "\u6db2",
"\ue306": "\u4ea4",
"\ue2d9": "\u62d4",
"\ue2dc": "\u4e30",
"\ue301": "\u67d4",
"\ue311": "\u8170",
"\ue303": "\u5439",
"\ue305": "\u7206",
"\ue2ec": "\u8bf1",
"\ue2e2": "\u9f9f",
"\ue2c2": "\u811a",
"\ue2f1": "\u575a",
"\ue2bd": "\u8214",
"\ue2e6": "\u9876",
"\ue30f": "\u5987",
"\ue2b9": "\u5507",
"\ue2bf": "\u5c44",
"\ue2c6": "\u5a9a",
"\ue30a": "\u9732",
"\ue2f7": "\u7a74",
"\ue2ab": "\u6478",
"\ue2c3": "\u5c04",
"\ue30e": "\u547b",
"\ue2ee": "\u543b",
"\ue299": "\u6bdb",
"\ue2f4": "\u5973",
"\ue2fb": "\u64a9",
"\ue2cc": "\u6b32",
"\ue2dd": "\u542b",
"\ue2be": "\u6e29",
"\ue295": "\u5978",
"\ue308": "\u6c34",
"\ue2af": "\u5f04",
"\ue2b2": "\u9e21",
"\ue2da": "\u5149",
"\ue2f8": "\u767d",
"\ue314": "\u554a",
"\ue2e9": "\u52c3",
"\ue2c8": "\u8210",
"\ue291": "\u5ae9",
"\ue29e": "\u82de",
"\ue2b5": "\u80a4",
"\ue2c0": "\u7ea4",
"\ue2f6": "\u5c4c",
"\ue2f9": "\u8dc3",
"\ue2e1": "\u80f8",
"\ue2f5": "\u5c3c",
"\ue2eb": "\u808f",
"\ue2cb": "\u629a",
"\ue2df": "\u6d6a",
"\ue300": "\u871c",
"\ue2d4": "\u6ee1",
"\ue2aa": "\u6252",
"\ue302": "\u6413",
"\ue292": "\u62b1",
"\ue2e8": "\u8361",
"\ue29f": "\u80a1",
"\ue293": "\u63c9",
"\ue2cf": "\u505a",
"\ue29b": "\u50ac",
"\ue2fd": "\u88d9",
"\ue2b6": "\u633a",
"\ue297": "\u5904",
"\ue2fa": "\u5976",
"\ue323": "\u4ea7",
"\ue2e3": "\u836f",
"\ue2d7": "\u6027",
"\ue2a0": "\u63f4",
"\ue2d2": "\u623f",
"\ue2d5": "\u9633",
"\ue2fe": "\u6ed1",
"\ue296": "\u5438",
"\ue2ac": "\u67de",
};
;// ./src/rules/onePage/hongxiuzhao.ts
const hongxiuzhao = () => (0,template/* mkRuleClass */.N)({
bookUrl: document.location.href,
bookname: document
.querySelector(".m-bookdetail div.f-fl > h1")
?.innerText.trim() ?? "",
author: document
.querySelector(".author > a:nth-child(1)")
?.innerText.trim() ?? "",
introDom: document.querySelector(".summery") ?? undefined,
introDomPatch: (dom) => {
(0,lib_dom.rm)("strong", false, dom);
(0,lib_dom.rm)("em", false, dom);
return dom;
},
coverUrl: document.querySelector(".cover > img")?.src,
additionalMetadatePatch: (additionalMetadate) => {
additionalMetadate.tags = Array.from(document.querySelectorAll(".tags > a")).map((a) => a.innerText.trim());
return additionalMetadate;
},
aList: document.querySelectorAll(".m-chapters li > a"),
getContent: (doc) => doc.querySelector(".article-content"),
contentPatch: (content) => {
(0,lib_dom.rm)("mark", true, content);
(0,lib_dom.rm)("h1", true, content);
(0,lib_dom.rm)("ins", true, content);
(0,lib_dom.rm)("script", true, content);
(0,lib_dom.rm)("p[style]", true, content);
(0,lib_dom.rm)('a[href="https://hongxiuzh.com"]', true, content);
for (const k in table) {
content.innerHTML = content.innerHTML.replaceAll(k, table[k]);
}
return content;
},
});
/***/ }),
/***/ "./src/rules/onePage/original/akatsuki.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ akatsuki: () => (/* binding */ akatsuki)
/* harmony export */ });
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const akatsuki = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.origin + document.location.pathname,
bookname: document.querySelector("#LookNovel").innerText.trim(),
author: document.querySelector(".box.story > h3.font-bb:nth-last-of-type(1) > a").innerText.trim(),
introDom: document.querySelector(".box.story.body-normal > .body-normal > div"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector("div.font-bb > center > img")
?.src ?? null,
aList: document.querySelectorAll("table.list td > a"),
sections: document.querySelectorAll("table.list td[colspan] > b"),
getSName: (sElem) => sElem.innerText.trim(),
getContent: (doc) => {
doc.querySelectorAll("center > img").forEach((img) => {
const parent = img.parentElement;
parent?.replaceWith(img);
});
const contentRaw = document.createElement("div");
const nodes = Array.from(doc.querySelectorAll(".body-novel, .body-novel + hr"));
if (nodes.length > 1) {
const previous = nodes[0].previousElementSibling;
if (previous?.nodeName.toLowerCase() === "div") {
nodes.unshift(previous);
}
}
for (const node of nodes) {
if (node instanceof HTMLDivElement && node.className === "body-novel") {
contentRaw.appendChild((0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_1__/* .convertBr */ .U9)(node, true));
}
else {
contentRaw.appendChild(node);
}
}
return contentRaw;
},
contentPatch: (content) => content,
concurrencyLimit: 2,
language: "ja",
});
/***/ }),
/***/ "./src/rules/onePage/original/alphapolis.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ alphapolis: () => (/* binding */ alphapolis)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const alphapolis = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("h1.title").innerText.trim(),
author: document.querySelector("div.author > span:nth-child(1) > a:nth-child(1)").innerText.trim(),
introDom: document.querySelector(".abstract"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector("div.cover > a > img")
?.src ?? null,
additionalMetadatePatch: (additionalMetadate) => {
additionalMetadate.tags = Array.from(document.querySelectorAll(".content-tags > .tag > a")).map((a) => a.innerText.trim());
return additionalMetadate;
},
aList: document.querySelectorAll(".episodes > .episode > a"),
getAName: (aElem) => aElem.querySelector(".title")?.innerText.trim(),
sections: document.querySelectorAll(".episodes > h3"),
getSName: (sElem) => sElem.innerText.trim(),
getContent: (doc) => doc.querySelector("#novelBody"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .insertBrBeforeText */ .Md)(content);
return content;
},
language: "ja",
});
/***/ }),
/***/ "./src/rules/onePage/original/houhuayuan.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ houhuayuan: () => (/* binding */ houhuayuan)
/* harmony export */ });
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const houhuayuan = () => {
const seriesbox = document.querySelector(".seriesbox");
let bookUrl;
let bookname;
let author = document.querySelector("h3.author")?.innerText
.replace(/♥|作者: /g, "")
.trim();
if (author === "") {
author = "佚名";
}
const aList = [];
if (seriesbox) {
const lis = seriesbox.querySelectorAll("ul.serieslist-ul > li");
for (const li of Array.from(lis)) {
if (li.className === "serieslist-li") {
const a = li.querySelector("a");
if (a) {
aList.push(a);
}
}
else if (li.className === "serieslist-li-current") {
const a = document.createElement("a");
a.innerText = document.querySelector(".entry-title").innerText.trim();
a.href = document.location.href;
aList.push(a);
}
}
const aFirst = aList[0];
bookname = aFirst.innerText
.replace(/第.+章$|\s序$/, "")
.trim();
bookUrl = aFirst.href;
}
else {
bookUrl = document.location.href;
bookname = document.querySelector(".entry-title").innerText.trim();
const a = document.createElement("a");
a.innerText = bookname;
a.href = bookUrl;
aList.push(a);
}
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl,
bookname,
author,
aList,
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
const pageLinks = doc.querySelectorAll(".page-links > a.post-page-numbers");
if (pageLinks) {
const content = document.createElement("div");
const _content0 = doc.querySelector("header + div.entry-content");
if (_content0) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .childNodesCopy */ .Fv)(_content0, content);
}
const pageUrls = Array.from(pageLinks).map((a) => a.href);
for (const url of pageUrls) {
const docc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(url, charset);
const _content1 = docc.querySelector("header + div.entry-content");
if (_content1) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .childNodesCopy */ .Fv)(_content1, content);
}
}
return content;
}
else {
return doc.querySelector("header + div.entry-content");
}
},
contentPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)('div[id^="stage-"]', true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)('div[id^="zhaoz-"]', true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("div.seriesbox", true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("fieldset", true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("div.wpulike", true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)(".simplefavorite-button", true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)(".page-links", true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .rm2 */ .Sf)([" – 蔷薇后花园", " – 黑沼泽俱乐部"], dom);
Array.from(dom.querySelectorAll("img")).forEach((img) => (img.src = img.getAttribute("data-src") ?? ""));
return dom;
},
nsfw: true,
});
};
/***/ }),
/***/ "./src/rules/onePage/original/kakuyomu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ kakuyomu: () => (/* binding */ kakuyomu)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
function clickButtonFromSpan(spanElements, targetText) {
spanElements.forEach(span => {
if (span.textContent?.includes(targetText)) {
const describedById = span.id;
if (describedById) {
const button = document.querySelector(`button[aria-describedby="${describedById}"]`);
button?.click();
}
}
});
}
function clickButtonFromDiv(divElements, targetText) {
divElements.forEach(div => {
if (div.textContent?.includes(targetText)) {
let parent = div;
while (parent && parent.nodeName !== 'BUTTON') {
parent = parent.parentElement;
}
parent?.click();
}
});
}
function clickButtonWithSVGAndH3(buttons) {
buttons.forEach(button => {
const svg = button.querySelector('svg[class^="Icons_icon"]');
const h3 = button.querySelector('h3');
if (svg && h3) {
const hasFlipClass = Array.from(svg.classList).some(className => className.startsWith('Icons_flip'));
if (!hasFlipClass) {
button.click();
}
}
});
}
const spanElements = document.querySelectorAll('span');
const divElements = document.querySelectorAll('div');
const buttons = document.querySelectorAll('button[class^="Button_button"]');
clickButtonFromSpan(spanElements, "…続きを読む");
clickButtonFromDiv(divElements, "つづきを表示");
clickButtonWithSVGAndH3(buttons);
const kakuyomu = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("h1").innerText.trim(),
author: document.querySelector("div[class*=partialGiftWidgetActivityName] > a").innerText.trim(),
introDom: document.querySelector("div[class*=CollapseTextWithKakuyomuLinks]"),
introDomPatch: (dom) => dom,
coverUrl: null,
additionalMetadatePatch: (additionalMetadate) => {
additionalMetadate.tags = Array.from(document.querySelectorAll("#workMeta-tags > li > a")).map((a) => a.innerText);
return additionalMetadate;
},
aList: document.querySelectorAll("a[class*=WorkTocSection_link]"),
getAName: (aElem) => aElem.querySelector('div[class*="Typography"]').innerText.trim(),
sections: document.querySelectorAll("h3"),
getSName: (dom) => dom.innerText.trim(),
getContent: (dom) => dom.querySelector(".widget-episodeBody"),
contentPatch: (dom) => dom,
language: "ja",
});
/***/ }),
/***/ "./src/rules/onePage/original/masiro.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ masiro: () => (/* binding */ masiro)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const masiro = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".novel-title").innerText.trim(),
author: document.querySelector(".author > a").innerText.trim(),
introDom: document.querySelector(".brief"),
introDomPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)(["简介:"], dom);
return dom;
},
coverUrl: document.querySelector("div.mailbox-attachment-icon > a > img.img").src,
additionalMetadatePatch: (additionalMetadate) => {
additionalMetadate.tags = Array.from(document.querySelectorAll("div.n-detail > div.tags a")).map((a) => a.innerText);
return additionalMetadate;
},
aList: document.querySelectorAll(".chapter-ul ul.episode-ul > a"),
getAName: (aElem) => aElem.querySelector('span[style^="overflow: hidden;"]').innerText.trim(),
getIsVIP: (aElem) => {
let isVIP = false;
let isPaid = false;
const small = aElem.querySelector("small");
if (small) {
const text = small.innerText.trim();
if (text !== "") {
isVIP = true;
if (text === "已购") {
isPaid = true;
}
}
}
return { isVIP, isPaid };
},
sections: document.querySelectorAll("li.chapter-box > span + b"),
getSName: (dom) => dom.innerText.trim(),
getContent: (dom) => dom.querySelector("div.box-body.nvl-content"),
contentPatch: (dom) => dom,
concurrencyLimit: 1,
sleepTime: 100,
maxSleepTime: 3000,
needLogin: true,
});
/***/ }),
/***/ "./src/rules/onePage/original/penana.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ penana: () => (/* binding */ penana)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const penana = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".booktitlewrap").innerText.trim(),
author: document.querySelector("div.fontbold").innerText.trim(),
introDom: document.querySelector("div.readtext"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector("img.bookcover")
?.src ?? null,
additionalMetadatePatch: (additionalMetadate) => {
additionalMetadate.tags = Array.from(document.querySelectorAll(".tags_wrap .story_tag a")).map((a) => a.innerText.trim());
return additionalMetadate;
},
aList: document.querySelectorAll("div#toclist a"),
getAName: (aElem) => aElem.querySelector("div.toc1")?.innerText.trim(),
sections: undefined,
getSName: undefined,
getContent: (doc) => doc.querySelector("article"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("span", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)('p[style="display:none"]', true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".displaynone", true, content);
return content;
},
language: "zh",
});
/***/ }),
/***/ "./src/rules/onePage/original/ptwxz.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ ptwxz: () => (/* binding */ ptwxz)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const ptwxz = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("h1")?.innerText.trim().replace('最新章节', '') ?? "",
author: document.querySelector('.list')?.textContent?.split(' \u00A0')[0]?.replace('作者:', '')?.trim() ?? "",
introDom: document.querySelector("#intro") ?? undefined,
introDomPatch: (dom) => dom,
coverUrl: document.location.href.replace(/(https:\/\/www\.piaotia\.com)\/html\/(\d+)\/(\d+)(\/index.html)?\/?$/, '$1/files/article/image/$2/$3/$3s.jpg'),
getAName: (aElem) => aElem.innerText.trim(),
aList: document.querySelectorAll('ul > li > a'),
getContent: (dom) => {
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
delay(1000);
return dom.body;
},
concurrencyLimit: 1,
sleepTime: 400,
maxSleepTime: 400,
contentPatch: (dom) => {
const title = dom.querySelector('h1')?.textContent?.trim() ?? '';
const table = dom.querySelector('table');
const bottomLink = dom.querySelector("div.bottomlink");
if (!table || !bottomLink) {
throw new Error('The required elements are not found in the DOM.');
}
let content = '';
let currentNode = table.nextSibling;
while (currentNode && currentNode !== bottomLink) {
if (currentNode.nodeType === Node.TEXT_NODE || (currentNode.nodeType === Node.ELEMENT_NODE && currentNode.nodeName.toLowerCase() !== 'table' && currentNode.nodeName.toLowerCase() !== 'div')) {
let textContent = currentNode.textContent || '';
if (currentNode.nodeType === Node.ELEMENT_NODE && currentNode.nodeName.toLowerCase() === 'br') {
textContent = '\n';
}
textContent.split('\n').forEach((line) => {
const trimmedLine = line.trim();
if (trimmedLine && title !== trimmedLine) {
content += `<p>${trimmedLine}</p>`;
}
});
}
currentNode = currentNode.nextSibling;
}
const divElement = document.createElement('div');
divElement.innerHTML = content;
return divElement;
}
});
/***/ }),
/***/ "./src/rules/onePage/original/syosetu.ts":
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.a(module, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ syosetu: () => (/* binding */ syosetu),
/* harmony export */ syosetuOrg: () => (/* binding */ syosetuOrg)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const currentPageIndexBox = document.querySelector('.p-eplist');
const firstPageAnchor = document.querySelector('.c-pager__item--first');
const lastPageAnchor = document.querySelector('.c-pager__item--last');
if (firstPageAnchor && lastPageAnchor) {
const currentURL = window.location.pathname + window.location.search;
const lastPageHref = lastPageAnchor.getAttribute('href') ? lastPageAnchor.getAttribute('href') : currentURL;
const firstPageHref = firstPageAnchor.getAttribute('href') ? firstPageAnchor.getAttribute('href') : currentURL;
const hrefLastPageMatch = lastPageHref ? lastPageHref.match(/(.*\/\?p=)(\d+)/) : null;
const hrefFirstPageMatch = firstPageHref ? firstPageHref.match(/(.*\/\?p=)(\d+)/) : null;
const baseUrl = hrefLastPageMatch ? hrefLastPageMatch[1] : hrefFirstPageMatch ? hrefFirstPageMatch[1] : '';
const lastPageNumber = hrefLastPageMatch ? parseInt(hrefLastPageMatch[2], 10) : 1;
const currentPageNumberMatch = currentURL.match(/(.*\/\?p=)(\d+)/);
const currentPageNumber = currentPageNumberMatch ? parseInt(currentPageNumberMatch[2], 10) : 1;
const fetchAndAppendContent = async (pageNumber, insertAfterCurrentBox) => {
try {
const response = await fetch(`${baseUrl}${pageNumber}`);
const html = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const pageIndexBox = doc.querySelector('.p-eplist');
if (pageIndexBox && currentPageIndexBox) {
const childrenArray = Array.from(pageIndexBox.children);
if (insertAfterCurrentBox) {
childrenArray.forEach(child => {
currentPageIndexBox.appendChild(child.cloneNode(true));
});
}
else {
childrenArray.reverse().forEach(child => {
currentPageIndexBox.insertBefore(child.cloneNode(true), currentPageIndexBox.firstChild);
});
}
}
}
catch (error) {
console.error('Error fetching page:', error);
}
};
for (let i = currentPageNumber - 1; i > 0; i--) {
await fetchAndAppendContent(i, false);
}
const endPageNumber = lastPageNumber === -1 ? currentPageNumber : lastPageNumber;
for (let i = currentPageNumber + 1; i <= endPageNumber; i++) {
await fetchAndAppendContent(i, true);
}
}
const syosetu = () => {
const getIntroDom = () => {
const a = document.querySelector("#novel_ex > .more");
if (a) {
a.click();
}
return document.querySelector("#novel_ex");
};
const getAList = () => {
const _aList = document.querySelectorAll("body > div.l-container > main > article > div.p-eplist > div > a");
if (_aList.length !== 0) {
return _aList;
}
else {
const a = document.createElement("a");
a.href = document.location.href;
a.innerText = document.querySelector(".p-novel__title")?.innerText;
return [a];
}
};
const getNsfw = () => {
const host = document.location.host;
return host === "novel18.syosetu.com";
};
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".p-novel__title").innerText.trim(),
author: document.querySelector("div.p-novel__author").innerText,
introDom: getIntroDom(),
introDomPatch: (dom) => dom,
coverUrl: null,
aList: getAList(),
sections: document.querySelectorAll(".p-eplist__chapter-title"),
getSName: (dom) => dom.innerText.trim(),
getContent: (dom) => {
const content = document.createElement("div");
const novelP = dom.querySelector(".p-novel__text--preface");
const novelHonbun = dom.querySelector(".p-novel__text:not(.p-novel__text--preface):not(.p-novel__text--afterword)");
const novelA = dom.querySelector(".p-novel__text--afterword");
if (novelP) {
content.appendChild(novelP);
const hr = dom.createElement("hr");
content.appendChild(hr);
}
if (novelHonbun) {
content.appendChild(novelHonbun);
}
if (novelA) {
const hr = dom.createElement("hr");
content.appendChild(hr);
content.appendChild(novelA);
}
return content;
},
contentPatch: (dom) => dom,
nsfw: getNsfw(),
needLogin: getNsfw(),
language: "ja",
});
};
const syosetuOrg = () => {
const getAList = () => {
const _aList = document.querySelectorAll('tr[class^="bgcolor"] > td > a');
if (_aList.length !== 0) {
return _aList;
}
else {
const a = document.createElement("a");
a.href = document.location.href;
a.innerText = document.querySelector("div.ss:nth-child(1) > p:nth-child(1) > span:nth-child(1) > a:nth-child(1)")?.innerText;
return [a];
}
};
const aList = getAList();
const getIntroDom = () => {
if (aList.length === 1 &&
aList[0].href === document.location.href) {
return undefined;
}
return document.querySelector("div.ss:nth-child(2)");
};
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector('div.ss > span[itemprop="name"], div.ss:nth-child(1) > p:nth-child(1) > span:nth-child(1) > a:nth-child(1)').innerText.trim(),
author: document.querySelector('div.ss span[itemprop="author"] > a, div.ss:nth-child(1) > p:nth-child(1) > a:nth-child(2)')?.innerText.trim(),
introDom: getIntroDom(),
introDomPatch: (dom) => dom,
coverUrl: null,
additionalMetadatePatch: (additionalMetadate) => {
additionalMetadate.tags = Array.from(document.querySelectorAll('span[itemprop="keywords"] > a, a.alert_color')).map((a) => a.innerText);
return additionalMetadate;
},
aList,
sections: document.querySelectorAll('div.ss > table > tbody > tr > td[colspan="2"] > strong'),
getSName: (dom) => dom.innerText.trim(),
getContent: (doc) => {
if (aList.length === 1 &&
aList[0].href === document.location.href) {
return doc.querySelector("div#maind > div.ss:nth-child(2)");
}
return doc.querySelector("div#maind > div.ss:nth-child(1)");
},
contentPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("p:nth-child(1)", false, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("div.novelnavi", true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)('div[style*="text-align:right;"]', true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("div#maegaki_open", true, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("div#atogaki_open", true, dom);
dom.querySelectorAll('a[name="img"]').forEach((a) => {
const img = document.createElement("img");
img.src = a.href;
img.alt = a.innerText;
a.replaceWith(img);
});
return dom;
},
language: "ja",
});
};
__webpack_async_result__();
} catch(e) { __webpack_async_result__(e); } }, 1);
/***/ }),
/***/ "./src/rules/onePage/qbtrcc.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ qbtrcc: () => (/* binding */ qbtrcc)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const qbtrcc = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("div.infos > h1").innerText.trim(),
author: document.querySelector("div.infos > div.date > span").innerText.replace("作者:", "").trim(),
introDom: document.querySelector("div.infos > p"),
introDomPatch: (introDom) => introDom,
coverUrl: "https://www.qbtr.cc/skin/default/images/bbb2.png",
aList: document.querySelectorAll("ul.clearfix > li > a"),
getContent: (doc) => doc.querySelector("div.read_chapterDetail"),
contentPatch: (content) => content,
});
/***/ }),
/***/ "./src/rules/onePage/qzxsw.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ qzxsw: () => (/* binding */ qzxsw)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const qzxsw = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("div.introduce > h1").innerText.trim(),
author: document.querySelector("div.introduce > p.bq > span:nth-child(2) > a").innerText.trim(),
introDom: document.querySelector("div.introduce > p.jj"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector("div.pic > img").src,
aList: document.querySelectorAll("div.ml_list > ul > li > a"),
getContent: (doc) => doc.querySelector(".articlecontent"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)([
"一秒记住m.quanzhifashi。com",
"m.quanzhifashi.com",
"http://m.quanzhifashi.com首发"
], content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("br", true, content);
return content;
},
});
/***/ }),
/***/ "./src/rules/onePage/soxscc.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ soxscc: () => (/* binding */ soxscc)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
const soxscc = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".xiaoshuo > h1").innerText.trim(),
author: document.querySelector(".xiaoshuo > h6:nth-child(3) > a").innerText.trim(),
introDom: document.querySelector("#intro"),
introDomPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("span.tags", false, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("q", true, dom);
return dom;
},
coverUrl: document.querySelector(".book_cover > img")
.src,
aList: document.querySelectorAll("div.novel_list[id] dd > a"),
sections: document.querySelectorAll("div.novel_list[id] dl > dt:nth-child(1) > b:nth-child(1)"),
getSName: (sElem) => sElem.innerText.trim(),
getContent: (doc) => doc.querySelector("div.content[id]"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rm2 */ .Sf)([
"最新章节地址:",
"全文阅读地址:",
"txt下载地址:",
"手机阅读:",
'为了方便下次阅读,你可以点击下方的"收藏"记录本次',
"请向你的朋友(QQ、博客、微信等方式)推荐本书",
"您可以在百度里搜索",
], content);
return content;
},
});
/***/ }),
/***/ "./src/rules/onePage/template.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ N: () => (/* binding */ mkRuleClass)
/* harmony export */ });
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/main.ts");
function mkRuleClass({ bookUrl, bookname, author, introDom, introDomPatch, coverUrl, additionalMetadatePatch, aList, getAName, getIsVIP, sections, getSName, postHook, getContentFromUrl, getContent, contentPatch, concurrencyLimit, sleepTime, maxSleepTime, needLogin, nsfw, cleanDomOptions, overrideConstructor, language, }) {
return class extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
if (concurrencyLimit) {
this.concurrencyLimit = concurrencyLimit;
}
if (sleepTime) {
this.sleepTime = sleepTime;
}
if (maxSleepTime) {
this.maxSleepTime = maxSleepTime;
}
if (needLogin) {
this.needLogin = needLogin;
}
if (nsfw) {
this.nsfw = nsfw;
}
if (overrideConstructor) {
overrideConstructor(this);
}
}
async bookParse() {
let introduction = null;
let introductionHTML = null;
if (introDom && introDomPatch) {
[introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .introDomHandle */ .HV)(introDom, introDomPatch);
}
const additionalMetadate = {
language: language ?? "zh",
};
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_2__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_3___default().error(error));
}
if (additionalMetadatePatch) {
Object.assign(additionalMetadate, additionalMetadatePatch(additionalMetadate));
}
const chapters = [];
let chapterNumber = 0;
let sectionNumber = 0;
let sectionChapterNumber = 0;
let sectionName = null;
let hasSection = false;
if (sections &&
sections instanceof NodeList &&
typeof getSName === "function") {
hasSection = true;
}
for (const aElem of Array.from(aList)) {
let chapterName;
if (getAName) {
chapterName = getAName(aElem);
}
else {
chapterName = aElem.innerText.trim();
}
const chapterUrl = aElem.href;
if (hasSection && sections && getSName) {
const _sectionName = (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .getSectionName */ .lq)(aElem, sections, getSName);
if (_sectionName !== sectionName) {
sectionName = _sectionName;
sectionNumber++;
sectionChapterNumber = 0;
}
}
chapterNumber++;
sectionChapterNumber++;
let isVIP = false;
let isPaid = false;
if (getIsVIP) {
({ isVIP, isPaid } = getIsVIP(aElem));
}
let chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_4__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber: hasSection ? sectionNumber : null,
sectionChapterNumber: hasSection ? sectionChapterNumber : null,
chapterParse: this.chapterParse,
charset: this.charset,
options: { bookname },
});
if (isVIP && !isPaid) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_5__/* .Status */ .nW.aborted;
}
if (typeof postHook === "function") {
chapter = postHook(chapter);
}
if (chapter) {
chapters.push(chapter);
}
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_6__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
let content;
if (typeof getContentFromUrl === "function") {
content = await getContentFromUrl(chapterUrl, chapterName, charset);
}
else if (typeof getContent === "function") {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_7__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
content = getContent(doc);
}
else {
throw Error("未发现 getContentFromUrl 或 getContent");
}
if (content) {
content = contentPatch(content);
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_8__/* .cleanDOM */ .an)(content, "TM", cleanDomOptions);
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
};
}
/***/ }),
/***/ "./src/rules/onePage/tianyabooks.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ tianyabooks: () => (/* binding */ tianyabooks)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const tianyabooks = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".book > h1")?.innerText
.replace(/[《》]/g, "")
.trim(),
author: document.querySelector(".book > h2 > a").innerText.trim(),
introDom: document.querySelector(".description"),
introDomPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("h3", false, dom);
return dom;
},
coverUrl: null,
aList: document.querySelectorAll(".book > dl > dd > a"),
sections: document.querySelectorAll(".book > dl > dt"),
getSName: (dom) => dom.innerText.trim(),
getContent: (doc) => doc.querySelector("#main"),
contentPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("div.crumb", false, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("h1", false, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)('p[align="center"]', false, dom);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("table", true, dom);
return dom;
},
});
/***/ }),
/***/ "./src/rules/onePage/trxs.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ trxs: () => (/* binding */ trxs)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const trxs = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".infos > h1").innerText
.split("(")[0]
.trim(),
author: document.querySelector(".date > span > a, .date > span").innerText
.replace("作者:", "")
.trim(),
introDom: document.querySelector(".infos > p"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector(".pic > img").src,
aList: document.querySelectorAll("div.book_list > ul.clearfix > li > a"),
getContent: (doc) => doc.querySelector(".read_chapterDetail"),
contentPatch: (content) => content,
});
/***/ }),
/***/ "./src/rules/onePage/uaa.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ uaa: () => (/* binding */ uaa)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
const uaa = () => {
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".info_box h1").innerText.trim(),
author: document.querySelector(".info_box div a").innerText.trim(),
introDom: document.querySelector("div.brief"),
introDomPatch: (dom) => {
return dom;
},
coverUrl: document.querySelector("img.cover")
.src,
additionalMetadatePatch: (additionalMetadate) => {
additionalMetadate.tags = Array.from(document.querySelectorAll(".tag_box li")).map((e) => e.innerText);
return additionalMetadate;
},
aList: document.querySelectorAll("ul.catalog_ul a"),
sections: undefined,
getSName: undefined,
getContent: (doc) => doc.querySelector("div.article"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".dizhi", true, content);
return content;
},
});
};
/***/ }),
/***/ "./src/rules/onePage/uukanshu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ uukanshu: () => (/* binding */ uukanshu)
/* harmony export */ });
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
const uukanshu = () => {
const button = document.querySelector('span[onclick="javascript:reverse(this);"]');
const reverse = unsafeWindow.reverse;
if (button.innerText === "顺序排列") {
reverse(button);
}
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("dd.jieshao_content > h1 > a").innerText
.replace("最新章节", "")
.trim(),
author: document.querySelector("dd.jieshao_content > h2 > a").innerText.trim(),
introDom: document.querySelector("dd.jieshao_content > h3"),
introDomPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)([
/^.+简介:\s+www\.uukanshu\.com\s+/,
/\s+https:\/\/www\.uukanshu\.com/,
/-+/,
], dom);
return dom;
},
coverUrl: document.querySelector("a.bookImg > img")
.src,
aList: document.querySelectorAll("#chapterList > li > a"),
sections: document.querySelectorAll("#chapterList > li.volume"),
getSName: (sElem) => sElem.innerText.trim(),
getContent: (doc) => doc.querySelector("#contentbox"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)(".ad_content", true, content);
const adReplace = [
/[UuUu]+看书\s*[ww]+.[UuUu]+[kk][aa][nn][ss][hh][UuUu].[nn][ee][tt]/g,
/[UuUu]+看书\s*[ww]+.[UuUu]+[kk][aa][nn][ss][hh][UuUu].[cCc][oOo][mMm]/g,
/[UU]*看书[(\\(].*?[)\\)]文字首发。/,
/请记住本书首发域名:。?/g,
/笔趣阁手机版阅读网址:/g,
/小说网手机版阅读网址:/g,
/https:\/\//g,
/http:\/\//g,
/UU看书\s+欢迎广大书友光临阅读,最新、最快、最火的连载作品尽在UU看书!UU看书。;?/g,
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .rms */ .j3)(adReplace, content);
return content;
},
});
};
/***/ }),
/***/ "./src/rules/onePage/wanben.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ wanben: () => (/* binding */ wanben)
/* harmony export */ });
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const wanben = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".detailTitle > h1").innerText.trim(),
author: document.querySelector(".writer > a").innerText.trim(),
introDom: document.querySelector(".detailTopMid > table:nth-child(3) > tbody:nth-child(1) > tr:nth-child(3) > td:nth-child(2)"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector(".detailTopLeft > img")?.src,
aList: document.querySelectorAll(".chapter li > a"),
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const { contentRaw } = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .nextPageParse */ .u1)({
chapterName,
chapterUrl,
charset,
selector: "div.readerCon",
contentPatch: (content, doc) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("script", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("div[style]", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("a", true, content);
const ads = [
"【提示】:如果觉得此文不错,请推荐给更多小伙伴吧!分享也是一种享受。",
"【看书助手】",
"百万热门书籍终身无广告免费阅读",
"【完本神站】",
"一秒记住、永不丢失!"
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .rm2 */ .Sf)(ads, content);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_3__/* .htmlTrim */ .is)(content);
return content;
},
getNextPage: (doc) => doc.querySelector(".readPage > a:nth-child(3)")
.href,
continueCondition: (_content, nextLink) => {
const pathname = nextLink.split("/").slice(-1)[0];
return pathname.includes("_");
},
enableCleanDOM: false,
});
return contentRaw;
},
contentPatch: (content) => content,
});
/***/ }),
/***/ "./src/rules/onePage/westnovel.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ westnovel: () => (/* binding */ westnovel)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const westnovel = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".btitle > h1 > a").innerText.trim(),
author: document.querySelector(".btitle > em:nth-child(2)").innerText
.replace("作者:", "")
.trim(),
introDom: document.querySelector(".intro-p > p:nth-child(1)"),
introDomPatch: (introDom) => introDom,
coverUrl: document.querySelector(".img-img")?.src,
aList: document.querySelectorAll(".chapterlist > dd > a"),
getContent: (doc) => doc.querySelector("#BookText"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("div.ads", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("div.link", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("h4", true, content);
return content;
},
});
/***/ }),
/***/ "./src/rules/onePage/xbyuan.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ xbyuan: () => (/* binding */ xbyuan)
/* harmony export */ });
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePage/template.ts");
const $ = (selector) => document.querySelector(selector);
const $$ = (selector) => document.querySelectorAll(selector);
const xbyuan = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: location.href,
bookname: $("#info h1").innerText.trim(),
author: $("#info .small > span").innerText.trim(),
introDom: $("#intro > p"),
introDomPatch: (_) => _,
coverUrl: $("#fmimg img").src,
aList: $$("#list dl")[1].querySelectorAll("a"),
async getContentFromUrl(chapterUrl, chapterName, charset) {
const { contentRaw } = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .nextPageParse */ .u1)({
chapterName,
chapterUrl,
charset,
selector: "#nr_content > p",
contentPatch(content, doc) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)("a", true, content);
const ads = [
"精华书阁",
"最新章节!",
"最快更新,为了您下次还能查看到本书的最快更新,请务必保存好书签!",
"https://www.xbyuan.com",
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .rm2 */ .Sf)(ads, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .rms */ .j3)(["(本章未完,请点击下一页继续阅读)"], content);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_3__/* .htmlTrim */ .is)(content);
return content;
},
getNextPage(doc) {
return doc.querySelector("#nexturl").href;
},
continueCondition(content, nextLink) {
const pathname = nextLink.split("/").slice(-1)[0];
return pathname.includes("_");
},
});
return contentRaw;
},
contentPatch: (content) => {
content.innerHTML = content.innerHTML
.replaceAll("「", "“")
.replaceAll("」", "”");
return content;
},
});
/***/ }),
/***/ "./src/rules/onePageWithMultiIndexPage/69shu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ c69shu: () => (/* binding */ c69shu)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePageWithMultiIndexPage/template.ts");
const c69shu = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("h1")?.innerText ?? "",
author: document.querySelector(".booknav2 > p:nth-child(3) > a")?.innerText ?? "",
introDom: document.querySelector(".content"),
introDomPatch: (content) => content,
coverUrl: document.querySelector(".bookimg2 > img")?.src ?? null,
getIndexPages: async () => {
const indexPages = [];
const menuUrl = document.querySelector('a.btn.more-btn[href^="https://69shuba.cx/book/"]').href;
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(menuUrl, "GBK");
indexPages.push(doc);
return indexPages;
},
getAList: (doc) => Array.from(doc.querySelectorAll("#catalog ul a")).reverse(),
getAName: (aElem) => aElem.innerText.trim(),
getContent: (doc) => doc.querySelector(".txtnav"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)(".hide720, .txtright, .bottom-ad", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .rm2 */ .Sf)([/^谷[\u4e00-\u9fa5]{0,1}$/gm], content);
const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, null);
const nodesToReplace = [];
while (walker.nextNode()) {
const node = walker.currentNode;
if (node.parentNode &&
node.parentNode.nodeName !== 'P' &&
node.textContent &&
node.textContent.trim() !== '') {
nodesToReplace.push(node);
}
}
nodesToReplace.forEach((node) => {
const p = document.createElement('p');
p.textContent = node.textContent;
if (node.parentNode) {
node.parentNode.replaceChild(p, node);
}
});
const paragraphs = content.querySelectorAll('p');
const brRegex = /<br\s*\/?>/i;
paragraphs.forEach((p) => {
if (brRegex.test(p.innerHTML)) {
const parts = p.innerHTML.split(brRegex);
const fragment = document.createDocumentFragment();
parts.forEach((part) => {
const newP = document.createElement('p');
newP.innerHTML = part.trim();
if (newP.innerHTML !== '') {
fragment.appendChild(newP);
}
});
if (p.parentNode) {
p.parentNode.replaceChild(fragment, p);
}
}
});
return content;
},
language: "zh",
concurrencyLimit: 1,
});
/***/ }),
/***/ "./src/rules/onePageWithMultiIndexPage/69yuedu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ c69yuedu: () => (/* binding */ c69yuedu)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePageWithMultiIndexPage/template.ts");
const c69yuedu = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("h1")?.innerText ?? "",
author: document.querySelector(".booknav2 > p:nth-child(2) > a")?.innerText ?? "",
introDom: document.querySelector(".navtxt"),
introDomPatch: (content) => content,
coverUrl: document.querySelector(".bookimg2 > img")?.src ?? null,
getIndexPages: async () => {
const indexPages = [];
const menuUrl = document.querySelector('.addbtn a.btn[href^="/chapters/"]').href;
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(menuUrl, "GBK");
indexPages.push(doc);
return indexPages;
},
getAList: (doc) => Array.from(doc.querySelectorAll("#chapters ul a")),
getAName: (aElem) => aElem.innerText.trim(),
getContent: (doc) => doc.querySelector(".content"),
contentPatch: (content) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__.rm)(".txtright, .bottom-ad", true, content);
const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, null);
const nodesToReplace = [];
while (walker.nextNode()) {
const node = walker.currentNode;
if (node.parentNode &&
node.parentNode.nodeName !== 'P' &&
node.textContent &&
node.textContent.trim() !== '') {
nodesToReplace.push(node);
}
}
nodesToReplace.forEach((node) => {
const p = document.createElement('p');
p.textContent = node.textContent;
if (node.parentNode) {
node.parentNode.replaceChild(p, node);
}
});
const paragraphs = content.querySelectorAll('p');
const brRegex = /<br\s*\/?>/i;
paragraphs.forEach((p) => {
if (brRegex.test(p.innerHTML)) {
const parts = p.innerHTML.split(brRegex);
const fragment = document.createDocumentFragment();
parts.forEach((part) => {
const newP = document.createElement('p');
newP.innerHTML = part.trim();
if (newP.innerHTML !== '') {
fragment.appendChild(newP);
}
});
if (p.parentNode) {
p.parentNode.replaceChild(fragment, p);
}
}
});
return content;
},
language: "zh",
concurrencyLimit: 1,
sleepTime: 500,
maxSleepTime: 1500
});
/***/ }),
/***/ "./src/rules/onePageWithMultiIndexPage/baihexs.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ baihexs: () => (/* binding */ baihexs)
/* harmony export */ });
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePageWithMultiIndexPage/template.ts");
const baihexs = () => {
const bookUrl = document.location.href;
const bookId = /(\d+)\/?$/.exec(document.location.href)?.[1];
if (!bookId) {
throw Error("获取书籍信息出错!");
}
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl,
bookname: document.querySelector(".block_txt2 > h2 > a").innerText.trim(),
author: document.querySelector(".block_txt2 > p:nth-child(4)").innerText
.replace("作者:", "")
.trim(),
introDom: document.querySelector(".intro_info"),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector(".block_img2 > img")
?.src,
getIndexUrls: async () => {
const contentPageUrl = `${document.location.origin}/wapbook-${bookId}`;
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(contentPageUrl + "/", document.characterSet);
const a = doc.querySelector("div.page > a:nth-last-child(1)");
const maxNumber = /(\d+)\/?$/.exec(a.href)?.[1];
if (!maxNumber) {
throw Error("获取章节列表时出错!");
}
const indexUrls = [];
for (let i = 1; i <= parseInt(maxNumber, 10); i++) {
const url = contentPageUrl + `_${i}/`;
indexUrls.push(url);
}
return indexUrls;
},
getAList: (doc) => doc.querySelectorAll(".chapter > li > a"),
getContent: (doc) => doc.querySelector("#nr1"),
contentPatch: (dom) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_2__/* .rm2 */ .Sf)(["请您牢记:百合小说网"], dom);
return dom;
},
concurrencyLimit: 3,
});
};
/***/ }),
/***/ "./src/rules/onePageWithMultiIndexPage/original/novelup.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ novelup: () => (/* binding */ novelup)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePageWithMultiIndexPage/template.ts");
const novelup = () => {
const bookUrl = document.location.origin + document.location.pathname;
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl,
bookname: document.querySelector("#section_episode_info_table > div:nth-child(2) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)").innerText.trim(),
author: document.querySelector("#section_episode_info_table > div:nth-child(2) > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2) > a:nth-child(1)").innerText.trim(),
introDom: document.querySelector(".novel_synopsis"),
introDomPatch: (dom) => {
Array.from(dom.querySelectorAll("p")).forEach((p) => {
const div = document.createElement("div");
div.innerHTML = p.innerHTML.split("\n").join("<br>");
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .insertBrBeforeText */ .Md)(div);
p.replaceWith(div);
});
return dom;
},
coverUrl: document.querySelector(".novel_cover img")?.src ??
null,
getIndexPages: async () => {
const indexPages = [];
let nextUrl = bookUrl;
do {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_2__/* .getHtmlDOM */ .wA)(nextUrl);
indexPages.push(doc);
nextUrl =
doc.querySelector("div.move_set:nth-child(4) > div:nth-child(3) > a")?.href ?? null;
} while (nextUrl);
return indexPages;
},
getAList: (doc) => doc.querySelectorAll(".episode_list li > .episode_link > a"),
getSections: (doc) => doc.querySelectorAll(".episode_list li.chapter"),
getSName: (sElem) => sElem.querySelector("cite")?.innerText.trim() ?? "",
getContent: (doc) => doc.querySelector(".content"),
contentPatch: (content) => {
Array.from(content.querySelectorAll("p")).forEach((p) => {
const div = document.createElement("div");
div.innerHTML = p.innerHTML.split("\n").join("<br>");
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__/* .insertBrBeforeText */ .Md)(div);
p.replaceWith(div);
});
return content;
},
language: "ja",
});
};
/***/ }),
/***/ "./src/rules/onePageWithMultiIndexPage/template.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ N: () => (/* binding */ mkRuleClass)
/* harmony export */ });
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_misc__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/misc.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/main/main.ts");
function mkRuleClass({ bookUrl, bookname, author, introDom, introDomPatch, coverUrl, getIndexUrls, getIndexPages, getAList, getAName, getIsVIP, getSections, getSName, postHook, getContentFromUrl, getContent, contentPatch, concurrencyLimit, sleepTime, maxSleepTime, needLogin, nsfw, cleanDomOptions, overrideConstructor, language, }) {
return class extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
if (concurrencyLimit) {
this.concurrencyLimit = concurrencyLimit;
}
if (sleepTime) {
this.sleepTime = sleepTime;
}
if (maxSleepTime) {
this.maxSleepTime = maxSleepTime;
}
if (needLogin) {
this.needLogin = needLogin;
}
if (nsfw) {
this.nsfw = nsfw;
}
if (overrideConstructor) {
overrideConstructor(this);
}
}
async bookParse() {
let [introduction, introductionHTML] = [null, null];
if (introDom && introDomPatch) {
[introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .introDomHandle */ .HV)(introDom, introDomPatch);
}
const additionalMetadate = {
language: language ?? "zh",
};
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_2__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_3___default().error(error));
}
let indexPages;
if (typeof getIndexPages === "function") {
indexPages = await getIndexPages();
}
else if (typeof getIndexUrls === "function") {
const indexUrls = await getIndexUrls();
const _indexPage = [];
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_4__/* .concurrencyRun */ .rr)(indexUrls, this.concurrencyLimit, async (url) => {
_log__WEBPACK_IMPORTED_MODULE_3___default().info(`[BookParse]抓取目录页:${url}`);
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_5__/* .getHtmlDomWithRetry */ .kP)(url, this.charset);
_indexPage.push([doc, url]);
return doc;
});
indexPages = _indexPage
.sort((a, b) => {
const aUrl = a[1];
const bUrl = b[1];
return indexUrls.indexOf(aUrl) - indexUrls.indexOf(bUrl);
})
.map((l) => l[0]);
}
else {
throw Error("未发现 getIndexUrls 或 getIndexPages");
}
const chapters = [];
let chapterNumber = 0;
let sectionNumber = 0;
let sectionChapterNumber = 0;
let sectionName = null;
for (const doc of indexPages) {
if (!doc) {
continue;
}
let sections;
let hasSection;
if (typeof getSections === "function") {
sections = getSections(doc);
hasSection = true;
}
const aList = getAList(doc);
for (const aElem of Array.from(aList)) {
let chapterName;
if (getAName) {
chapterName = getAName(aElem);
}
else {
chapterName = aElem.innerText.trim();
}
const chapterUrl = aElem.href;
if (hasSection && sections && getSName) {
const _sectionName = (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .getSectionName */ .lq)(aElem, sections, getSName);
if (_sectionName !== null && _sectionName !== sectionName) {
sectionName = _sectionName;
sectionNumber++;
sectionChapterNumber = 0;
}
}
chapterNumber++;
sectionChapterNumber++;
let isVIP = false;
let isPaid = false;
if (getIsVIP) {
({ isVIP, isPaid } = getIsVIP(aElem));
}
let chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_6__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber: hasSection ? sectionNumber : null,
sectionChapterNumber: hasSection ? sectionChapterNumber : null,
chapterParse: this.chapterParse,
charset: this.charset,
options: { bookname },
});
if (isVIP && !isPaid) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_7__/* .Status */ .nW.aborted;
}
if (typeof postHook === "function") {
chapter = postHook(chapter);
}
if (chapter) {
chapters.push(chapter);
}
}
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_8__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
let content;
if (typeof getContentFromUrl === "function") {
content = await getContentFromUrl(chapterUrl, chapterName, charset);
}
else if (typeof getContent === "function") {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_5__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
content = getContent(doc);
}
else {
throw Error("未发现 getContentFromUrl 或 getContent");
}
if (content) {
content = contentPatch(content);
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__/* .cleanDOM */ .an)(content, "TM", cleanDomOptions);
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
};
}
/***/ }),
/***/ "./src/rules/onePageWithMultiIndexPage/wanben.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ wanben: () => (/* binding */ wanben)
/* harmony export */ });
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePageWithMultiIndexPage/template.ts");
const wanben = () => {
const getIntroDom = () => {
const a = document.querySelector(".bookInfo > a");
if (a) {
a.click();
a.remove();
}
return document.querySelector(".bookInfo");
};
return (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector("div.bookPhr > h2").innerText.trim(),
author: document.querySelector("div.bookPhrMid > p:nth-child(1)").innerText
.replace("作者:", "")
.trim(),
introDom: getIntroDom(),
introDomPatch: (dom) => dom,
coverUrl: document.querySelector("div.bookImg > img")
?.src,
getIndexUrls: async () => {
const contentPageUrl = document.querySelector("#contentbox > div.detailDiv > div.category > a").href;
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(contentPageUrl, document.characterSet);
const aList = doc.querySelectorAll("div.pageBg div.pagenum a");
const indexUrls = Array.from(aList).map((a) => a.href);
return indexUrls;
},
getAList: (doc) => doc.querySelectorAll("div.chapterDiv > div.chapterList > ul > a"),
getContentFromUrl: async (chapterUrl, chapterName, charset) => {
const { contentRaw } = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_2__/* .nextPageParse */ .u1)({
chapterName,
chapterUrl,
charset,
selector: "div.raderCon",
contentPatch: (content, doc) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_3__.rm)("script", true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_3__.rm)("[style]", true, content);
const ads = [
"【提示】:如果觉得此文不错,请推荐给更多小伙伴吧!分享也是一种享受。",
"【看书助手】",
"【完本神站】",
"百万热门书籍终身无广告免费阅读",
];
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_3__/* .rm2 */ .Sf)(ads, content);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_4__/* .htmlTrim */ .is)(content);
return content;
},
getNextPage: (doc) => doc.querySelector("div.page > a:nth-child(3)")
.href,
continueCondition: (_content, nextLink) => {
const pathname = nextLink.split("/").slice(-1)[0];
return pathname.includes("_");
},
enableCleanDOM: false,
});
return contentRaw;
},
contentPatch: (dom) => dom,
});
};
/***/ }),
/***/ "./src/rules/onePageWithMultiIndexPage/xbookcn.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ xbookcn: () => (/* binding */ xbookcn)
/* harmony export */ });
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _template__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules/onePageWithMultiIndexPage/template.ts");
const xbookcn = () => (0,_template__WEBPACK_IMPORTED_MODULE_0__/* .mkRuleClass */ .N)({
bookUrl: document.location.href,
bookname: document.querySelector(".status-msg-body")?.textContent ?? "",
author: document.querySelector(".entry-content > p:nth-child(1)")?.innerText.split(":")[1] ?? "",
introDom: document.querySelector(".entry-content"),
introDomPatch: (content) => content,
coverUrl: null,
getIndexPages: async () => {
const bookUrl = document.location.origin + document.location.pathname;
const indexPages = [];
let nextUrl = bookUrl;
do {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(nextUrl, "UTF-8");
indexPages.push(doc);
nextUrl =
doc.querySelector("#Blog1_blog-pager-older-link")?.href ?? null;
} while (nextUrl);
return indexPages;
},
getAList: (doc) => doc.querySelectorAll("h3 > a"),
getAName: (aElem) => aElem.innerText.trim(),
getContent: (doc) => doc.querySelector(".entry-content"),
contentPatch: (content) => content,
language: "zh",
});
/***/ }),
/***/ "./src/rules/special/original/17k.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ C17k: () => (/* binding */ C17k)
/* harmony export */ });
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
class C17k extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.charset = "UTF-8";
this.concurrencyLimit = 5;
}
async bookParse() {
const bookUrl = document.location.href.replace("/list/", "/book/");
const bookname = document.querySelector("h1.Title").innerText.trim();
const author = document.querySelector("div.Author > a").innerText.trim();
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(bookUrl, undefined);
const introDom = doc.querySelector("#bookInfo p.intro > a");
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_2__/* .introDomHandle */ .HV)(introDom);
const additionalMetadate = {};
const coverUrl = doc.querySelector("#bookCover img.book").src;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_3__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_4___default().error(error));
}
const chapters = [];
const sections = document.querySelectorAll("dl.Volume");
let chapterNumber = 0;
for (let i = 0; i < sections.length; i++) {
const s = sections[i];
const sectionNumber = i + 1;
const sectionName = s.querySelector("dt > span.tit").innerText.trim();
let sectionChapterNumber = 0;
const cs = s.querySelectorAll("dd > a");
for (const a of Array.from(cs)) {
const span = a.firstElementChild;
chapterNumber++;
sectionChapterNumber++;
const chapterName = span.innerText.trim();
const chapterUrl = a.href;
const isVIP = () => {
return !!span?.className.includes("vip");
};
const isPaid = () => {
return false;
};
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_5__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP: isVIP(),
isPaid: isPaid(),
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
});
const isLogin = () => {
return false;
};
if (isVIP() && !(isLogin() && chapter.isPaid)) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_6__/* .Status */ .nW.aborted;
}
chapters.push(chapter);
}
}
const book = new _main_Book__WEBPACK_IMPORTED_MODULE_7__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
book.ToCUrl = document.location.href;
return book;
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
async function publicChapter() {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
chapterName = doc.querySelector("#readArea > div.readAreaBox.content > h1").innerText.trim();
const content = doc.querySelector("#readArea > div.readAreaBox.content > div.p");
if (content) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_8__.rm)("p.copy", false, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_8__.rm)("#banner_content", false, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_8__.rm)("div.qrcode", false, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_8__.rm)("div.chapter_text_ad", false, content);
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__/* .cleanDOM */ .an)(content, "TM");
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
else {
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
}
async function vipChapter() {
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
if (isVIP) {
return vipChapter();
}
else {
return publicChapter();
}
}
}
/***/ }),
/***/ "./src/rules/special/original/bilibili.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ MangaBilibili: () => (/* binding */ MangaBilibili)
/* harmony export */ });
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_misc__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/lib/misc.ts");
/* harmony import */ var _lib_hash__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/lib/hash.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _main_Attachment__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/main/Attachment.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
class MangaBilibili extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "naive";
this.concurrencyLimit = 1;
this.streamZip = true;
this.maxRunLimit = 1;
}
async bookParse() {
const _comic_id = /\/mc(\d+)$/.exec(document.location.pathname)?.[1];
if (!_comic_id) {
throw new Error("获取 comic_id 失败!");
}
const comic_id = parseInt(_comic_id);
const signIn = await isSignin(comic_id);
const detail = await getDetail(comic_id);
const nov = '25';
const bookUrl = document.location.href;
const bookname = detail.title;
const author = detail.author_name.join(", ");
const introduction = detail.evaluate;
const introductionHTML = document.createElement("div");
introductionHTML.innerText = detail.evaluate;
const additionalMetadate = {};
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_1__/* .getAttachment */ ["if"])(detail.vertical_cover, this.attachmentMode, "vertical_cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_2___default().error(error));
additionalMetadate.tags = detail.styles;
additionalMetadate.attachments = [];
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_1__/* .getAttachment */ ["if"])(detail.horizontal_cover, this.attachmentMode, "horizontal_cover-")
.then((coverClass) => {
additionalMetadate.attachments?.push(coverClass);
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_2___default().error(error));
const chapters = detail.ep_list.map((ep) => {
const chapterUrl = `https://manga.bilibili.com/mc${comic_id}/${ep.id}?from=manga_detail`;
const chapterNumber = ep.ord;
const chapterName = [ep.short_title.trim(), ep.title.trim()].join(" ");
const isVIP = ep.pay_gold !== 0;
const isPaid = isVIP ? !ep.is_locked : true;
const options = {
comic_id,
ep_id: ep.id,
nov: nov,
};
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_3__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName: null,
sectionNumber: null,
sectionChapterNumber: null,
chapterParse: this.chapterParse,
charset: this.charset,
options,
});
if (ep.is_locked || ep.type === 6) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_4__/* .Status */ .nW.aborted;
}
return chapter;
});
return new _main_Book__WEBPACK_IMPORTED_MODULE_5__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
async function isSignin(comic_id) {
const body = { comic_id };
const resp = await fetch("https://manga.bilibili.com/twirp/bookshelf.v1.Bookshelf/HasFavorite?device=pc&platform=web", {
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(body),
method: "POST",
});
return resp.ok;
}
async function getDetail(comic_id) {
const url = "https://manga.bilibili.com/twirp/comic.v1.Comic/ComicDetail?device=pc&platform=web&nov=" + nov;
const body = {
comic_id,
};
const headers = {
accept: "application/json, text/plain, */*",
"content-type": "application/json;charset=UTF-8",
};
const init = {
headers,
body: JSON.stringify(body),
method: "POST",
};
const resp = await fetch(url, init);
const data = (await resp.json());
if (data.code === 0) {
return data.data;
}
else {
throw new Error("获取目录失败!");
}
}
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const paths = await getImageIndex(options.ep_id);
const _outs = [];
const worker = async (path) => {
const obj = await getImage(path);
const out = {
path,
obj,
};
_outs.push(out);
return out;
};
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_6__/* .concurrencyRun */ .rr)(paths, 3, worker);
_outs.sort((a, b) => paths.indexOf(a.path) - paths.indexOf(b.path));
const outs = _outs.map((out) => out.obj);
const dom = document.createElement("div");
outs.forEach((o) => {
const p = document.createElement("p");
p.appendChild(o.dom);
dom.appendChild(p);
});
const text = outs.map((o) => o.text).join("\n\n");
const images = outs.map((o) => o.images);
return {
chapterName,
contentRaw: dom,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
async function getImageIndex(ep_id) {
const url = "https://manga.bilibili.com/twirp/comic.v1.Comic/GetImageIndex?device=pc&platform=web&nov=" + options.nov;
const body = {
ep_id,
};
const headers = {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json;charset=utf-8",
};
const init = {
headers,
body: JSON.stringify(body),
method: "POST",
mode: "cors",
credentials: "include",
};
const resp = await fetch(url, init);
const data = (await resp.json());
if (data.code === 0) {
const images = data.data.images;
return images.map((i) => i.path);
}
else {
throw new Error(`抓取章节图片索引失败! ep_id: ${ep_id}, code: ${data.code}, mes: ${data.msg}`);
}
}
async function getImage(path) {
const token = await getImageToken(path);
if (token) {
const img = await getImage(token);
const _dom = document.createElement("img");
_dom.setAttribute("data-src-address", img.name);
_dom.alt = img.url;
const _text = `![${img.url}](${img.name})`;
_log__WEBPACK_IMPORTED_MODULE_2___default().info(`ep_id: ${options.ep_id}, path: ${path} 抓取成功!`);
return {
dom: _dom,
text: _text,
images: img,
};
}
throw new Error("获取图片 " + path + " 失败!");
async function getImageToken(path) {
const url = "https://manga.bilibili.com/twirp/comic.v1.Comic/ImageToken?device=pc&platform=web&nov=" + options.nov;
const body = {
urls: JSON.stringify([path]),
m1: '',
};
const headers = {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json;charset=utf-8",
};
const init = {
headers,
body: JSON.stringify(body),
method: "POST",
referrer: chapterUrl,
};
const resp = await fetch(url, init);
const data = (await resp.json());
if (data.code === 0) {
return data.data[0];
}
}
async function getImage(_token) {
const url = _token.url + "?token=" + _token.token;
const headers = {
Accept: "application/json, text/plain, */*",
};
const init = {
headers,
method: "GET",
};
const resp = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_7__/* .fetchWithRetry */ .J5)(url, init);
const blob = await resp.blob();
const hash = await (0,_lib_hash__WEBPACK_IMPORTED_MODULE_8__/* .calculateSha1 */ .Q)(blob);
const ext = await (0,_lib_attachments__WEBPACK_IMPORTED_MODULE_1__/* .getExt */ .an)(blob, url);
const name = ["cm-", hash, ".", ext].join("");
const imgClass = new _main_Attachment__WEBPACK_IMPORTED_MODULE_9__/* .AttachmentClass */ .q(url, name, "naive");
imgClass.Blob = blob;
imgClass.status = _main_main__WEBPACK_IMPORTED_MODULE_4__/* .Status */ .nW.finished;
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_1__/* .putAttachmentClassCache */ .Ld)(imgClass);
return imgClass;
}
}
}
}
/***/ }),
/***/ "./src/rules/special/original/ciweimao.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Duread: () => (/* binding */ Duread),
/* harmony export */ Shubl: () => (/* binding */ Shubl)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("crypto-js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _main_Attachment__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__("./src/main/Attachment.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules.ts");
class Shubl extends _rules__WEBPACK_IMPORTED_MODULE_1__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.concurrencyLimit = 1;
this.maxRunLimit = 1;
}
async bookParse() {
const bookUrl = document.location.href;
const bookname = document.querySelector(".book-title > span").innerText.trim();
const author = document.querySelector("div.username").innerText.trim();
const introDom = document.querySelector(".book-brief");
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_2__/* .introDomHandle */ .HV)(introDom, (introDomI) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_3__/* .rms */ .j3)(["简介:"], introDomI);
return introDomI;
});
const additionalMetadate = {};
const coverUrl = document.querySelector(".book-img")
.src;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_4__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_5___default().error(error));
}
additionalMetadate.tags = Array.from(document.querySelectorAll("div.row > span.tag")).map((span) => span.innerText.trim());
const chapters = [];
const chapterTitleList = Array.from(document.querySelectorAll("#chapter_list > div.chapter > div.chapter-title")).map((div) => div.innerText.trim());
const articlesList = document.querySelectorAll("#chapter_list > div.chapter > div.articles");
const sectionLength = chapterTitleList.length;
let chapterNumber = 0;
for (let i = 0; i < sectionLength; i++) {
const s = articlesList[i];
const sectionNumber = i + 1;
const sectionName = chapterTitleList[i];
let sectionChapterNumber = 0;
const cs = s.querySelectorAll("span.chapter_item");
for (const c of Array.from(cs)) {
chapterNumber++;
sectionChapterNumber++;
const a = c.querySelector("a");
if (a) {
const chapterName = a.innerText.trim();
const chapterUrl = a.href;
const isVIP = () => {
return c.childElementCount === 2;
};
const isPaid = () => {
return isVIP() && c.querySelector("i")?.className === "unlock";
};
const isLogin = () => {
return (document.querySelector("#header > div.container > div.right.pull-right")?.childElementCount === 3);
};
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_6__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP: isVIP(),
isPaid: isPaid(),
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
});
if (isVIP() && !(isLogin() && isPaid())) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_7__/* .Status */ .nW.aborted;
}
chapters.push(chapter);
}
}
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_8__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const rootPath = document.location.origin + '/';
const [parentWidth, setFontSize] = [939.2, "18"];
return getChapter({
chapterUrl,
chapterName,
isVIP,
isPaid,
charset,
options,
rootPath,
parentWidth,
setFontSize,
});
}
}
class Duread extends _rules__WEBPACK_IMPORTED_MODULE_1__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.concurrencyLimit = 1;
this.maxRunLimit = 1;
}
async bookParse() {
const bookUrl = document.location.href;
const bookname = document.querySelector(".book-title > span").innerText.trim();
const author = document.querySelector("div.username").innerText.trim();
const introDom = document.querySelector(".book-brief");
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_2__/* .introDomHandle */ .HV)(introDom, (introDomI) => {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_3__/* .rms */ .j3)(["简介:"], introDomI);
return introDomI;
});
const additionalMetadate = {};
const coverUrl = document.querySelector(".book-img")
.src;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_4__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_5___default().error(error));
}
additionalMetadate.tags = Array.from(document.querySelectorAll("div.row > span.tag")).map((span) => span.innerText.trim());
const chapters = [];
const chapterTitleList = Array.from(document.querySelectorAll("#chapter_list > div.chapter > div.chapter-title")).map((div) => div.innerText.trim());
const articlesList = document.querySelectorAll("#chapter_list > div.chapter > div.articles");
const sectionLength = chapterTitleList.length;
let chapterNumber = 0;
for (let i = 0; i < sectionLength; i++) {
const s = articlesList[i];
const sectionNumber = i + 1;
const sectionName = chapterTitleList[i];
let sectionChapterNumber = 0;
const cs = s.querySelectorAll("span.chapter_item");
for (const c of Array.from(cs)) {
chapterNumber++;
sectionChapterNumber++;
const a = c.querySelector("a");
if (a) {
const chapterName = a.innerText.trim();
const chapterUrl = a.href;
const isVIP = () => {
return c.childElementCount === 2;
};
const isPaid = () => {
return isVIP() && c.querySelector("i")?.className === "unlock";
};
const isLogin = () => {
return (document.querySelector("#header > div.container > div.right.pull-right")?.childElementCount === 3);
};
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_6__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP: isVIP(),
isPaid: isPaid(),
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
});
if (isVIP() && !(isLogin() && isPaid())) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_7__/* .Status */ .nW.aborted;
}
chapters.push(chapter);
}
}
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_8__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const rootPath = "https://www.duread.cn/";
const [parentWidth, setFontSize] = [939.2, "18"];
return getChapter({
chapterUrl,
chapterName,
isVIP,
isPaid,
charset,
options,
rootPath,
parentWidth,
setFontSize,
});
}
}
function getChapter({ chapterUrl, chapterName, isVIP, isPaid, charset, options, rootPath, parentWidth, setFontSize, }) {
function decrypt(item) {
let message = item.content;
const keys = item.keys;
const len = item.keys.length;
const accessKey = item.accessKey;
const accessKeyList = accessKey.split("");
const charsNotLatinNum = accessKeyList.length;
const output = [];
output.push(keys[accessKeyList[charsNotLatinNum - 1].charCodeAt(0) % len]);
output.push(keys[accessKeyList[0].charCodeAt(0) % len]);
for (let i = 0; i < output.length; i++) {
message = atob(message);
const data = output[i];
const iv = btoa(message.substr(0, 16));
const keys255 = btoa(message.substr(16));
const pass = crypto_js__WEBPACK_IMPORTED_MODULE_0__.format.OpenSSL.parse(keys255);
message = crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.decrypt(pass, crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Base64.parse(data), {
iv: crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Base64.parse(iv),
format: crypto_js__WEBPACK_IMPORTED_MODULE_0__.format.OpenSSL,
});
if (i < output.length - 1) {
message = message.toString(crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Base64);
message = atob(message);
}
}
return message.toString(crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8);
}
async function getChapterAuthorSay() {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_9__/* .getHtmlDOM */ .wA)(chapterUrl, undefined);
const chapterAuthorSays = doc.querySelectorAll("#J_BookCnt .chapter.author_say");
let divChapterAuthorSay;
if (chapterAuthorSays.length !== 0) {
const hr = document.createElement("hr");
divChapterAuthorSay = document.createElement("div");
divChapterAuthorSay.appendChild(hr);
for (const chapterAuthorSay of Array.from(chapterAuthorSays)) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_3__.rm)("i", true, chapterAuthorSay);
divChapterAuthorSay.appendChild(chapterAuthorSay);
}
}
return divChapterAuthorSay;
}
const chapterId = chapterUrl.split("/").slice(-1)[0];
async function publicChapter() {
async function chapterDecrypt(chapterIdt, refererUrl) {
const accessKeyUrl = rootPath + "chapter/ajax_get_session_code";
const chapterContentUrl = rootPath + "chapter/get_book_chapter_detail_info";
_log__WEBPACK_IMPORTED_MODULE_5___default().debug(`[Chapter]请求 ${accessKeyUrl} Referer ${refererUrl}`);
const accessKeyObj = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_9__/* .gfetch */ ._V)(accessKeyUrl, {
method: "POST",
headers: {
Accept: "application/json, text/javascript, */*; q=0.01",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
Referer: refererUrl,
Origin: document.location.origin,
"X-Requested-With": "XMLHttpRequest",
},
data: `chapter_id=${chapterIdt}`,
responseType: "json",
})
.then((response) => response.response)
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_5___default().error(error));
const chapter_access_key = accessKeyObj
.chapter_access_key;
_log__WEBPACK_IMPORTED_MODULE_5___default().debug(`[Chapter]请求 ${chapterContentUrl} Referer ${refererUrl}`);
const chapterContentObj = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_9__/* .gfetch */ ._V)(chapterContentUrl, {
method: "POST",
headers: {
Accept: "application/json, text/javascript, */*; q=0.01",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
Referer: refererUrl,
Origin: document.location.origin,
"X-Requested-With": "XMLHttpRequest",
},
data: `chapter_id=${chapterIdt}&chapter_access_key=${chapter_access_key}`,
responseType: "json",
})
.then((response) => response.response)
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_5___default().error(error));
if (chapterContentObj.code !== 100000) {
_log__WEBPACK_IMPORTED_MODULE_5___default().error(chapterContentObj);
throw new Error(`下载 ${refererUrl} 失败`);
}
return decrypt({
content: chapterContentObj.chapter_content,
keys: chapterContentObj.encryt_keys,
accessKey: chapter_access_key,
});
}
const divChapterAuthorSay = await getChapterAuthorSay();
const content = document.createElement("div");
const decryptDate = await chapterDecrypt(chapterId, chapterUrl);
content.innerHTML = decryptDate;
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_3__.rm)(".chapter span", true, content);
if (divChapterAuthorSay) {
content.appendChild(divChapterAuthorSay);
}
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_10__/* .cleanDOM */ .an)(content, "TM");
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
async function vipChapter(parentWidth, setFontSize) {
async function vipChapterDecrypt(chapterIdi, refererUrl) {
const imageSessionCodeUrl = rootPath + "chapter/ajax_get_image_session_code";
_log__WEBPACK_IMPORTED_MODULE_5___default().debug(`[Chapter]请求 ${imageSessionCodeUrl} Referer ${refererUrl}`);
const imageSessionCodeObject = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_9__/* .gfetch */ ._V)(imageSessionCodeUrl, {
method: "POST",
headers: {
Accept: "application/json, text/javascript, */*; q=0.01",
Referer: refererUrl,
Origin: document.location.origin,
"X-Requested-With": "XMLHttpRequest",
},
responseType: "json",
})
.then((response) => response.response)
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_5___default().error(error));
if (imageSessionCodeObject.code !== 100000) {
_log__WEBPACK_IMPORTED_MODULE_5___default().error(imageSessionCodeObject);
throw new Error(`下载 ${refererUrl} 失败`);
}
const imageCode = decrypt({
content: imageSessionCodeObject.image_code,
keys: imageSessionCodeObject.encryt_keys,
accessKey: imageSessionCodeObject
.access_key,
});
const vipCHapterImageUrlI = rootPath +
"chapter/book_chapter_image?chapter_id=" +
chapterIdi +
"&area_width=" +
parentWidth +
"&font=undefined" +
"&font_size=" +
setFontSize +
"&image_code=" +
imageCode +
"&bg_color_name=white" +
"&text_color_name=white";
return vipCHapterImageUrlI;
}
const getIsLogin = () => {
if (document.location.host === "www.duread.cn" || document.location.host === "duread.cn") {
return (document.querySelector("div.dropdown-menu")?.childElementCount === 3);
}
else if (document.location.host === "www.shubl.com" || document.location.host === "shubl.com") {
return (document.querySelector("div.pull-right:nth-child(2)")
?.childElementCount === 3);
}
else {
return (document.querySelector(".login-info.ly-fr")?.childElementCount === 1);
}
};
const isLogin = getIsLogin();
if (isLogin && isPaid) {
const divChapterAuthorSay = await getChapterAuthorSay();
const vipCHapterImageUrl = await vipChapterDecrypt(chapterId, chapterUrl);
_log__WEBPACK_IMPORTED_MODULE_5___default().debug(`[Chapter]请求 ${vipCHapterImageUrl} Referer ${chapterUrl}`);
const vipCHapterImageBlob = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_9__/* .gfetch */ ._V)(vipCHapterImageUrl, {
method: "GET",
headers: {
Referer: chapterUrl,
Accept: "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
},
responseType: "blob",
})
.then((response) => response.response)
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_5___default().error(error));
const vipCHapterName = `vipCHapter${chapterId}.png`;
const vipCHapterImage = new _main_Attachment__WEBPACK_IMPORTED_MODULE_11__/* .AttachmentClass */ .q(vipCHapterImageUrl, vipCHapterName, "TM");
if (vipCHapterImageBlob) {
vipCHapterImage.Blob = vipCHapterImageBlob;
vipCHapterImage.status = _main_main__WEBPACK_IMPORTED_MODULE_7__/* .Status */ .nW.finished;
}
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_4__/* .putAttachmentClassCache */ .Ld)(vipCHapterImage);
const contentImages = [vipCHapterImage];
let ddom;
let dtext;
if (divChapterAuthorSay) {
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_10__/* .cleanDOM */ .an)(divChapterAuthorSay, "TM");
[ddom, dtext] = [dom, text, images];
}
const img = document.createElement("img");
img.setAttribute("data-src-address", vipCHapterName);
img.alt = vipCHapterImageUrl;
const contentHTML = document.createElement("div");
contentHTML.appendChild(img);
if (ddom) {
contentHTML.appendChild(ddom);
}
let contentText = `VIP章节,请打开HTML文件查看。\n![${vipCHapterImageUrl}](${vipCHapterName})`;
if (dtext) {
contentText = contentText + "\n\n" + dtext;
}
return {
chapterName,
contentRaw: contentHTML,
contentText,
contentHTML,
contentImages,
additionalMetadate: null,
};
}
else {
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
}
if (isVIP) {
return vipChapter(parentWidth, setFontSize);
}
else {
return publicChapter();
}
}
/***/ }),
/***/ "./src/rules/special/original/ciyuanji.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Ciyuanji: () => (/* binding */ Ciyuanji)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("crypto-js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules.ts");
class Ciyuanji extends _rules__WEBPACK_IMPORTED_MODULE_1__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.concurrencyLimit = 1;
}
async bookParse() {
const bookUrl = document.location.href;
const bookObject = unsafeWindow.__NEXT_DATA__.props.pageProps.book;
const bookId = bookObject.bookId;
const bookname = bookObject.bookName;
const author = bookObject.authorName;
const introDom = document.createElement("div");
introDom.innerHTML = bookObject.notes.replace("/\n/g", "<br/><br/>");
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_2__/* .introDomHandle */ .HV)(introDom);
const additionalMetadate = {};
const coverUrl = bookObject.imgUrl;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_3__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_4___default().error(error));
}
additionalMetadate.tags = bookObject.tagList.map((tagobj) => tagobj.tagName);
const bookChapterObject = unsafeWindow.__NEXT_DATA__.props.pageProps.bookChapter;
const chapterList = bookChapterObject.chapterList;
const chapters = [];
let chapterNumber = 0;
let sectionName = null;
let sectionNumber = 0;
let sectionChapterNumber = 0;
for (const chapterObj of chapterList) {
const chapterId = chapterObj.chapterId;
const chapterUrl = `${document.location.origin}/chapter/${bookId}_${chapterId}`;
const chapterName = chapterObj.chapterName;
const _sectionName = chapterObj.title;
if (sectionName !== _sectionName) {
sectionName = _sectionName;
sectionNumber++;
sectionChapterNumber = 0;
}
chapterNumber++;
sectionChapterNumber++;
const isVIP = chapterObj.isFee === "1";
const isPaid = chapterObj.isBuy === "1";
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_5__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
});
if (chapter.isVIP && !chapter.isPaid) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_6__/* .Status */ .nW.aborted;
}
chapters.push(chapter);
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_7__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const data = {
key: "ZUreQN0Epkpxh3pooWOgixjTfPwumCTYWzYTQ7SMgDnqFLQ1s9tqpVhkGf02we89moQwhSQ07DVzc3LWupRgbVvm29aYeY7zyFN",
type1: "PC-Token",
type2: "PC-UserInfo",
type3: "PC-Enum",
type4: "PC-IsActivityStart",
f: "NpkTYvpvhJjEog8Y051gQDHmReY54z5t3F0zSd9QEFuxWGqfC8g8Y4GPuabq0KPdxArlji4dSnnHCARHnkqYBLu7iIw55ibTo18",
};
function encrypt(input) {
if (input && "string" === typeof input) {
const key = crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8.parse(data.key);
return crypto_js__WEBPACK_IMPORTED_MODULE_0__.DES.encrypt(input, key, {
mode: crypto_js__WEBPACK_IMPORTED_MODULE_0__.mode.ECB,
padding: crypto_js__WEBPACK_IMPORTED_MODULE_0__.pad.Pkcs7,
}).toString();
}
}
function decrypt(input) {
if (input && "string" === typeof input) {
input = input.replace(/\n/g, "");
const key = crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8.parse(data.key);
return crypto_js__WEBPACK_IMPORTED_MODULE_0__.DES.decrypt(input, key, {
mode: crypto_js__WEBPACK_IMPORTED_MODULE_0__.mode.ECB,
padding: crypto_js__WEBPACK_IMPORTED_MODULE_0__.pad.Pkcs7,
}).toString(crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8);
}
}
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_8__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
const nextDataElement = document.getElementById("__NEXT_DATA__");
if (!nextDataElement) {
throw new Error("无法找到'__NEXT_DATA__',下载失败");
}
const __NEXT_DATA__ = JSON.parse(nextDataElement.innerHTML);
const chapterObj = __NEXT_DATA__.props.pageProps.chapterContent.chapter;
const content = document.createElement("div");
const chapterContent = decrypt(chapterObj.chapterContentFormat);
if (chapterContent) {
content.innerHTML = chapterContent;
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__/* .cleanDOM */ .an)(content, "TM");
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
}
/***/ }),
/***/ "./src/rules/special/original/cool18.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Cool18: () => (/* binding */ Cool18)
/* harmony export */ });
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
class Cool18 extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.nsfw = true;
}
async bookParse() {
const bookUrl = document.location.href;
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(bookUrl, this.charset);
const title = doc.querySelector('.show_content > center > font[size="6"] > b').innerText.trim();
const matchs = /[【《](.+)[】》](.+)?作者:([^\s-]+)/.exec(title);
let bookname = title;
let author = "";
if (matchs) {
bookname = matchs[1];
author = matchs[3];
}
const introduction = null;
const introductionHTML = null;
const additionalMetadate = {};
const _aElems = Array.from(document.querySelectorAll(".show_content > pre a, body > table:nth-child(7) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > ul:nth-child(2) > li > a"));
const _a = document.createElement("a");
_a.href = document.location.href;
_a.innerText = title;
_aElems.push(_a);
const aElems = _aElems
.filter((a) => {
const href = a.href;
const url = new URL(href);
return (url.searchParams.get("act") === "threadview" &&
url.searchParams.has("tid"));
})
.filter((a) => a.innerText.includes("(无内容)") === false)
.filter((item, pos, self) => {
const urls = self.map((a) => a.href);
const url = item.href;
return urls.indexOf(url) === pos;
})
.sort((a, b) => {
const _aTid = new URL(a.href).searchParams.get("tid");
const _bTid = new URL(b.href).searchParams.get("tid");
const aTid = parseInt(_aTid);
const bTid = parseInt(_bTid);
return aTid - bTid;
});
const chapters = aElems.map((a) => {
const chapterUrl = a.href;
const chapterNumber = -1;
const chapterName = a.innerText
.replace(`【${bookname}】`, "")
.replace(`《${bookname}》`, "")
.replace(`作者:${author}`, "")
.trim();
return new _main_Chapter__WEBPACK_IMPORTED_MODULE_2__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP: false,
isPaid: false,
sectionName: null,
sectionNumber: null,
sectionChapterNumber: null,
chapterParse: this.chapterParse,
charset: this.charset,
options: { bookname, author },
});
});
let i = 0;
for (const chapter of chapters) {
i++;
chapter.chapterNumber = i;
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_3__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_1__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
chapterName = doc.querySelector('.show_content > center > font[size="6"] > b').innerText
.replace(`【${options.bookname}】`, "")
.replace(`《${options.bookname}》`, "")
.replace(`作者:${options.author}`, "")
.trim();
const dom = doc.querySelector(".show_content > pre, .show_content > div");
if (dom) {
Array.from(dom.querySelectorAll('font[color*="E6E6DD"]')).forEach((f) => f.remove());
const contentRaw = document.createElement("div");
const nodes = Array.from(dom.childNodes);
if (nodes.length > 10) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_4__/* .childNodesCopy */ .Fv)(dom, contentRaw);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_4__.rm)("a", true, contentRaw);
(0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_5__/* .convertFixWidth */ .N0)(contentRaw);
}
else {
for (const node of nodes) {
if (node instanceof Text && (node.textContent?.length ?? 0) > 200) {
if ((0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_5__/* .isFixWidth */ .eu)(node)) {
contentRaw.appendChild((0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_5__/* .convertFixWidthText */ .WF)(node));
continue;
}
else {
const div = document.createElement("div");
div.innerText = node.textContent?.trim() ?? "";
contentRaw.appendChild(div);
continue;
}
}
contentRaw.appendChild(node);
}
Array.from(contentRaw.querySelectorAll("p"))
.filter((p) => p.innerText.trim() === "" &&
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_4__/* .getPreviousSibling */ .UN)(p) instanceof HTMLElement &&
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_4__/* .getNextSibling */ .wX)(p) instanceof HTMLElement)
.forEach((p) => p.remove());
}
const { dom: contentHTML, text: contentText, images: contentImages, } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_5__/* .cleanDOM */ .an)(contentRaw, "TM");
return {
chapterName,
contentRaw,
contentText,
contentHTML,
contentImages,
additionalMetadate: null,
};
}
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
}
/***/ }),
/***/ "./src/rules/special/original/doufuyuedu.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ doufuyuedu: () => (/* binding */ doufuyuedu)
/* harmony export */ });
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/lib/cleanDOM.ts");
class doufuyuedu extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "naive";
this.concurrencyLimit = 1;
this.maxRunLimit = 1;
}
async bookParse() {
const bookUrl = document.location.href;
const bookID = bookUrl.match(/novel-(\d+)/)[1];
const bookname = document.querySelector("h1.book_tt").innerText.trim();
const author = document.querySelector("div.user_name").innerText.trim();
const introductionHTML = document.createElement("div");
introductionHTML.innerHTML = document.querySelector("div.book_des").innerHTML;
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("a", true, introductionHTML);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("span", true, introductionHTML);
const introduction = introductionHTML.innerText;
const additionalMetadate = {};
const coverUrl = document.querySelector("img.book_img ").src;
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_2__/* .getAttachment */ ["if"])(coverUrl, "TM", "vertical_cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_3___default().error(error));
additionalMetadate.tags = Array.from(document.querySelectorAll("div.book_subtt > span.book_tag")).map((tag) => tag.innerText);
const chapters = [];
let chapterNumber = 0;
let sectionNumber = 0;
let sectionChapterNumber = 0;
const sectionList = document.querySelectorAll("div.catelogue");
Array.from(sectionList).forEach((section) => {
sectionNumber++;
sectionChapterNumber = 0;
const sectionName = section.querySelector("div.catelogue_hd").innerText.trim();
const chapterList = section.querySelectorAll("div.catelogue_bd > ul > li > a");
const isVIP = (section.querySelector("i.icon-vip") ?? null) == null;
Array.from(chapterList).forEach((ep) => {
const chapterUrl = ep.href;
const chapterName = ep.innerText.trim();
chapterNumber++;
sectionChapterNumber++;
const isPaid = true;
const options = {};
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_4__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName: sectionName,
sectionNumber: sectionNumber,
sectionChapterNumber: sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options,
});
chapters.push(chapter);
});
});
return new _main_Book__WEBPACK_IMPORTED_MODULE_5__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const rawDom = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_6__/* .getFrameContentEvent */ .n6)(chapterUrl) ?? document.createElement("html");
const contentRaw = document.createElement("div");
contentRaw.innerHTML = rawDom.querySelector("div#J_chapterContent").innerHTML;
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_1__.rm)("span", true, contentRaw);
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_7__/* .cleanDOM */ .an)(contentRaw, "TM");
return {
chapterName,
contentRaw: contentRaw,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
}
/***/ }),
/***/ "./src/rules/special/original/esjzone.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ esjzone: () => (/* binding */ esjzone)
/* harmony export */ });
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
class esjzone extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
}
async bookParse() {
const bookUrl = document.location.href;
const bookname = document.querySelector(".book-detail h2").innerText.trim();
const author = Array.from(document.querySelectorAll('ul.book-detail li')).find(li => li.textContent && li.textContent.includes('作者:'))?.querySelector('a')?.innerText.trim() || "Unknown Author";
const introDom = document.querySelector(".description");
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .introDomHandle */ .HV)(introDom);
const additionalMetadate = {};
additionalMetadate.tags = Array.from(document.querySelectorAll('section.widget-tags.m-t-20 a.tag')).map((a) => a.innerText);
const isVIP = false;
const isPaid = false;
const coverUrl = document.querySelector("div.product-gallery")?.querySelector("img")?.getAttribute("src") ?? null;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_2__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_3___default().error(error));
}
const chapters = [];
let chapterNumber = 0;
let sectionName = null;
let sectionNumber = 0;
let sectionChapterNumber = 0;
function getAName(aElem) {
return aElem.querySelector("p")?.innerHTML.trim() ?? aElem?.innerText.trim();
}
const sectionList = document.querySelector('#chapterList')?.childNodes ?? [];
sectionList.forEach((sectionElem) => {
const node = sectionElem;
switch (node.tagName) {
case 'A': {
sectionChapterNumber++;
const chapterUrl = sectionElem.href;
const chapterName = getAName(node);
chapterNumber++;
sectionChapterNumber++;
chapters.push(new _main_Chapter__WEBPACK_IMPORTED_MODULE_4__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
}));
break;
}
case 'DETAILS': {
sectionName = node.querySelector('summary')?.innerText.trim() ?? null;
const aList = node.querySelectorAll('a');
sectionNumber++;
sectionChapterNumber = 0;
aList.forEach((aElem) => {
const chapterUrl = aElem.href;
const chapterName = getAName(aElem);
chapterNumber++;
sectionChapterNumber++;
chapters.push(new _main_Chapter__WEBPACK_IMPORTED_MODULE_4__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
}));
});
break;
}
case 'P':
sectionName = node?.innerText?.trim() ?? null;
sectionNumber++;
sectionChapterNumber = 0;
break;
}
});
return new _main_Book__WEBPACK_IMPORTED_MODULE_5__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_6__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
const content = doc.querySelector('.forum-content');
if (content) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_7__.rm)('h3', true, content);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_7__.rm)('footer', true, content);
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_8__/* .cleanDOM */ .an)(content, "TM");
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
else {
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: [],
additionalMetadate: null,
};
}
}
}
/***/ }),
/***/ "./src/rules/special/original/faloo.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ faloo: () => (/* binding */ faloo)
/* harmony export */ });
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
class faloo extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.concurrencyLimit = 1;
this.maxRunLimit = 1;
this.sleepTime = 1000;
this.maxSleepTime = 5000;
}
async bookParse() {
const bookUrl = document.location.href;
const bookname = document.querySelector("h1#novelName").innerText.trim();
const author = document.querySelector("img.rentouOne").innerText.trim();
const introDom = document.querySelector("div.T-L-T-C-Box1");
let introduction = null;
let introductionHTML = null;
if (introDom) {
[introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .introDomHandle */ .HV)(introDom);
}
const additionalMetadate = {};
const coverUrl = document.querySelector("img.imgcss")
?.src ?? null;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_2__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_3___default().error(error));
}
additionalMetadate.tags = Array.from(document.querySelectorAll("div.T-R-T-B2-Box1 a")).map((a) => a.innerText.trim());
const aList = document.querySelectorAll("div.C-Fo-Zuo div.DivTable a");
const sections = document.querySelectorAll("div.C-Fo-Zuo h3 a");
const chapters = [];
function getName(aElem) {
return aElem?.innerText.trim();
}
let chapterNumber = 0;
let sectionNumber = 0;
let sectionChapterNumber = 0;
let sectionName = null;
for (const aElem of Array.from(aList)) {
const chapterName = aElem.innerText.trim();
const chapterUrl = aElem.href;
const _sectionName = (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .getSectionName */ .lq)(aElem, sections, getName);
if (_sectionName !== sectionName) {
sectionName = _sectionName;
sectionNumber++;
sectionChapterNumber = 0;
}
chapterNumber++;
sectionChapterNumber++;
const isVIP = false;
const isPaid = false;
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_4__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber: sectionNumber,
sectionChapterNumber: sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: { bookname },
});
if (isVIP && !isPaid) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_5__/* .Status */ .nW.aborted;
}
if (chapter) {
chapters.push(chapter);
}
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_6__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_7__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
if (!doc) {
throw new Error("chapterParse: getHtmlDOM error");
}
const doms = doc.querySelector("div.noveContent");
const content = document.createElement("div");
if (doms) {
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_8__.rm)("b", true, doms);
if (doms.querySelector("div.con_img")) {
const domain = "https://read.faloo.com/";
const script = Array.from(doc.querySelectorAll('script')).find(s => s?.textContent && s.textContent.includes('image_do3'));
if (script) {
const match = script?.textContent?.match(/image_do3(.*)/);
if (match) {
const [num, o, id, n, en, t, k, u, time, fontsize, fontcolor, chaptertype, font_family_type, background_type, unt, now_time] = match[1].split(/['",]+/).filter(Boolean);
const fontcolor1 = "000000";
const url = domain + "Page4VipImage.aspx?num=" + num + "&o=" + o + "&id=" + id + "&n=" + n
+ "&ct=" + chaptertype + "&en=" + en + "&t=" + t + "&font_size=" + fontsize
+ "&font_color=" + fontcolor1 + "&FontFamilyType=" + font_family_type + "&backgroundtype="
+ background_type + "&u=" + u + "&time=" + time + "&k=" + k;
const img = document.createElement("img");
img.alt = "VIP图片章节,请使用Epub下载";
img.src = url;
content.appendChild(img);
}
}
}
else {
content.innerHTML = doms.innerHTML;
}
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_9__/* .cleanDOM */ .an)(content, "TM", undefined);
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
}
/***/ }),
/***/ "./src/rules/special/original/fanqie.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ fanqie: () => (/* binding */ fanqie)
/* harmony export */ });
/* unused harmony export replaceFanqieCharacter */
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_GM__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/lib/GM.ts");
/* harmony import */ var _lib_misc__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/misc.ts");
class fanqie extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.concurrencyLimit = 1;
}
async bookParse() {
const bookUrl = document.location.href;
const bookname = document.querySelector(".info-name h1").innerText.trim();
const author = document.querySelector('.author-name')?.innerText.trim();
const introDom = document.querySelector(".page-abstract-content");
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_1__/* .introDomHandle */ .HV)(introDom);
const additionalMetadate = {};
additionalMetadate.tags = Array.from(document.querySelectorAll('span.info-label-grey')).map((a) => a.innerText);
const chapters = [];
let chapterNumber = 0;
let sectionName = null;
let sectionNumber = 0;
let sectionChapterNumber = 0;
const sectionList = document.querySelector('.page-directory-content')?.childNodes ?? [];
sectionList.forEach((sectionElem) => {
const node = sectionElem;
sectionName = node.querySelector('div.volume')?.innerText.trim();
sectionChapterNumber = 0;
sectionNumber++;
const chapterList = node.querySelectorAll('div.chapter-item');
chapterList.forEach((chapterElem) => {
sectionChapterNumber++;
chapterNumber++;
const chapterUrl = chapterElem.querySelector('a').href;
const chapterName = chapterElem.querySelector('a').innerText;
const isVIP = chapterElem.querySelector('.chapter-item-lock') ? true : false;
const isPaid = false;
chapters.push(new _main_Chapter__WEBPACK_IMPORTED_MODULE_2__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
}));
});
});
while (document.querySelectorAll(".book-cover img.loaded").length === 0)
await new Promise((resolve) => setTimeout(resolve, 1000));
const coverUrl = document.querySelector(".book-cover img.loaded")?.getAttribute("src") ?? null;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_3__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_4___default().error(error));
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_5__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const contentRaw = document.createElement('div');
if (isVIP) {
_log__WEBPACK_IMPORTED_MODULE_4___default().debug('未购买SVIP,尝试第三方API获取章节内容');
const id = chapterUrl.match(/\d+/);
const url = `https://novel.snssdk.com/api/novel/reader/full/v1/?item_id=${id}`;
const result = await new Promise((resolve) => {
(0,_lib_GM__WEBPACK_IMPORTED_MODULE_6__/* ._GM_xmlhttpRequest */ .nV)({
url: url,
method: "GET",
onload: function (response) {
if (response.status === 200) {
resolve(response.responseText);
}
else {
_log__WEBPACK_IMPORTED_MODULE_4___default().error(response);
resolve('');
}
},
});
});
let json = null;
let content = '';
try {
json = JSON.parse(result);
}
catch (error) {
_log__WEBPACK_IMPORTED_MODULE_4___default().error('JSON.parse(result) error', error);
}
const data = json?.data ?? null;
if (!data) {
_log__WEBPACK_IMPORTED_MODULE_4___default().debug(url, result);
content = '你没有购买SVIP,且第三方API获取章节内容失败';
}
else if (data.need_pay)
content = '你没有购买SVIP,且第三方API未购买VIP';
else
content = data.content;
contentRaw.innerHTML = content;
}
else {
const textSelector = '.muye-reader-content';
const html = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_7__/* .getFrameContentConditionWithWindow */ .Q2)(chapterUrl, (frame) => {
const doc = frame.contentWindow?.document ?? null;
if (doc) {
return doc.querySelectorAll(textSelector).length !== 0;
}
else {
return false;
}
});
const doc = html?.document?.querySelector(textSelector) ?? null;
if (!html || !doc) {
contentRaw.innerHTML = '获取章节内容失败';
}
else {
const [fontName, fontlink] = await getFont(html);
if (fontName && fontlink) {
contentRaw.innerHTML = await replaceFanqieCharacter(fontName, fontlink, doc.innerHTML);
}
else {
_log__WEBPACK_IMPORTED_MODULE_4___default().error('字体替换失败,字体名称:', fontName, '字体链接:', fontlink);
contentRaw.innerHTML = '字体替换失败';
}
}
}
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_8__/* .cleanDOM */ .an)(contentRaw, "TM");
return {
chapterName,
contentRaw: contentRaw,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
}
async function getFont(dom) {
const style = dom.document.querySelector('div.muye-reader-box')?.style;
const fontFamily = style?.fontFamily.split(',')[0] ?? null;
const styleSheets = dom?.document?.styleSheets ?? null;
if (!fontFamily || !styleSheets) {
return [null, null];
}
for (const styleSheet of Array.from(styleSheets)) {
try {
const cssRules = styleSheet.cssRules;
for (const rule of Array.from(cssRules)) {
const ruleElem = rule;
const font = ruleElem?.style?.fontFamily?.replace(/['"]/g, '') ?? null;
if (font && fontFamily.includes(font)) {
let src = ruleElem.style.getPropertyValue('src');
const match = src.match(/url\(["']?([^"')]+)["']?\)/);
if (match) {
src = match[1];
const fileNameMatch = src.match(/[^/]+$/);
const fileName = fileNameMatch ? fileNameMatch[0] : null;
return [fileName, src];
}
}
}
}
catch (e) {
_log__WEBPACK_IMPORTED_MODULE_4___default().error('Cannot find stylesheet:', e);
}
}
return [null, null];
}
async function replaceFanqieCharacter(fontName, fontlink, inputText) {
let outputText = inputText;
const FontTable = await getFanqieFontTable(fontName, fontlink);
if (FontTable) {
for (const Character in FontTable) {
if (Object.prototype.hasOwnProperty.call(FontTable, Character)) {
const normalCharacter = FontTable[Character];
outputText = outputText.replaceAll(Character, normalCharacter);
}
}
}
else {
return `[fanqie-font]字体对照表 ${fontName} 未找到,请前往https://github.com/404-novel-project/fanqie_font_tables 提交字体链接, ${fontlink}`;
}
return outputText;
}
async function getFanqieFontTable(fontName, fontlink) {
const FontTable = await fetchRemoteFont(fontName);
if (!FontTable) {
_log__WEBPACK_IMPORTED_MODULE_4___default().error(`[fanqie-font]字体对照表 ${fontName} 未找到,请前往https://github.com/404-novel-project/fanqie_font_tables 提交字体链接, ${fontlink}`);
}
else {
_log__WEBPACK_IMPORTED_MODULE_4___default().debug(`[fanqie-font]字体对照表 ${fontName}已找到,如果你认为字体对应有错误,请前往https://github.com/404-novel-project/fanqie_font_tables 重新提交字体链接, ${fontlink}`);
}
return FontTable;
}
async function fetchRemoteFont(fontName) {
const url = `https://fastly.jsdelivr.net/gh/404-novel-project/fanqie_font_tables@master/${fontName}.json`;
_log__WEBPACK_IMPORTED_MODULE_4___default().info(`[fanqie-font]开始请求远程字体对照表 ${fontName}`);
const retryLimit = 10;
let retry = retryLimit;
while (retry > 0) {
let responseStatus = -1;
try {
const response = await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload: (response) => {
responseStatus = response.status;
if (response.status >= 200 && response.status < 300) {
_log__WEBPACK_IMPORTED_MODULE_4___default().info(`[fanqie-font]远程字体对照表 ${fontName} 下载成功`);
resolve(JSON.parse(response.responseText));
}
else {
reject(new Error(`HTTP status ${response.status}`));
}
},
onerror: (error) => {
reject(error);
}
});
});
if (response) {
return response;
}
}
catch (error) {
_log__WEBPACK_IMPORTED_MODULE_4___default().error(error);
retry--;
if (responseStatus === 404 || retry < 0) {
_log__WEBPACK_IMPORTED_MODULE_4___default().info(`[fanqie-font]远程字体对照表 ${fontName} 下载失败`);
return undefined;
}
else {
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_9__/* .sleep */ .yy)(2000);
continue;
}
}
}
}
/***/ }),
/***/ "./src/rules/special/original/gongzicp.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Gongzicp: () => (/* binding */ Gongzicp)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("crypto-js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_misc__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/misc.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var _setting__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/setting.ts");
class Gongzicp extends _rules__WEBPACK_IMPORTED_MODULE_1__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
this.concurrencyLimit = 1;
this.maxRunLimit = 1;
}
async bookParse() {
const bookUrl = document.location.href;
const bookId = document.querySelector("span.c-light-gray").innerText.replace("CP", "");
if (!bookId) {
throw new Error("获取bookID出错");
}
const novelGetInfoBaseUrl = "https://www.gongzicp.com/webapi/novel/novelGetInfo";
const novelGetInfoUrl = new URL(novelGetInfoBaseUrl);
novelGetInfoUrl.searchParams.set("id", bookId);
_log__WEBPACK_IMPORTED_MODULE_2___default().debug(`请求地址: ${novelGetInfoUrl.toString()}`);
const novelInfo = await fetch(novelGetInfoUrl.toString(), {
credentials: "include",
headers: {
Accept: "application/json, text/plain, */*",
Client: "pc",
Lang: "cn",
"Content-Type": "application/json;charset=utf-8",
},
referrer: bookUrl,
method: "GET",
mode: "cors",
})
.then((response) => response.json())
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_2___default().error(error));
if (novelInfo.code !== 200) {
throw new Error(`数据接口请求失败,URL:${novelGetInfoUrl.toString()}`);
}
const data = novelInfo.data;
const bookname = data.novelInfo.novel_name;
const author = data.novelInfo.author_nickname;
const introDom = document.createElement("div");
introDom.innerHTML = data.novelInfo.novel_info;
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_3__/* .introDomHandle */ .HV)(introDom);
const additionalMetadate = {};
const coverUrl = data.novelInfo.novel_cover;
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_4__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_2___default().error(error));
}
additionalMetadate.tags = data.novelInfo.tag_list;
async function isLogin() {
const getUserInfoUrl = "https://www.gongzicp.com/webapi/user/getUserInfo";
_log__WEBPACK_IMPORTED_MODULE_2___default().debug(`正在请求: ${getUserInfoUrl}`);
const userInfo = await fetch(getUserInfoUrl, {
headers: {
accept: "application/json, text/javascript, */*; q=0.01",
"x-requested-with": "XMLHttpRequest",
},
method: "GET",
mode: "cors",
credentials: "include",
})
.then((response) => response.json())
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_2___default().error(error));
return userInfo.code === 200;
}
const logined = await isLogin();
const chapters = [];
const _chapterList = data.chapterList;
let sectionNumber = 0;
let sectionName = null;
let sectionChapterNumber = 0;
for (const chapterObj of _chapterList) {
if (chapterObj.type === "volume") {
sectionNumber = chapterObj.vid;
sectionName = chapterObj.name;
sectionChapterNumber = 0;
}
else if (chapterObj.type === "item") {
const chapterUrl = [
document.location.origin,
`read-${chapterObj.id}.html`,
].join("/");
const chapterNumber = parseInt(chapterObj.order);
const chapterName = chapterObj.name;
const isVIP = chapterObj.pay;
const isPaid = chapterObj.is_sub;
const isLock = chapterObj.lock || chapterObj.chapter_status !== 1;
sectionChapterNumber++;
const chapterOption = {
novel_id: data.novelInfo.novel_id,
chapter_id: chapterObj.id,
};
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_5__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: chapterOption,
});
if ((isVIP && !(logined && chapter.isPaid)) || isLock) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_6__/* .Status */ .nW.aborted;
}
chapters.push(chapter);
}
}
return new _main_Book__WEBPACK_IMPORTED_MODULE_7__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
function cpDecrypt(input) {
class CP {
iv;
key;
constructor(iv, key) {
iv += parseInt("165455", 14).toString(32);
this.iv = crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8.parse("$h$b3!" + iv);
key = atob(key) + parseInt("4d5a6c8", 14).toString(36);
this.key = crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8.parse(key + "A");
}
encrypt(input) {
if (typeof input === "string") {
const str = JSON.stringify(input);
const byte = crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8.parse(str);
return crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.encrypt(byte, this.key, {
mode: crypto_js__WEBPACK_IMPORTED_MODULE_0__.mode.CBC,
padding: crypto_js__WEBPACK_IMPORTED_MODULE_0__.pad.Pkcs7,
iv: this.iv,
});
}
}
decrypt(input) {
const byte = crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.decrypt(input, this.key, {
mode: crypto_js__WEBPACK_IMPORTED_MODULE_0__.mode.CBC,
padding: crypto_js__WEBPACK_IMPORTED_MODULE_0__.pad.Pkcs7,
iv: this.iv,
});
return crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8.stringify(byte).toString();
}
}
const cp = new CP("iGzsYn", "dTBMUnJidSRFbg==");
const content = cp.decrypt(input);
return content;
}
function randomWalker() {
_log__WEBPACK_IMPORTED_MODULE_2___default().info("[chapter]随机翻页中……");
if (document.location.pathname.includes("novel")) {
document.querySelector(".chapter-list .chapter a").click();
}
if (document.location.pathname.includes("read")) {
const rightMenu = document.querySelector(".right-menu");
if (rightMenu?.childElementCount === 6) {
document.querySelector(".right-menu > div:nth-child(3) > a:nth-child(1)").click();
}
else if (rightMenu?.childElementCount === 7) {
if (document.querySelector("div.content.unpaid")) {
document.querySelector(".right-menu > div:nth-child(3) > a:nth-child(1)").click();
}
else if (Math.random() < 0.3) {
document.querySelector(".right-menu > div:nth-child(3) > a:nth-child(1)").click();
}
else {
document.querySelector(".right-menu > div:nth-child(4) > a:nth-child(1)").click();
}
}
}
}
async function getChapter() {
const cid = options.chapter_id;
const chapterGetInfoBaseUrl = "https://www.gongzicp.com/webapi/novel/chapterGetInfo";
const chapterGetInfoUrl = new URL(chapterGetInfoBaseUrl);
chapterGetInfoUrl.searchParams.set("cid", cid.toString());
chapterGetInfoUrl.searchParams.set("server", "0");
let retryTime = 0;
async function getChapterInfo(url) {
_log__WEBPACK_IMPORTED_MODULE_2___default().debug(`请求地址: ${url}, Referrer: ${chapterUrl},retryTime:${retryTime}`);
const resultI = await fetch(url, {
credentials: "include",
headers: {
Accept: "application/json, text/plain, */*",
Client: "pc",
"Content-Type": "application/json",
},
referrer: chapterUrl,
method: "GET",
})
.then((resp) => resp.json())
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_2___default().error(error));
if (resultI.data.chapterInfo.content.length !== 0 &&
resultI.data.chapterInfo.content.length < 30) {
retryTime++;
if (retryTime > _setting__WEBPACK_IMPORTED_MODULE_8__/* .retryLimit */ .Iz) {
_log__WEBPACK_IMPORTED_MODULE_2___default().error(`请求 ${url} 失败`);
throw new Error(`请求 ${url} 失败`);
}
_log__WEBPACK_IMPORTED_MODULE_2___default().warn("[chapter]疑似被阻断,进行随机翻页……");
const walkerTime = Math.round(Math.random() * retryTime) + 1;
for (let i = 0; i < walkerTime; i++) {
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_9__/* .sleep */ .yy)(3000 + Math.round(Math.random() * 5000));
randomWalker();
}
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_9__/* .sleep */ .yy)(3000 + Math.round(Math.random() * 2000));
return getChapterInfo(url);
}
else {
retryTime = 0;
return resultI;
}
}
const result = await getChapterInfo(chapterGetInfoUrl.toString());
if (result.code === 200) {
const chapterInfo = result.data.chapterInfo;
if (chapterInfo.chapterPrice !== 0 &&
chapterInfo.content.length === 0) {
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
else if (chapterInfo.chapterPrice === 0 ||
(chapterInfo.chapterPrice !== 0 && chapterInfo.content.length !== 0)) {
const content = cpDecrypt(chapterInfo.content);
const contentRaw = document.createElement("pre");
contentRaw.innerHTML = content;
let contentText = content
.split("\n")
.map((p) => p.trim())
.join("\n\n");
let contentHTML;
const _contentHTML = document.createElement("div");
_contentHTML.innerHTML = content
.split("\n")
.map((p) => p.trim())
.map((p) => {
if (p.length === 0) {
return "<p><br/></p>";
}
else {
return `<p>${p}</p>`;
}
})
.join("\n");
if (chapterInfo.postscript === null || chapterInfo.postscript.length === 0) {
contentHTML = _contentHTML;
}
else {
contentHTML = document.createElement("div");
contentHTML.className = "main";
const hr = document.createElement("hr");
const authorSayDom = document.createElement("div");
authorSayDom.innerHTML = chapterInfo.postscript
.split("\n")
.map((p) => {
if (p.length === 0) {
return "<p><br/></p>";
}
else {
return `<p>${p}</p>`;
}
})
.join("\n");
contentHTML.appendChild(_contentHTML);
contentHTML.appendChild(hr);
contentHTML.appendChild(authorSayDom);
contentRaw.innerHTML = [
contentRaw.innerHTML,
"-".repeat(20),
chapterInfo.postscript,
].join("\n\n");
contentText = [
contentText,
"-".repeat(20),
chapterInfo.postscript,
].join("\n\n");
}
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_9__/* .sleep */ .yy)(3000 + Math.round(Math.random() * 5000));
return {
chapterName,
contentRaw,
contentText,
contentHTML,
contentImages: null,
additionalMetadate: null,
};
}
}
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
async function antiAntiCrawler() {
if (Math.random() < 0.2) {
randomWalker();
}
await (0,_lib_misc__WEBPACK_IMPORTED_MODULE_9__/* .sleep */ .yy)(3000 + Math.round(Math.random() * 4000));
}
async function publicChapter() {
await antiAntiCrawler();
return getChapter();
}
async function vipChapter() {
await antiAntiCrawler();
return getChapter();
}
if (isVIP) {
return vipChapter();
}
else {
return publicChapter();
}
}
}
/***/ }),
/***/ "./src/rules/special/original/hanwujinian.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Hanwujinian: () => (/* binding */ Hanwujinian)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("crypto-js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__("./src/lib/dom.ts");
/* harmony import */ var _lib_rule__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/rule.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _main_main__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/main/main.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules.ts");
class Hanwujinian extends _rules__WEBPACK_IMPORTED_MODULE_1__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.attachmentMode = "TM";
}
async bookParse() {
const bookUrl = document.location.href;
const anotherPageUrl = document.querySelector("a.titleText_3").href;
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_2__/* .getHtmlDOM */ .wA)(anotherPageUrl, this.charset);
const bookname = document.querySelector("span.titleText_1").innerText.trim();
const author = document.querySelector("span.authorText_1").innerText.trim();
const introDom = document.querySelector("#introtext");
const [introduction, introductionHTML] = await (0,_lib_rule__WEBPACK_IMPORTED_MODULE_3__/* .introDomHandle */ .HV)(introDom);
const coverUrl = document.querySelector(".wR_JSAS > img").src;
const additionalMetadate = {};
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_4__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((coverClass) => {
additionalMetadate.cover = coverClass;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_5___default().error(error));
}
additionalMetadate.tags = Array.from(document.querySelectorAll("div.labelBox_1 > span")).map((span) => span?.innerText.trim());
const chapters = [];
let chapterNumber = 0;
let sectionNumber = 0;
let sectionChapterNumber = 0;
let sectionName = null;
const signIn = document.querySelector("#userMeun") !== null;
const sections = doc.querySelectorAll('div.wR_JS > div.wR_JC[style*="margin: 30px auto;"]');
const divList = doc.querySelectorAll("div.wR_JS > div.wR_JC > div.wR_JSAC");
for (const divElem of Array.from(divList)) {
const aElem = divElem.querySelector("a");
const chapterName = aElem.innerText.trim();
const chapterUrl = aElem.href;
if (sections.length !== 0) {
const _sectionName = (0,_lib_rule__WEBPACK_IMPORTED_MODULE_3__/* .getSectionName */ .lq)(aElem, sections, (dom) => dom.innerText.trim());
if (_sectionName !== sectionName) {
sectionName = _sectionName;
sectionNumber++;
sectionChapterNumber = 0;
}
}
chapterNumber++;
sectionChapterNumber++;
const icon = divElem.querySelector("img");
const isVIP = icon !== null;
const isPaid = isVIP ? icon.src.includes("lock_2_off.png") : false;
const chapter = new _main_Chapter__WEBPACK_IMPORTED_MODULE_6__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber,
chapterName,
isVIP,
isPaid,
sectionName,
sectionNumber,
sectionChapterNumber,
chapterParse: this.chapterParse,
charset: this.charset,
options: { bookname },
});
if (chapter.isVIP) {
if (signIn) {
if (chapter.isPaid === false) {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_7__/* .Status */ .nW.aborted;
}
}
else {
chapter.status = _main_main__WEBPACK_IMPORTED_MODULE_7__/* .Status */ .nW.aborted;
}
}
chapters.push(chapter);
}
const book = new _main_Book__WEBPACK_IMPORTED_MODULE_8__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
book.ToCUrl = anotherPageUrl;
return book;
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const doc = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_2__/* .getHtmlDOM */ .wA)(chapterUrl, charset);
const script = Array.from(doc.querySelectorAll("script")).filter((s) => s.innerHTML.includes("var chapterContent"))?.[0];
const getContent = (CryptoJS, chapterContent) => {
function AesDecrypt(content) {
const keys = {
key: "2018122911430000",
iv: "048fe2a99140c0e6",
};
const key = CryptoJS.enc.Latin1.parse(keys.key);
const iv = CryptoJS.enc.Latin1.parse(keys.iv);
const d = CryptoJS.AES.decrypt(content, key, {
iv,
padding: CryptoJS.pad.ZeroPadding,
});
return d.toString(CryptoJS.enc.Utf8);
}
const text = decodeURI(AesDecrypt(chapterContent));
const div = document.createElement("div");
div.innerText = text;
return div;
};
if (script) {
const chapterContentLine = script.innerHTML
.split("\n")
.filter((l) => l.includes("var chapterContent"))?.[0];
const content = new Function("CryptoJS", `${chapterContentLine};return (${getContent.toString()})(CryptoJS, chapterContent);`)(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_9__/* .rm2 */ .Sf)(["更多优惠快去下载寒武纪年小说APP哦"], content);
content.innerHTML = content.innerHTML.replaceAll("%3A", ":");
content.innerHTML = content.innerHTML.replaceAll("++++【", "【");
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_10__/* .cleanDOM */ .an)(content, "TM");
return {
chapterName,
contentRaw: content,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
return {
chapterName,
contentRaw: null,
contentText: null,
contentHTML: null,
contentImages: null,
additionalMetadate: null,
};
}
}
/***/ }),
/***/ "./src/rules/special/original/ihuaben.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ ihuaben: () => (/* binding */ ihuaben)
/* harmony export */ });
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _lib_http__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./src/lib/http.ts");
/* harmony import */ var _lib_dom__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/lib/dom.ts");
class ihuaben extends _rules__WEBPACK_IMPORTED_MODULE_0__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.concurrencyLimit = 1;
this.attachmentMode = "TM";
}
async bookParse() {
const bookUrl = document.location.href;
const bookname = document.querySelector("h1.text-danger")?.innerText;
const author = document.querySelector("a.text-muted")?.innerText;
const introduction = document.querySelector("div.aboutbook")?.innerText;
const introductionHTML = document.createElement("div");
introductionHTML.innerText = introduction;
const coverUrl = document.querySelector("div.cover img")?.src;
const additionalMetadate = {
tags: Array.from(document.querySelectorAll("div.tagList a")).map((e) => e.innerText),
language: "zh",
};
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_1__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((img) => {
additionalMetadate.cover = img;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_2___default().error(error));
}
const chapternumsMatch = document.querySelector("div.chapters h2.hidden-xs a")?.innerText?.match(/\d+/);
let chapternums = chapternumsMatch ? parseInt(chapternumsMatch[0]) : 0;
chapternums = Math.ceil(chapternums / 40);
const chapterList = Array.from(getList(document));
for (let i = 2; i <= chapternums; i++) {
const url = bookUrl + "?page=" + i;
const dom = await (0,_lib_http__WEBPACK_IMPORTED_MODULE_3__/* .ggetHtmlDOM */ .pG)(url);
getList(dom).forEach((e) => chapterList.push(e));
}
let chapterNumber = 0;
const chapters = chapterList.map((c) => {
const cc = c;
const chapterUrl = cc.href;
const ChapterName = cc.innerText;
chapterNumber++;
return new _main_Chapter__WEBPACK_IMPORTED_MODULE_4__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber: chapterNumber,
chapterName: ChapterName,
isVIP: false,
isPaid: false,
sectionName: null,
sectionNumber: null,
sectionChapterNumber: null,
chapterParse: this.chapterParse,
charset: this.charset,
options: {},
});
});
return new _main_Book__WEBPACK_IMPORTED_MODULE_5__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const contentRaw = document.createElement("div");
contentRaw.innerHTML = (await (0,_lib_http__WEBPACK_IMPORTED_MODULE_3__/* .getFrameContentEvent */ .n6)(chapterUrl))?.querySelector("div.discription")?.innerHTML ?? "";
(0,_lib_dom__WEBPACK_IMPORTED_MODULE_6__.rm)("i", true, contentRaw);
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_7__/* .cleanDOM */ .an)(contentRaw, "TM");
return {
chapterName,
contentRaw,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate: null,
};
}
}
function getList(dom) {
return dom.querySelectorAll("div.chapterlist span.chapterTitle a");
}
/***/ }),
/***/ "./src/rules/special/original/iqingguo.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Iqingguo: () => (/* binding */ Iqingguo)
/* harmony export */ });
/* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/rules.ts");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("crypto-js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _main_Book__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./src/main/Book.ts");
/* harmony import */ var _lib_cleanDOM__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./src/lib/cleanDOM.ts");
/* harmony import */ var _main_Chapter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./src/main/Chapter.ts");
/* harmony import */ var _lib_attachments__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./src/lib/attachments.ts");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_log__WEBPACK_IMPORTED_MODULE_3__);
class Iqingguo extends _rules__WEBPACK_IMPORTED_MODULE_1__/* .BaseRuleClass */ .Q {
constructor() {
super();
this.concurrencyLimit = 2;
this.attachmentMode = "TM";
}
async bookParse() {
const bookId = new URLSearchParams(document.location.search).get("id");
if (!bookId) {
throw new Error("无法找到 bookId!");
}
const bookPath = `/v1/books/${bookId}/cover`;
const catalogPath = `/v1/books/${bookId}/catalog`;
const bookData = (await get(bookPath))
.cover;
const catalogData = await get(catalogPath);
const bookUrl = document.location.href;
const bookname = bookData.name;
const author = bookData.user.author;
const introduction = bookData.description;
const introductionHTML = document.createElement("div");
introductionHTML.innerText = introduction;
const coverUrl = bookData.url;
const additionalMetadate = {
lastModified: bookData.latestModified,
tags: [bookData.genre, bookData.subGenre],
language: "zh",
ids: bookId,
};
if (coverUrl) {
(0,_lib_attachments__WEBPACK_IMPORTED_MODULE_2__/* .getAttachment */ ["if"])(coverUrl, this.attachmentMode, "cover-")
.then((img) => {
additionalMetadate.cover = img;
})
.catch((error) => _log__WEBPACK_IMPORTED_MODULE_3___default().error(error));
}
const chapters = catalogData.map((c) => {
const chapterUrl = "https://www.iqingguo.com/book/reading?" +
new URLSearchParams({ id: bookId, cid: c.id }).toString();
return new _main_Chapter__WEBPACK_IMPORTED_MODULE_4__/* .Chapter */ .I({
bookUrl,
bookname,
chapterUrl,
chapterNumber: c.sn,
chapterName: c.name,
isVIP: false,
isPaid: false,
sectionName: null,
sectionNumber: null,
sectionChapterNumber: null,
chapterParse: this.chapterParse,
charset: this.charset,
options: {
bookId,
chapterId: c.id,
},
});
});
return new _main_Book__WEBPACK_IMPORTED_MODULE_5__/* .Book */ .E({
bookUrl,
bookname,
author,
introduction,
introductionHTML,
additionalMetadate,
chapters,
});
}
async chapterParse(chapterUrl, chapterName, isVIP, isPaid, charset, options) {
const chapterPath = `/v1/chapters/${options.chapterId}`;
const data = await get(chapterPath);
chapterName = data.name;
const contentRaw = document.createElement("div");
contentRaw.innerText = data.content;
const { dom, text, images } = await (0,_lib_cleanDOM__WEBPACK_IMPORTED_MODULE_6__/* .cleanDOM */ .an)(contentRaw, "TM");
const additionalMetadate = {
lastModified: data.updateTime,
};
return {
chapterName,
contentRaw,
contentText: text,
contentHTML: dom,
contentImages: images,
additionalMetadate,
};
}
}
function sign(path, params) {
params = params ?? {};
Object.assign(params, {
packageName: "com.iqingoo.reader.web",
t: Math.ceil(new Date().getTime() / 1e3),
});
const orderd = Object.keys(params)
.sort()
.reduce((obj, key) => {
obj[key] = params[key];
return obj;
}, {});
const l = path + "?" + new URLSearchParams(orderd).toString();
orderd.sign = crypto_js__WEBPACK_IMPORTED_MODULE_0__.MD5(decodeURI(l)).toString(crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Hex);
return orderd;
}
async function get(path, params) {
const origin = "https://iqg-api.qingoo.cn";
const parm = sign(path, params);
const url = origin + path + "?" + new URLSearchParams(parm).toString();
const resp = await fetch(url, {
headers: {
accept: "application/json, text/plain, */*",
},
method: "GET",
mode: "cors",
credentials: "include",
});
const _data = (await resp.json());
if (_data.code !== 200) {
throw new Error("请求出错! " + url);
}
return _data.data;
}
/***/ }),
/***/ "./src/rules/special/original/jjwxc.ts":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
Jjwxc: () => (/* binding */ Jjwxc)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/generator/token-before.js
var token_before_namespaceObject = {};
__webpack_require__.r(token_before_namespaceObject);
__webpack_require__.d(token_before_namespaceObject, {
safe: () => (safe),
spec: () => (spec)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/lexer/units.js
var units_namespaceObject = {};
__webpack_require__.r(units_namespaceObject);
__webpack_require__.d(units_namespaceObject, {
angle: () => (angle),
decibel: () => (decibel),
flex: () => (flex),
frequency: () => (frequency),
length: () => (units_length),
resolution: () => (resolution),
semitones: () => (semitones),
time: () => (time)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/lexer/trace.js
var trace_namespaceObject = {};
__webpack_require__.r(trace_namespaceObject);
__webpack_require__.d(trace_namespaceObject, {
getTrace: () => (getTrace),
isKeyword: () => (isKeyword),
isProperty: () => (isProperty),
isType: () => (isType)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/AnPlusB.js
var AnPlusB_namespaceObject = {};
__webpack_require__.r(AnPlusB_namespaceObject);
__webpack_require__.d(AnPlusB_namespaceObject, {
generate: () => (AnPlusB_generate),
name: () => (AnPlusB_name),
parse: () => (AnPlusB_parse),
structure: () => (structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Atrule.js
var Atrule_namespaceObject = {};
__webpack_require__.r(Atrule_namespaceObject);
__webpack_require__.d(Atrule_namespaceObject, {
generate: () => (Atrule_generate),
name: () => (Atrule_name),
parse: () => (Atrule_parse),
structure: () => (Atrule_structure),
walkContext: () => (walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/AtrulePrelude.js
var AtrulePrelude_namespaceObject = {};
__webpack_require__.r(AtrulePrelude_namespaceObject);
__webpack_require__.d(AtrulePrelude_namespaceObject, {
generate: () => (AtrulePrelude_generate),
name: () => (AtrulePrelude_name),
parse: () => (AtrulePrelude_parse),
structure: () => (AtrulePrelude_structure),
walkContext: () => (AtrulePrelude_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/AttributeSelector.js
var AttributeSelector_namespaceObject = {};
__webpack_require__.r(AttributeSelector_namespaceObject);
__webpack_require__.d(AttributeSelector_namespaceObject, {
generate: () => (AttributeSelector_generate),
name: () => (AttributeSelector_name),
parse: () => (AttributeSelector_parse),
structure: () => (AttributeSelector_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Block.js
var Block_namespaceObject = {};
__webpack_require__.r(Block_namespaceObject);
__webpack_require__.d(Block_namespaceObject, {
generate: () => (Block_generate),
name: () => (Block_name),
parse: () => (Block_parse),
structure: () => (Block_structure),
walkContext: () => (Block_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Brackets.js
var Brackets_namespaceObject = {};
__webpack_require__.r(Brackets_namespaceObject);
__webpack_require__.d(Brackets_namespaceObject, {
generate: () => (Brackets_generate),
name: () => (Brackets_name),
parse: () => (Brackets_parse),
structure: () => (Brackets_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/CDC.js
var CDC_namespaceObject = {};
__webpack_require__.r(CDC_namespaceObject);
__webpack_require__.d(CDC_namespaceObject, {
generate: () => (CDC_generate),
name: () => (CDC_name),
parse: () => (CDC_parse),
structure: () => (CDC_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/CDO.js
var CDO_namespaceObject = {};
__webpack_require__.r(CDO_namespaceObject);
__webpack_require__.d(CDO_namespaceObject, {
generate: () => (CDO_generate),
name: () => (CDO_name),
parse: () => (CDO_parse),
structure: () => (CDO_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/ClassSelector.js
var ClassSelector_namespaceObject = {};
__webpack_require__.r(ClassSelector_namespaceObject);
__webpack_require__.d(ClassSelector_namespaceObject, {
generate: () => (ClassSelector_generate),
name: () => (ClassSelector_name),
parse: () => (ClassSelector_parse),
structure: () => (ClassSelector_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Combinator.js
var Combinator_namespaceObject = {};
__webpack_require__.r(Combinator_namespaceObject);
__webpack_require__.d(Combinator_namespaceObject, {
generate: () => (Combinator_generate),
name: () => (Combinator_name),
parse: () => (Combinator_parse),
structure: () => (Combinator_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Comment.js
var Comment_namespaceObject = {};
__webpack_require__.r(Comment_namespaceObject);
__webpack_require__.d(Comment_namespaceObject, {
generate: () => (Comment_generate),
name: () => (Comment_name),
parse: () => (Comment_parse),
structure: () => (Comment_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Declaration.js
var Declaration_namespaceObject = {};
__webpack_require__.r(Declaration_namespaceObject);
__webpack_require__.d(Declaration_namespaceObject, {
generate: () => (Declaration_generate),
name: () => (Declaration_name),
parse: () => (Declaration_parse),
structure: () => (Declaration_structure),
walkContext: () => (Declaration_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/DeclarationList.js
var DeclarationList_namespaceObject = {};
__webpack_require__.r(DeclarationList_namespaceObject);
__webpack_require__.d(DeclarationList_namespaceObject, {
generate: () => (DeclarationList_generate),
name: () => (DeclarationList_name),
parse: () => (DeclarationList_parse),
structure: () => (DeclarationList_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Dimension.js
var Dimension_namespaceObject = {};
__webpack_require__.r(Dimension_namespaceObject);
__webpack_require__.d(Dimension_namespaceObject, {
generate: () => (Dimension_generate),
name: () => (Dimension_name),
parse: () => (Dimension_parse),
structure: () => (Dimension_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Function.js
var Function_namespaceObject = {};
__webpack_require__.r(Function_namespaceObject);
__webpack_require__.d(Function_namespaceObject, {
generate: () => (Function_generate),
name: () => (Function_name),
parse: () => (Function_parse),
structure: () => (Function_structure),
walkContext: () => (Function_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Hash.js
var Hash_namespaceObject = {};
__webpack_require__.r(Hash_namespaceObject);
__webpack_require__.d(Hash_namespaceObject, {
generate: () => (Hash_generate),
name: () => (Hash_name),
parse: () => (Hash_parse),
structure: () => (Hash_structure),
xxx: () => (xxx)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Identifier.js
var Identifier_namespaceObject = {};
__webpack_require__.r(Identifier_namespaceObject);
__webpack_require__.d(Identifier_namespaceObject, {
generate: () => (Identifier_generate),
name: () => (Identifier_name),
parse: () => (Identifier_parse),
structure: () => (Identifier_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/IdSelector.js
var IdSelector_namespaceObject = {};
__webpack_require__.r(IdSelector_namespaceObject);
__webpack_require__.d(IdSelector_namespaceObject, {
generate: () => (IdSelector_generate),
name: () => (IdSelector_name),
parse: () => (IdSelector_parse),
structure: () => (IdSelector_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/MediaFeature.js
var MediaFeature_namespaceObject = {};
__webpack_require__.r(MediaFeature_namespaceObject);
__webpack_require__.d(MediaFeature_namespaceObject, {
generate: () => (MediaFeature_generate),
name: () => (MediaFeature_name),
parse: () => (MediaFeature_parse),
structure: () => (MediaFeature_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/MediaQuery.js
var MediaQuery_namespaceObject = {};
__webpack_require__.r(MediaQuery_namespaceObject);
__webpack_require__.d(MediaQuery_namespaceObject, {
generate: () => (MediaQuery_generate),
name: () => (MediaQuery_name),
parse: () => (MediaQuery_parse),
structure: () => (MediaQuery_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/MediaQueryList.js
var MediaQueryList_namespaceObject = {};
__webpack_require__.r(MediaQueryList_namespaceObject);
__webpack_require__.d(MediaQueryList_namespaceObject, {
generate: () => (MediaQueryList_generate),
name: () => (MediaQueryList_name),
parse: () => (MediaQueryList_parse),
structure: () => (MediaQueryList_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/NestingSelector.js
var NestingSelector_namespaceObject = {};
__webpack_require__.r(NestingSelector_namespaceObject);
__webpack_require__.d(NestingSelector_namespaceObject, {
generate: () => (NestingSelector_generate),
name: () => (NestingSelector_name),
parse: () => (NestingSelector_parse),
structure: () => (NestingSelector_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Nth.js
var Nth_namespaceObject = {};
__webpack_require__.r(Nth_namespaceObject);
__webpack_require__.d(Nth_namespaceObject, {
generate: () => (Nth_generate),
name: () => (Nth_name),
parse: () => (Nth_parse),
structure: () => (Nth_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Number.js
var Number_namespaceObject = {};
__webpack_require__.r(Number_namespaceObject);
__webpack_require__.d(Number_namespaceObject, {
generate: () => (Number_generate),
name: () => (Number_name),
parse: () => (Number_parse),
structure: () => (Number_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Operator.js
var Operator_namespaceObject = {};
__webpack_require__.r(Operator_namespaceObject);
__webpack_require__.d(Operator_namespaceObject, {
generate: () => (Operator_generate),
name: () => (Operator_name),
parse: () => (Operator_parse),
structure: () => (Operator_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Parentheses.js
var Parentheses_namespaceObject = {};
__webpack_require__.r(Parentheses_namespaceObject);
__webpack_require__.d(Parentheses_namespaceObject, {
generate: () => (Parentheses_generate),
name: () => (Parentheses_name),
parse: () => (Parentheses_parse),
structure: () => (Parentheses_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Percentage.js
var Percentage_namespaceObject = {};
__webpack_require__.r(Percentage_namespaceObject);
__webpack_require__.d(Percentage_namespaceObject, {
generate: () => (Percentage_generate),
name: () => (Percentage_name),
parse: () => (Percentage_parse),
structure: () => (Percentage_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/PseudoClassSelector.js
var PseudoClassSelector_namespaceObject = {};
__webpack_require__.r(PseudoClassSelector_namespaceObject);
__webpack_require__.d(PseudoClassSelector_namespaceObject, {
generate: () => (PseudoClassSelector_generate),
name: () => (PseudoClassSelector_name),
parse: () => (PseudoClassSelector_parse),
structure: () => (PseudoClassSelector_structure),
walkContext: () => (PseudoClassSelector_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/PseudoElementSelector.js
var PseudoElementSelector_namespaceObject = {};
__webpack_require__.r(PseudoElementSelector_namespaceObject);
__webpack_require__.d(PseudoElementSelector_namespaceObject, {
generate: () => (PseudoElementSelector_generate),
name: () => (PseudoElementSelector_name),
parse: () => (PseudoElementSelector_parse),
structure: () => (PseudoElementSelector_structure),
walkContext: () => (PseudoElementSelector_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Ratio.js
var Ratio_namespaceObject = {};
__webpack_require__.r(Ratio_namespaceObject);
__webpack_require__.d(Ratio_namespaceObject, {
generate: () => (Ratio_generate),
name: () => (Ratio_name),
parse: () => (Ratio_parse),
structure: () => (Ratio_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Raw.js
var Raw_namespaceObject = {};
__webpack_require__.r(Raw_namespaceObject);
__webpack_require__.d(Raw_namespaceObject, {
generate: () => (Raw_generate),
name: () => (Raw_name),
parse: () => (Raw_parse),
structure: () => (Raw_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Rule.js
var Rule_namespaceObject = {};
__webpack_require__.r(Rule_namespaceObject);
__webpack_require__.d(Rule_namespaceObject, {
generate: () => (Rule_generate),
name: () => (Rule_name),
parse: () => (Rule_parse),
structure: () => (Rule_structure),
walkContext: () => (Rule_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Selector.js
var Selector_namespaceObject = {};
__webpack_require__.r(Selector_namespaceObject);
__webpack_require__.d(Selector_namespaceObject, {
generate: () => (Selector_generate),
name: () => (Selector_name),
parse: () => (Selector_parse),
structure: () => (Selector_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/SelectorList.js
var SelectorList_namespaceObject = {};
__webpack_require__.r(SelectorList_namespaceObject);
__webpack_require__.d(SelectorList_namespaceObject, {
generate: () => (SelectorList_generate),
name: () => (SelectorList_name),
parse: () => (SelectorList_parse),
structure: () => (SelectorList_structure),
walkContext: () => (SelectorList_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/String.js
var String_namespaceObject = {};
__webpack_require__.r(String_namespaceObject);
__webpack_require__.d(String_namespaceObject, {
generate: () => (String_generate),
name: () => (String_name),
parse: () => (String_parse),
structure: () => (String_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/StyleSheet.js
var StyleSheet_namespaceObject = {};
__webpack_require__.r(StyleSheet_namespaceObject);
__webpack_require__.d(StyleSheet_namespaceObject, {
generate: () => (StyleSheet_generate),
name: () => (StyleSheet_name),
parse: () => (StyleSheet_parse),
structure: () => (StyleSheet_structure),
walkContext: () => (StyleSheet_walkContext)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/TypeSelector.js
var TypeSelector_namespaceObject = {};
__webpack_require__.r(TypeSelector_namespaceObject);
__webpack_require__.d(TypeSelector_namespaceObject, {
generate: () => (TypeSelector_generate),
name: () => (TypeSelector_name),
parse: () => (TypeSelector_parse),
structure: () => (TypeSelector_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/UnicodeRange.js
var UnicodeRange_namespaceObject = {};
__webpack_require__.r(UnicodeRange_namespaceObject);
__webpack_require__.d(UnicodeRange_namespaceObject, {
generate: () => (UnicodeRange_generate),
name: () => (UnicodeRange_name),
parse: () => (UnicodeRange_parse),
structure: () => (UnicodeRange_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Url.js
var Url_namespaceObject = {};
__webpack_require__.r(Url_namespaceObject);
__webpack_require__.d(Url_namespaceObject, {
generate: () => (Url_generate),
name: () => (Url_name),
parse: () => (Url_parse),
structure: () => (Url_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/Value.js
var Value_namespaceObject = {};
__webpack_require__.r(Value_namespaceObject);
__webpack_require__.d(Value_namespaceObject, {
generate: () => (Value_generate),
name: () => (Value_name),
parse: () => (Value_parse),
structure: () => (Value_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/WhiteSpace.js
var WhiteSpace_namespaceObject = {};
__webpack_require__.r(WhiteSpace_namespaceObject);
__webpack_require__.d(WhiteSpace_namespaceObject, {
generate: () => (WhiteSpace_generate),
name: () => (WhiteSpace_name),
parse: () => (WhiteSpace_parse),
structure: () => (WhiteSpace_structure)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/index.js
var node_namespaceObject = {};
__webpack_require__.r(node_namespaceObject);
__webpack_require__.d(node_namespaceObject, {
AnPlusB: () => (AnPlusB_namespaceObject),
Atrule: () => (Atrule_namespaceObject),
AtrulePrelude: () => (AtrulePrelude_namespaceObject),
AttributeSelector: () => (AttributeSelector_namespaceObject),
Block: () => (Block_namespaceObject),
Brackets: () => (Brackets_namespaceObject),
CDC: () => (CDC_namespaceObject),
CDO: () => (CDO_namespaceObject),
ClassSelector: () => (ClassSelector_namespaceObject),
Combinator: () => (Combinator_namespaceObject),
Comment: () => (Comment_namespaceObject),
Declaration: () => (Declaration_namespaceObject),
DeclarationList: () => (DeclarationList_namespaceObject),
Dimension: () => (Dimension_namespaceObject),
Function: () => (Function_namespaceObject),
Hash: () => (Hash_namespaceObject),
IdSelector: () => (IdSelector_namespaceObject),
Identifier: () => (Identifier_namespaceObject),
MediaFeature: () => (MediaFeature_namespaceObject),
MediaQuery: () => (MediaQuery_namespaceObject),
MediaQueryList: () => (MediaQueryList_namespaceObject),
NestingSelector: () => (NestingSelector_namespaceObject),
Nth: () => (Nth_namespaceObject),
Number: () => (Number_namespaceObject),
Operator: () => (Operator_namespaceObject),
Parentheses: () => (Parentheses_namespaceObject),
Percentage: () => (Percentage_namespaceObject),
PseudoClassSelector: () => (PseudoClassSelector_namespaceObject),
PseudoElementSelector: () => (PseudoElementSelector_namespaceObject),
Ratio: () => (Ratio_namespaceObject),
Raw: () => (Raw_namespaceObject),
Rule: () => (Rule_namespaceObject),
Selector: () => (Selector_namespaceObject),
SelectorList: () => (SelectorList_namespaceObject),
String: () => (String_namespaceObject),
StyleSheet: () => (StyleSheet_namespaceObject),
TypeSelector: () => (TypeSelector_namespaceObject),
UnicodeRange: () => (UnicodeRange_namespaceObject),
Url: () => (Url_namespaceObject),
Value: () => (Value_namespaceObject),
WhiteSpace: () => (WhiteSpace_namespaceObject)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/scope/index.js
var scope_namespaceObject = {};
__webpack_require__.r(scope_namespaceObject);
__webpack_require__.d(scope_namespaceObject, {
AtrulePrelude: () => (atrulePrelude),
Selector: () => (selector),
Value: () => (value)
});
// NAMESPACE OBJECT: ./node_modules/css-tree/lib/syntax/node/index-parse.js
var index_parse_namespaceObject = {};
__webpack_require__.r(index_parse_namespaceObject);
__webpack_require__.d(index_parse_namespaceObject, {
AnPlusB: () => (AnPlusB_parse),
Atrule: () => (Atrule_parse),
AtrulePrelude: () => (AtrulePrelude_parse),
AttributeSelector: () => (AttributeSelector_parse),
Block: () => (Block_parse),
Brackets: () => (Brackets_parse),
CDC: () => (CDC_parse),
CDO: () => (CDO_parse),
ClassSelector: () => (ClassSelector_parse),
Combinator: () => (Combinator_parse),
Comment: () => (Comment_parse),
Declaration: () => (Declaration_parse),
DeclarationList: () => (DeclarationList_parse),
Dimension: () => (Dimension_parse),
Function: () => (Function_parse),
Hash: () => (Hash_parse),
IdSelector: () => (IdSelector_parse),
Identifier: () => (Identifier_parse),
MediaFeature: () => (MediaFeature_parse),
MediaQuery: () => (MediaQuery_parse),
MediaQueryList: () => (MediaQueryList_parse),
NestingSelector: () => (NestingSelector_parse),
Nth: () => (Nth_parse),
Number: () => (Number_parse),
Operator: () => (Operator_parse),
Parentheses: () => (Parentheses_parse),
Percentage: () => (Percentage_parse),
PseudoClassSelector: () => (PseudoClassSelector_parse),
PseudoElementSelector: () => (PseudoElementSelector_parse),
Ratio: () => (Ratio_parse),
Raw: () => (Raw_parse),
Rule: () => (Rule_parse),
Selector: () => (Selector_parse),
SelectorList: () => (SelectorList_parse),
String: () => (String_parse),
StyleSheet: () => (StyleSheet_parse),
TypeSelector: () => (TypeSelector_parse),
UnicodeRange: () => (UnicodeRange_parse),
Url: () => (Url_parse),
Value: () => (Value_parse),
WhiteSpace: () => (WhiteSpace_parse)
});
// EXTERNAL MODULE: ./src/lib/attachments.ts
var attachments = __webpack_require__("./src/lib/attachments.ts");
// EXTERNAL MODULE: ./src/lib/cleanDOM.ts
var cleanDOM = __webpack_require__("./src/lib/cleanDOM.ts");
// EXTERNAL MODULE: ./src/lib/http.ts
var http = __webpack_require__("./src/lib/http.ts");
// EXTERNAL MODULE: ./src/lib/misc.ts
var misc = __webpack_require__("./src/lib/misc.ts");
// EXTERNAL MODULE: ./src/lib/dom.ts
var lib_dom = __webpack_require__("./src/lib/dom.ts");
// EXTERNAL MODULE: ./src/lib/rule.ts
var rule = __webpack_require__("./src/lib/rule.ts");
// EXTERNAL MODULE: ./node_modules/loglevel/lib/loglevel.js
var loglevel = __webpack_require__("./node_modules/loglevel/lib/loglevel.js");
var loglevel_default = /*#__PURE__*/__webpack_require__.n(loglevel);
// EXTERNAL MODULE: ./src/main/main.ts
var main = __webpack_require__("./src/main/main.ts");
// EXTERNAL MODULE: ./src/main/Attachment.ts
var Attachment = __webpack_require__("./src/main/Attachment.ts");
// EXTERNAL MODULE: ./src/main/Chapter.ts
var Chapter = __webpack_require__("./src/main/Chapter.ts");
// EXTERNAL MODULE: ./src/main/Book.ts + 1 modules
var Book = __webpack_require__("./src/main/Book.ts");
// EXTERNAL MODULE: ./src/rules.ts + 12 modules
var rules = __webpack_require__("./src/rules.ts");
// EXTERNAL MODULE: ./src/setting.ts
var setting = __webpack_require__("./src/setting.ts");
;// ./src/rules/lib/jjwxcFontDecode.ts
async function replaceJjwxcCharacter(fontName, inputText) {
let outputText = inputText;
const jjwxcFontTable = await getJjwxcFontTable(fontName);
if (jjwxcFontTable) {
for (const jjwxcCharacter in jjwxcFontTable) {
if (Object.prototype.hasOwnProperty.call(jjwxcFontTable, jjwxcCharacter)) {
const normalCharacter = jjwxcFontTable[jjwxcCharacter];
outputText = outputText.replaceAll(jjwxcCharacter, normalCharacter);
}
}
outputText = outputText.replace(/\u200c/g, "");
}
return outputText;
}
async function getJjwxcFontTable(fontName) {
const jjwxcFontTableLocal = false;
if (jjwxcFontTableLocal) {
return jjwxcFontTableLocal;
}
else if (setting/* enableJjwxcRemoteFont */.ts) {
return await fetchRemoteFont(fontName);
}
else {
return undefined;
}
}
async function fetchRemoteFont(fontName) {
const url = `https://fastly.jsdelivr.net/gh/404-novel-project/jinjiang_font_tables@master/${fontName}.woff2.json`;
const fontlink = `https://static.jjwxc.net/tmp/fonts/${fontName}.woff2?h=my.jjwxc.net`;
loglevel_default().info(`[jjwxc-font]开始请求远程字体对照表 ${fontName}`);
let retry = setting/* retryLimit */.Iz;
while (retry > 0) {
let resp;
try {
resp = await fetch(url);
}
catch (error) {
loglevel_default().error(error);
retry--;
if (retry > 0) {
await (0,misc/* sleep */.yy)(5000);
continue;
}
else {
loglevel_default().error(`[jjwxc-font]远程字体对照表 ${fontName} 下载失败,请前往https://github.com/404-novel-project/jinjiang_font_tables 提交字体链接, ${fontlink}`);
return undefined;
}
}
if (resp.ok) {
loglevel_default().info(`[jjwxc-font]远程字体对照表 ${fontName} 下载成功`);
loglevel_default().debug(`[jjwxc-font]如果你认为字体对应有错误,请前往https://github.com/404-novel-project/jinjiang_font_tables 重新提交字体链接, ${fontlink}`);
return (await resp.json());
}
else {
retry--;
if (resp.status === 404 || retry <= 0) {
loglevel_default().error(`[jjwxc-font]远程字体对照表 ${fontName} 下载失败,请前往https://github.com/404-novel-project/jinjiang_font_tables 提交字体链接, ${fontlink}`);
return undefined;
}
else {
await (0,misc/* sleep */.yy)(5000);
}
}
}
}
// EXTERNAL MODULE: ./src/lib/GM.ts
var GM = __webpack_require__("./src/lib/GM.ts");
;// ./node_modules/css-tree/lib/tokenizer/types.js
// CSS Syntax Module Level 3
// https://www.w3.org/TR/css-syntax-3/
const EOF = 0; // <EOF-token>
const Ident = 1; // <ident-token>
const Function = 2; // <function-token>
const AtKeyword = 3; // <at-keyword-token>
const Hash = 4; // <hash-token>
const types_String = 5; // <string-token>
const BadString = 6; // <bad-string-token>
const Url = 7; // <url-token>
const BadUrl = 8; // <bad-url-token>
const Delim = 9; // <delim-token>
const types_Number = 10; // <number-token>
const Percentage = 11; // <percentage-token>
const Dimension = 12; // <dimension-token>
const WhiteSpace = 13; // <whitespace-token>
const CDO = 14; // <CDO-token>
const CDC = 15; // <CDC-token>
const Colon = 16; // <colon-token> :
const Semicolon = 17; // <semicolon-token> ;
const Comma = 18; // <comma-token> ,
const LeftSquareBracket = 19; // <[-token>
const RightSquareBracket = 20; // <]-token>
const LeftParenthesis = 21; // <(-token>
const RightParenthesis = 22; // <)-token>
const LeftCurlyBracket = 23; // <{-token>
const RightCurlyBracket = 24; // <}-token>
const Comment = 25;
;// ./node_modules/css-tree/lib/tokenizer/char-code-definitions.js
const char_code_definitions_EOF = 0;
// https://drafts.csswg.org/css-syntax-3/
// § 4.2. Definitions
// digit
// A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9).
function isDigit(code) {
return code >= 0x0030 && code <= 0x0039;
}
// hex digit
// A digit, or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F),
// or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f).
function isHexDigit(code) {
return (
isDigit(code) || // 0 .. 9
(code >= 0x0041 && code <= 0x0046) || // A .. F
(code >= 0x0061 && code <= 0x0066) // a .. f
);
}
// uppercase letter
// A code point between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z).
function isUppercaseLetter(code) {
return code >= 0x0041 && code <= 0x005A;
}
// lowercase letter
// A code point between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z).
function isLowercaseLetter(code) {
return code >= 0x0061 && code <= 0x007A;
}
// letter
// An uppercase letter or a lowercase letter.
function isLetter(code) {
return isUppercaseLetter(code) || isLowercaseLetter(code);
}
// non-ASCII code point
// A code point with a value equal to or greater than U+0080 <control>.
function isNonAscii(code) {
return code >= 0x0080;
}
// name-start code point
// A letter, a non-ASCII code point, or U+005F LOW LINE (_).
function isNameStart(code) {
return isLetter(code) || isNonAscii(code) || code === 0x005F;
}
// name code point
// A name-start code point, a digit, or U+002D HYPHEN-MINUS (-).
function char_code_definitions_isName(code) {
return isNameStart(code) || isDigit(code) || code === 0x002D;
}
// non-printable code point
// A code point between U+0000 NULL and U+0008 BACKSPACE, or U+000B LINE TABULATION,
// or a code point between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE, or U+007F DELETE.
function isNonPrintable(code) {
return (
(code >= 0x0000 && code <= 0x0008) ||
(code === 0x000B) ||
(code >= 0x000E && code <= 0x001F) ||
(code === 0x007F)
);
}
// newline
// U+000A LINE FEED. Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition,
// as they are converted to U+000A LINE FEED during preprocessing.
// TODO: we doesn't do a preprocessing, so check a code point for U+000D CARRIAGE RETURN and U+000C FORM FEED
function isNewline(code) {
return code === 0x000A || code === 0x000D || code === 0x000C;
}
// whitespace
// A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
function isWhiteSpace(code) {
return isNewline(code) || code === 0x0020 || code === 0x0009;
}
// § 4.3.8. Check if two code points are a valid escape
function char_code_definitions_isValidEscape(first, second) {
// If the first code point is not U+005C REVERSE SOLIDUS (\), return false.
if (first !== 0x005C) {
return false;
}
// Otherwise, if the second code point is a newline or EOF, return false.
if (isNewline(second) || second === char_code_definitions_EOF) {
return false;
}
// Otherwise, return true.
return true;
}
// § 4.3.9. Check if three code points would start an identifier
function isIdentifierStart(first, second, third) {
// Look at the first code point:
// U+002D HYPHEN-MINUS
if (first === 0x002D) {
// If the second code point is a name-start code point or a U+002D HYPHEN-MINUS,
// or the second and third code points are a valid escape, return true. Otherwise, return false.
return (
isNameStart(second) ||
second === 0x002D ||
char_code_definitions_isValidEscape(second, third)
);
}
// name-start code point
if (isNameStart(first)) {
// Return true.
return true;
}
// U+005C REVERSE SOLIDUS (\)
if (first === 0x005C) {
// If the first and second code points are a valid escape, return true. Otherwise, return false.
return char_code_definitions_isValidEscape(first, second);
}
// anything else
// Return false.
return false;
}
// § 4.3.10. Check if three code points would start a number
function isNumberStart(first, second, third) {
// Look at the first code point:
// U+002B PLUS SIGN (+)
// U+002D HYPHEN-MINUS (-)
if (first === 0x002B || first === 0x002D) {
// If the second code point is a digit, return true.
if (isDigit(second)) {
return 2;
}
// Otherwise, if the second code point is a U+002E FULL STOP (.)
// and the third code point is a digit, return true.
// Otherwise, return false.
return second === 0x002E && isDigit(third) ? 3 : 0;
}
// U+002E FULL STOP (.)
if (first === 0x002E) {
// If the second code point is a digit, return true. Otherwise, return false.
return isDigit(second) ? 2 : 0;
}
// digit
if (isDigit(first)) {
// Return true.
return 1;
}
// anything else
// Return false.
return 0;
}
//
// Misc
//
// detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
function isBOM(code) {
// UTF-16BE
if (code === 0xFEFF) {
return 1;
}
// UTF-16LE
if (code === 0xFFFE) {
return 1;
}
return 0;
}
// Fast code category
// Only ASCII code points has a special meaning, that's why we define a maps for 0..127 codes only
const CATEGORY = new Array(0x80);
const EofCategory = 0x80;
const WhiteSpaceCategory = 0x82;
const DigitCategory = 0x83;
const NameStartCategory = 0x84;
const NonPrintableCategory = 0x85;
for (let i = 0; i < CATEGORY.length; i++) {
CATEGORY[i] =
isWhiteSpace(i) && WhiteSpaceCategory ||
isDigit(i) && DigitCategory ||
isNameStart(i) && NameStartCategory ||
isNonPrintable(i) && NonPrintableCategory ||
i || EofCategory;
}
function charCodeCategory(code) {
return code < 0x80 ? CATEGORY[code] : NameStartCategory;
}
;// ./node_modules/css-tree/lib/tokenizer/utils.js
function getCharCode(source, offset) {
return offset < source.length ? source.charCodeAt(offset) : 0;
}
function getNewlineLength(source, offset, code) {
if (code === 13 /* \r */ && getCharCode(source, offset + 1) === 10 /* \n */) {
return 2;
}
return 1;
}
function cmpChar(testStr, offset, referenceCode) {
let code = testStr.charCodeAt(offset);
// code.toLowerCase() for A..Z
if (isUppercaseLetter(code)) {
code = code | 32;
}
return code === referenceCode;
}
function cmpStr(testStr, start, end, referenceStr) {
if (end - start !== referenceStr.length) {
return false;
}
if (start < 0 || end > testStr.length) {
return false;
}
for (let i = start; i < end; i++) {
const referenceCode = referenceStr.charCodeAt(i - start);
let testCode = testStr.charCodeAt(i);
// testCode.toLowerCase() for A..Z
if (isUppercaseLetter(testCode)) {
testCode = testCode | 32;
}
if (testCode !== referenceCode) {
return false;
}
}
return true;
}
function findWhiteSpaceStart(source, offset) {
for (; offset >= 0; offset--) {
if (!isWhiteSpace(source.charCodeAt(offset))) {
break;
}
}
return offset + 1;
}
function findWhiteSpaceEnd(source, offset) {
for (; offset < source.length; offset++) {
if (!isWhiteSpace(source.charCodeAt(offset))) {
break;
}
}
return offset;
}
function findDecimalNumberEnd(source, offset) {
for (; offset < source.length; offset++) {
if (!isDigit(source.charCodeAt(offset))) {
break;
}
}
return offset;
}
// § 4.3.7. Consume an escaped code point
function utils_consumeEscaped(source, offset) {
// It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and
// that the next input code point has already been verified to be part of a valid escape.
offset += 2;
// hex digit
if (isHexDigit(getCharCode(source, offset - 1))) {
// Consume as many hex digits as possible, but no more than 5.
// Note that this means 1-6 hex digits have been consumed in total.
for (const maxOffset = Math.min(source.length, offset + 5); offset < maxOffset; offset++) {
if (!isHexDigit(getCharCode(source, offset))) {
break;
}
}
// If the next input code point is whitespace, consume it as well.
const code = getCharCode(source, offset);
if (isWhiteSpace(code)) {
offset += getNewlineLength(source, offset, code);
}
}
return offset;
}
// §4.3.11. Consume a name
// Note: This algorithm does not do the verification of the first few code points that are necessary
// to ensure the returned code points would constitute an <ident-token>. If that is the intended use,
// ensure that the stream starts with an identifier before calling this algorithm.
function consumeName(source, offset) {
// Let result initially be an empty string.
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
// name code point
if (char_code_definitions_isName(code)) {
// Append the code point to result.
continue;
}
// the stream starts with a valid escape
if (char_code_definitions_isValidEscape(code, getCharCode(source, offset + 1))) {
// Consume an escaped code point. Append the returned code point to result.
offset = utils_consumeEscaped(source, offset) - 1;
continue;
}
// anything else
// Reconsume the current input code point. Return result.
break;
}
return offset;
}
// §4.3.12. Consume a number
function consumeNumber(source, offset) {
let code = source.charCodeAt(offset);
// 2. If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-),
// consume it and append it to repr.
if (code === 0x002B || code === 0x002D) {
code = source.charCodeAt(offset += 1);
}
// 3. While the next input code point is a digit, consume it and append it to repr.
if (isDigit(code)) {
offset = findDecimalNumberEnd(source, offset + 1);
code = source.charCodeAt(offset);
}
// 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then:
if (code === 0x002E && isDigit(source.charCodeAt(offset + 1))) {
// 4.1 Consume them.
// 4.2 Append them to repr.
offset += 2;
// 4.3 Set type to "number".
// TODO
// 4.4 While the next input code point is a digit, consume it and append it to repr.
offset = findDecimalNumberEnd(source, offset);
}
// 5. If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E)
// or U+0065 LATIN SMALL LETTER E (e), ... , followed by a digit, then:
if (cmpChar(source, offset, 101 /* e */)) {
let sign = 0;
code = source.charCodeAt(offset + 1);
// ... optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+) ...
if (code === 0x002D || code === 0x002B) {
sign = 1;
code = source.charCodeAt(offset + 2);
}
// ... followed by a digit
if (isDigit(code)) {
// 5.1 Consume them.
// 5.2 Append them to repr.
// 5.3 Set type to "number".
// TODO
// 5.4 While the next input code point is a digit, consume it and append it to repr.
offset = findDecimalNumberEnd(source, offset + 1 + sign + 1);
}
}
return offset;
}
// § 4.3.14. Consume the remnants of a bad url
// ... its sole use is to consume enough of the input stream to reach a recovery point
// where normal tokenizing can resume.
function consumeBadUrlRemnants(source, offset) {
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
// U+0029 RIGHT PARENTHESIS ())
// EOF
if (code === 0x0029) {
// Return.
offset++;
break;
}
if (char_code_definitions_isValidEscape(code, getCharCode(source, offset + 1))) {
// Consume an escaped code point.
// Note: This allows an escaped right parenthesis ("\)") to be encountered
// without ending the <bad-url-token>. This is otherwise identical to
// the "anything else" clause.
offset = utils_consumeEscaped(source, offset);
}
}
return offset;
}
// § 4.3.7. Consume an escaped code point
// Note: This algorithm assumes that escaped is valid without leading U+005C REVERSE SOLIDUS (\)
function utils_decodeEscaped(escaped) {
// Single char escaped that's not a hex digit
if (escaped.length === 1 && !isHexDigit(escaped.charCodeAt(0))) {
return escaped[0];
}
// Interpret the hex digits as a hexadecimal number.
let code = parseInt(escaped, 16);
if (
(code === 0) || // If this number is zero,
(code >= 0xD800 && code <= 0xDFFF) || // or is for a surrogate,
(code > 0x10FFFF) // or is greater than the maximum allowed code point
) {
// ... return U+FFFD REPLACEMENT CHARACTER
code = 0xFFFD;
}
// Otherwise, return the code point with that value.
return String.fromCodePoint(code);
}
;// ./node_modules/css-tree/lib/tokenizer/names.js
/* harmony default export */ const names = ([
'EOF-token',
'ident-token',
'function-token',
'at-keyword-token',
'hash-token',
'string-token',
'bad-string-token',
'url-token',
'bad-url-token',
'delim-token',
'number-token',
'percentage-token',
'dimension-token',
'whitespace-token',
'CDO-token',
'CDC-token',
'colon-token',
'semicolon-token',
'comma-token',
'[-token',
']-token',
'(-token',
')-token',
'{-token',
'}-token'
]);
;// ./node_modules/css-tree/lib/tokenizer/adopt-buffer.js
const MIN_SIZE = 16 * 1024;
function adoptBuffer(buffer = null, size) {
if (buffer === null || buffer.length < size) {
return new Uint32Array(Math.max(size + 1024, MIN_SIZE));
}
return buffer;
};
;// ./node_modules/css-tree/lib/tokenizer/OffsetToLocation.js
const N = 10;
const F = 12;
const R = 13;
function computeLinesAndColumns(host) {
const source = host.source;
const sourceLength = source.length;
const startOffset = source.length > 0 ? isBOM(source.charCodeAt(0)) : 0;
const lines = adoptBuffer(host.lines, sourceLength);
const columns = adoptBuffer(host.columns, sourceLength);
let line = host.startLine;
let column = host.startColumn;
for (let i = startOffset; i < sourceLength; i++) {
const code = source.charCodeAt(i);
lines[i] = line;
columns[i] = column++;
if (code === N || code === R || code === F) {
if (code === R && i + 1 < sourceLength && source.charCodeAt(i + 1) === N) {
i++;
lines[i] = line;
columns[i] = column;
}
line++;
column = 1;
}
}
lines[sourceLength] = line;
columns[sourceLength] = column;
host.lines = lines;
host.columns = columns;
host.computed = true;
}
class OffsetToLocation {
constructor() {
this.lines = null;
this.columns = null;
this.computed = false;
}
setSource(source, startOffset = 0, startLine = 1, startColumn = 1) {
this.source = source;
this.startOffset = startOffset;
this.startLine = startLine;
this.startColumn = startColumn;
this.computed = false;
}
getLocation(offset, filename) {
if (!this.computed) {
computeLinesAndColumns(this);
}
return {
source: filename,
offset: this.startOffset + offset,
line: this.lines[offset],
column: this.columns[offset]
};
}
getLocationRange(start, end, filename) {
if (!this.computed) {
computeLinesAndColumns(this);
}
return {
source: filename,
start: {
offset: this.startOffset + start,
line: this.lines[start],
column: this.columns[start]
},
end: {
offset: this.startOffset + end,
line: this.lines[end],
column: this.columns[end]
}
};
}
};
;// ./node_modules/css-tree/lib/tokenizer/TokenStream.js
const OFFSET_MASK = 0x00FFFFFF;
const TYPE_SHIFT = 24;
const balancePair = new Map([
[Function, RightParenthesis],
[LeftParenthesis, RightParenthesis],
[LeftSquareBracket, RightSquareBracket],
[LeftCurlyBracket, RightCurlyBracket]
]);
class TokenStream {
constructor(source, tokenize) {
this.setSource(source, tokenize);
}
reset() {
this.eof = false;
this.tokenIndex = -1;
this.tokenType = 0;
this.tokenStart = this.firstCharOffset;
this.tokenEnd = this.firstCharOffset;
}
setSource(source = '', tokenize = () => {}) {
source = String(source || '');
const sourceLength = source.length;
const offsetAndType = adoptBuffer(this.offsetAndType, source.length + 1); // +1 because of eof-token
const balance = adoptBuffer(this.balance, source.length + 1);
let tokenCount = 0;
let balanceCloseType = 0;
let balanceStart = 0;
let firstCharOffset = -1;
// capture buffers
this.offsetAndType = null;
this.balance = null;
tokenize(source, (type, start, end) => {
switch (type) {
default:
balance[tokenCount] = sourceLength;
break;
case balanceCloseType: {
let balancePrev = balanceStart & OFFSET_MASK;
balanceStart = balance[balancePrev];
balanceCloseType = balanceStart >> TYPE_SHIFT;
balance[tokenCount] = balancePrev;
balance[balancePrev++] = tokenCount;
for (; balancePrev < tokenCount; balancePrev++) {
if (balance[balancePrev] === sourceLength) {
balance[balancePrev] = tokenCount;
}
}
break;
}
case LeftParenthesis:
case Function:
case LeftSquareBracket:
case LeftCurlyBracket:
balance[tokenCount] = balanceStart;
balanceCloseType = balancePair.get(type);
balanceStart = (balanceCloseType << TYPE_SHIFT) | tokenCount;
break;
}
offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | end;
if (firstCharOffset === -1) {
firstCharOffset = start;
}
});
// finalize buffers
offsetAndType[tokenCount] = (EOF << TYPE_SHIFT) | sourceLength; // <EOF-token>
balance[tokenCount] = sourceLength;
balance[sourceLength] = sourceLength; // prevents false positive balance match with any token
while (balanceStart !== 0) {
const balancePrev = balanceStart & OFFSET_MASK;
balanceStart = balance[balancePrev];
balance[balancePrev] = sourceLength;
}
this.source = source;
this.firstCharOffset = firstCharOffset === -1 ? 0 : firstCharOffset;
this.tokenCount = tokenCount;
this.offsetAndType = offsetAndType;
this.balance = balance;
this.reset();
this.next();
}
lookupType(offset) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return this.offsetAndType[offset] >> TYPE_SHIFT;
}
return EOF;
}
lookupOffset(offset) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return this.offsetAndType[offset - 1] & OFFSET_MASK;
}
return this.source.length;
}
lookupValue(offset, referenceStr) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return cmpStr(
this.source,
this.offsetAndType[offset - 1] & OFFSET_MASK,
this.offsetAndType[offset] & OFFSET_MASK,
referenceStr
);
}
return false;
}
getTokenStart(tokenIndex) {
if (tokenIndex === this.tokenIndex) {
return this.tokenStart;
}
if (tokenIndex > 0) {
return tokenIndex < this.tokenCount
? this.offsetAndType[tokenIndex - 1] & OFFSET_MASK
: this.offsetAndType[this.tokenCount] & OFFSET_MASK;
}
return this.firstCharOffset;
}
substrToCursor(start) {
return this.source.substring(start, this.tokenStart);
}
isBalanceEdge(pos) {
return this.balance[this.tokenIndex] < pos;
}
isDelim(code, offset) {
if (offset) {
return (
this.lookupType(offset) === Delim &&
this.source.charCodeAt(this.lookupOffset(offset)) === code
);
}
return (
this.tokenType === Delim &&
this.source.charCodeAt(this.tokenStart) === code
);
}
skip(tokenCount) {
let next = this.tokenIndex + tokenCount;
if (next < this.tokenCount) {
this.tokenIndex = next;
this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
next = this.offsetAndType[next];
this.tokenType = next >> TYPE_SHIFT;
this.tokenEnd = next & OFFSET_MASK;
} else {
this.tokenIndex = this.tokenCount;
this.next();
}
}
next() {
let next = this.tokenIndex + 1;
if (next < this.tokenCount) {
this.tokenIndex = next;
this.tokenStart = this.tokenEnd;
next = this.offsetAndType[next];
this.tokenType = next >> TYPE_SHIFT;
this.tokenEnd = next & OFFSET_MASK;
} else {
this.eof = true;
this.tokenIndex = this.tokenCount;
this.tokenType = EOF;
this.tokenStart = this.tokenEnd = this.source.length;
}
}
skipSC() {
while (this.tokenType === WhiteSpace || this.tokenType === Comment) {
this.next();
}
}
skipUntilBalanced(startToken, stopConsume) {
let cursor = startToken;
let balanceEnd;
let offset;
loop:
for (; cursor < this.tokenCount; cursor++) {
balanceEnd = this.balance[cursor];
// stop scanning on balance edge that points to offset before start token
if (balanceEnd < startToken) {
break loop;
}
offset = cursor > 0 ? this.offsetAndType[cursor - 1] & OFFSET_MASK : this.firstCharOffset;
// check stop condition
switch (stopConsume(this.source.charCodeAt(offset))) {
case 1: // just stop
break loop;
case 2: // stop & included
cursor++;
break loop;
default:
// fast forward to the end of balanced block
if (this.balance[balanceEnd] === cursor) {
cursor = balanceEnd;
}
}
}
this.skip(cursor - this.tokenIndex);
}
forEachToken(fn) {
for (let i = 0, offset = this.firstCharOffset; i < this.tokenCount; i++) {
const start = offset;
const item = this.offsetAndType[i];
const end = item & OFFSET_MASK;
const type = item >> TYPE_SHIFT;
offset = end;
fn(type, start, end, i);
}
}
dump() {
const tokens = new Array(this.tokenCount);
this.forEachToken((type, start, end, index) => {
tokens[index] = {
idx: index,
type: names[type],
chunk: this.source.substring(start, end),
balance: this.balance[index]
};
});
return tokens;
}
};
;// ./node_modules/css-tree/lib/tokenizer/index.js
function tokenize(source, onToken) {
function getCharCode(offset) {
return offset < sourceLength ? source.charCodeAt(offset) : 0;
}
// § 4.3.3. Consume a numeric token
function consumeNumericToken() {
// Consume a number and let number be the result.
offset = consumeNumber(source, offset);
// If the next 3 input code points would start an identifier, then:
if (isIdentifierStart(getCharCode(offset), getCharCode(offset + 1), getCharCode(offset + 2))) {
// Create a <dimension-token> with the same value and type flag as number, and a unit set initially to the empty string.
// Consume a name. Set the <dimension-token>’s unit to the returned value.
// Return the <dimension-token>.
type = Dimension;
offset = consumeName(source, offset);
return;
}
// Otherwise, if the next input code point is U+0025 PERCENTAGE SIGN (%), consume it.
if (getCharCode(offset) === 0x0025) {
// Create a <percentage-token> with the same value as number, and return it.
type = Percentage;
offset++;
return;
}
// Otherwise, create a <number-token> with the same value and type flag as number, and return it.
type = types_Number;
}
// § 4.3.4. Consume an ident-like token
function consumeIdentLikeToken() {
const nameStartOffset = offset;
// Consume a name, and let string be the result.
offset = consumeName(source, offset);
// If string’s value is an ASCII case-insensitive match for "url",
// and the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
if (cmpStr(source, nameStartOffset, offset, 'url') && getCharCode(offset) === 0x0028) {
// While the next two input code points are whitespace, consume the next input code point.
offset = findWhiteSpaceEnd(source, offset + 1);
// If the next one or two input code points are U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('),
// or whitespace followed by U+0022 QUOTATION MARK (") or U+0027 APOSTROPHE ('),
// then create a <function-token> with its value set to string and return it.
if (getCharCode(offset) === 0x0022 ||
getCharCode(offset) === 0x0027) {
type = Function;
offset = nameStartOffset + 4;
return;
}
// Otherwise, consume a url token, and return it.
consumeUrlToken();
return;
}
// Otherwise, if the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
// Create a <function-token> with its value set to string and return it.
if (getCharCode(offset) === 0x0028) {
type = Function;
offset++;
return;
}
// Otherwise, create an <ident-token> with its value set to string and return it.
type = Ident;
}
// § 4.3.5. Consume a string token
function consumeStringToken(endingCodePoint) {
// This algorithm may be called with an ending code point, which denotes the code point
// that ends the string. If an ending code point is not specified,
// the current input code point is used.
if (!endingCodePoint) {
endingCodePoint = getCharCode(offset++);
}
// Initially create a <string-token> with its value set to the empty string.
type = types_String;
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
switch (charCodeCategory(code)) {
// ending code point
case endingCodePoint:
// Return the <string-token>.
offset++;
return;
// EOF
// case EofCategory:
// This is a parse error. Return the <string-token>.
// return;
// newline
case WhiteSpaceCategory:
if (isNewline(code)) {
// This is a parse error. Reconsume the current input code point,
// create a <bad-string-token>, and return it.
offset += getNewlineLength(source, offset, code);
type = BadString;
return;
}
break;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the next input code point is EOF, do nothing.
if (offset === source.length - 1) {
break;
}
const nextCode = getCharCode(offset + 1);
// Otherwise, if the next input code point is a newline, consume it.
if (isNewline(nextCode)) {
offset += getNewlineLength(source, offset + 1, nextCode);
} else if (char_code_definitions_isValidEscape(code, nextCode)) {
// Otherwise, (the stream starts with a valid escape) consume
// an escaped code point and append the returned code point to
// the <string-token>’s value.
offset = utils_consumeEscaped(source, offset) - 1;
}
break;
// anything else
// Append the current input code point to the <string-token>’s value.
}
}
}
// § 4.3.6. Consume a url token
// Note: This algorithm assumes that the initial "url(" has already been consumed.
// This algorithm also assumes that it’s being called to consume an "unquoted" value, like url(foo).
// A quoted value, like url("foo"), is parsed as a <function-token>. Consume an ident-like token
// automatically handles this distinction; this algorithm shouldn’t be called directly otherwise.
function consumeUrlToken() {
// Initially create a <url-token> with its value set to the empty string.
type = Url;
// Consume as much whitespace as possible.
offset = findWhiteSpaceEnd(source, offset);
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
switch (charCodeCategory(code)) {
// U+0029 RIGHT PARENTHESIS ())
case 0x0029:
// Return the <url-token>.
offset++;
return;
// EOF
// case EofCategory:
// This is a parse error. Return the <url-token>.
// return;
// whitespace
case WhiteSpaceCategory:
// Consume as much whitespace as possible.
offset = findWhiteSpaceEnd(source, offset);
// If the next input code point is U+0029 RIGHT PARENTHESIS ()) or EOF,
// consume it and return the <url-token>
// (if EOF was encountered, this is a parse error);
if (getCharCode(offset) === 0x0029 || offset >= source.length) {
if (offset < source.length) {
offset++;
}
return;
}
// otherwise, consume the remnants of a bad url, create a <bad-url-token>,
// and return it.
offset = consumeBadUrlRemnants(source, offset);
type = BadUrl;
return;
// U+0022 QUOTATION MARK (")
// U+0027 APOSTROPHE (')
// U+0028 LEFT PARENTHESIS (()
// non-printable code point
case 0x0022:
case 0x0027:
case 0x0028:
case NonPrintableCategory:
// This is a parse error. Consume the remnants of a bad url,
// create a <bad-url-token>, and return it.
offset = consumeBadUrlRemnants(source, offset);
type = BadUrl;
return;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the stream starts with a valid escape, consume an escaped code point and
// append the returned code point to the <url-token>’s value.
if (char_code_definitions_isValidEscape(code, getCharCode(offset + 1))) {
offset = utils_consumeEscaped(source, offset) - 1;
break;
}
// Otherwise, this is a parse error. Consume the remnants of a bad url,
// create a <bad-url-token>, and return it.
offset = consumeBadUrlRemnants(source, offset);
type = BadUrl;
return;
// anything else
// Append the current input code point to the <url-token>’s value.
}
}
}
// ensure source is a string
source = String(source || '');
const sourceLength = source.length;
let start = isBOM(getCharCode(0));
let offset = start;
let type;
// https://drafts.csswg.org/css-syntax-3/#consume-token
// § 4.3.1. Consume a token
while (offset < sourceLength) {
const code = source.charCodeAt(offset);
switch (charCodeCategory(code)) {
// whitespace
case WhiteSpaceCategory:
// Consume as much whitespace as possible. Return a <whitespace-token>.
type = WhiteSpace;
offset = findWhiteSpaceEnd(source, offset + 1);
break;
// U+0022 QUOTATION MARK (")
case 0x0022:
// Consume a string token and return it.
consumeStringToken();
break;
// U+0023 NUMBER SIGN (#)
case 0x0023:
// If the next input code point is a name code point or the next two input code points are a valid escape, then:
if (char_code_definitions_isName(getCharCode(offset + 1)) || char_code_definitions_isValidEscape(getCharCode(offset + 1), getCharCode(offset + 2))) {
// Create a <hash-token>.
type = Hash;
// If the next 3 input code points would start an identifier, set the <hash-token>’s type flag to "id".
// if (isIdentifierStart(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
// // TODO: set id flag
// }
// Consume a name, and set the <hash-token>’s value to the returned string.
offset = consumeName(source, offset + 1);
// Return the <hash-token>.
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
break;
// U+0027 APOSTROPHE (')
case 0x0027:
// Consume a string token and return it.
consumeStringToken();
break;
// U+0028 LEFT PARENTHESIS (()
case 0x0028:
// Return a <(-token>.
type = LeftParenthesis;
offset++;
break;
// U+0029 RIGHT PARENTHESIS ())
case 0x0029:
// Return a <)-token>.
type = RightParenthesis;
offset++;
break;
// U+002B PLUS SIGN (+)
case 0x002B:
// If the input stream starts with a number, ...
if (isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
break;
// U+002C COMMA (,)
case 0x002C:
// Return a <comma-token>.
type = Comma;
offset++;
break;
// U+002D HYPHEN-MINUS (-)
case 0x002D:
// If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
if (isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
consumeNumericToken();
} else {
// Otherwise, if the next 2 input code points are U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), consume them and return a <CDC-token>.
if (getCharCode(offset + 1) === 0x002D &&
getCharCode(offset + 2) === 0x003E) {
type = CDC;
offset = offset + 3;
} else {
// Otherwise, if the input stream starts with an identifier, ...
if (isIdentifierStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
}
}
break;
// U+002E FULL STOP (.)
case 0x002E:
// If the input stream starts with a number, ...
if (isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
break;
// U+002F SOLIDUS (/)
case 0x002F:
// If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A ASTERISK (*),
if (getCharCode(offset + 1) === 0x002A) {
// ... consume them and all following code points up to and including the first U+002A ASTERISK (*)
// followed by a U+002F SOLIDUS (/), or up to an EOF code point.
type = Comment;
offset = source.indexOf('*/', offset + 2);
offset = offset === -1 ? source.length : offset + 2;
} else {
type = Delim;
offset++;
}
break;
// U+003A COLON (:)
case 0x003A:
// Return a <colon-token>.
type = Colon;
offset++;
break;
// U+003B SEMICOLON (;)
case 0x003B:
// Return a <semicolon-token>.
type = Semicolon;
offset++;
break;
// U+003C LESS-THAN SIGN (<)
case 0x003C:
// If the next 3 input code points are U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D HYPHEN-MINUS (!--), ...
if (getCharCode(offset + 1) === 0x0021 &&
getCharCode(offset + 2) === 0x002D &&
getCharCode(offset + 3) === 0x002D) {
// ... consume them and return a <CDO-token>.
type = CDO;
offset = offset + 4;
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
break;
// U+0040 COMMERCIAL AT (@)
case 0x0040:
// If the next 3 input code points would start an identifier, ...
if (isIdentifierStart(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
// ... consume a name, create an <at-keyword-token> with its value set to the returned value, and return it.
type = AtKeyword;
offset = consumeName(source, offset + 1);
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
break;
// U+005B LEFT SQUARE BRACKET ([)
case 0x005B:
// Return a <[-token>.
type = LeftSquareBracket;
offset++;
break;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the input stream starts with a valid escape, ...
if (char_code_definitions_isValidEscape(code, getCharCode(offset + 1))) {
// ... reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
} else {
// Otherwise, this is a parse error. Return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
break;
// U+005D RIGHT SQUARE BRACKET (])
case 0x005D:
// Return a <]-token>.
type = RightSquareBracket;
offset++;
break;
// U+007B LEFT CURLY BRACKET ({)
case 0x007B:
// Return a <{-token>.
type = LeftCurlyBracket;
offset++;
break;
// U+007D RIGHT CURLY BRACKET (})
case 0x007D:
// Return a <}-token>.
type = RightCurlyBracket;
offset++;
break;
// digit
case DigitCategory:
// Reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
break;
// name-start code point
case NameStartCategory:
// Reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
break;
// EOF
// case EofCategory:
// Return an <EOF-token>.
// break;
// anything else
default:
// Return a <delim-token> with its value set to the current input code point.
type = Delim;
offset++;
}
// put token to stream
onToken(type, start, start = offset);
}
}
;// ./node_modules/css-tree/lib/utils/List.js
//
// list
// ┌──────┐
// ┌──────────────┼─head │
// │ │ tail─┼──────────────┐
// │ └──────┘ │
// ▼ ▼
// item item item item
// ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
// null ◀──┼─prev │◀───┼─prev │◀───┼─prev │◀───┼─prev │
// │ next─┼───▶│ next─┼───▶│ next─┼───▶│ next─┼──▶ null
// ├──────┤ ├──────┤ ├──────┤ ├──────┤
// │ data │ │ data │ │ data │ │ data │
// └──────┘ └──────┘ └──────┘ └──────┘
//
let releasedCursors = null;
class List_List {
static createItem(data) {
return {
prev: null,
next: null,
data
};
}
constructor() {
this.head = null;
this.tail = null;
this.cursor = null;
}
createItem(data) {
return List_List.createItem(data);
}
// cursor helpers
allocateCursor(prev, next) {
let cursor;
if (releasedCursors !== null) {
cursor = releasedCursors;
releasedCursors = releasedCursors.cursor;
cursor.prev = prev;
cursor.next = next;
cursor.cursor = this.cursor;
} else {
cursor = {
prev,
next,
cursor: this.cursor
};
}
this.cursor = cursor;
return cursor;
}
releaseCursor() {
const { cursor } = this;
this.cursor = cursor.cursor;
cursor.prev = null;
cursor.next = null;
cursor.cursor = releasedCursors;
releasedCursors = cursor;
}
updateCursors(prevOld, prevNew, nextOld, nextNew) {
let { cursor } = this;
while (cursor !== null) {
if (cursor.prev === prevOld) {
cursor.prev = prevNew;
}
if (cursor.next === nextOld) {
cursor.next = nextNew;
}
cursor = cursor.cursor;
}
}
*[Symbol.iterator]() {
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
yield cursor.data;
}
}
// getters
get size() {
let size = 0;
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
size++;
}
return size;
}
get isEmpty() {
return this.head === null;
}
get first() {
return this.head && this.head.data;
}
get last() {
return this.tail && this.tail.data;
}
// convertors
fromArray(array) {
let cursor = null;
this.head = null;
for (let data of array) {
const item = List_List.createItem(data);
if (cursor !== null) {
cursor.next = item;
} else {
this.head = item;
}
item.prev = cursor;
cursor = item;
}
this.tail = cursor;
return this;
}
toArray() {
return [...this];
}
toJSON() {
return [...this];
}
// array-like methods
forEach(fn, thisArg = this) {
// push cursor
const cursor = this.allocateCursor(null, this.head);
while (cursor.next !== null) {
const item = cursor.next;
cursor.next = item.next;
fn.call(thisArg, item.data, item, this);
}
// pop cursor
this.releaseCursor();
}
forEachRight(fn, thisArg = this) {
// push cursor
const cursor = this.allocateCursor(this.tail, null);
while (cursor.prev !== null) {
const item = cursor.prev;
cursor.prev = item.prev;
fn.call(thisArg, item.data, item, this);
}
// pop cursor
this.releaseCursor();
}
reduce(fn, initialValue, thisArg = this) {
// push cursor
let cursor = this.allocateCursor(null, this.head);
let acc = initialValue;
let item;
while (cursor.next !== null) {
item = cursor.next;
cursor.next = item.next;
acc = fn.call(thisArg, acc, item.data, item, this);
}
// pop cursor
this.releaseCursor();
return acc;
}
reduceRight(fn, initialValue, thisArg = this) {
// push cursor
let cursor = this.allocateCursor(this.tail, null);
let acc = initialValue;
let item;
while (cursor.prev !== null) {
item = cursor.prev;
cursor.prev = item.prev;
acc = fn.call(thisArg, acc, item.data, item, this);
}
// pop cursor
this.releaseCursor();
return acc;
}
some(fn, thisArg = this) {
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
if (fn.call(thisArg, cursor.data, cursor, this)) {
return true;
}
}
return false;
}
map(fn, thisArg = this) {
const result = new List_List();
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
result.appendData(fn.call(thisArg, cursor.data, cursor, this));
}
return result;
}
filter(fn, thisArg = this) {
const result = new List_List();
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
if (fn.call(thisArg, cursor.data, cursor, this)) {
result.appendData(cursor.data);
}
}
return result;
}
nextUntil(start, fn, thisArg = this) {
if (start === null) {
return;
}
// push cursor
const cursor = this.allocateCursor(null, start);
while (cursor.next !== null) {
const item = cursor.next;
cursor.next = item.next;
if (fn.call(thisArg, item.data, item, this)) {
break;
}
}
// pop cursor
this.releaseCursor();
}
prevUntil(start, fn, thisArg = this) {
if (start === null) {
return;
}
// push cursor
const cursor = this.allocateCursor(start, null);
while (cursor.prev !== null) {
const item = cursor.prev;
cursor.prev = item.prev;
if (fn.call(thisArg, item.data, item, this)) {
break;
}
}
// pop cursor
this.releaseCursor();
}
// mutation
clear() {
this.head = null;
this.tail = null;
}
copy() {
const result = new List_List();
for (let data of this) {
result.appendData(data);
}
return result;
}
prepend(item) {
// head
// ^
// item
this.updateCursors(null, item, this.head, item);
// insert to the beginning of the list
if (this.head !== null) {
// new item <- first item
this.head.prev = item;
// new item -> first item
item.next = this.head;
} else {
// if list has no head, then it also has no tail
// in this case tail points to the new item
this.tail = item;
}
// head always points to new item
this.head = item;
return this;
}
prependData(data) {
return this.prepend(List_List.createItem(data));
}
append(item) {
return this.insert(item);
}
appendData(data) {
return this.insert(List_List.createItem(data));
}
insert(item, before = null) {
if (before !== null) {
// prev before
// ^
// item
this.updateCursors(before.prev, item, before, item);
if (before.prev === null) {
// insert to the beginning of list
if (this.head !== before) {
throw new Error('before doesn\'t belong to list');
}
// since head points to before therefore list doesn't empty
// no need to check tail
this.head = item;
before.prev = item;
item.next = before;
this.updateCursors(null, item);
} else {
// insert between two items
before.prev.next = item;
item.prev = before.prev;
before.prev = item;
item.next = before;
}
} else {
// tail
// ^
// item
this.updateCursors(this.tail, item, null, item);
// insert to the ending of the list
if (this.tail !== null) {
// last item -> new item
this.tail.next = item;
// last item <- new item
item.prev = this.tail;
} else {
// if list has no tail, then it also has no head
// in this case head points to new item
this.head = item;
}
// tail always points to new item
this.tail = item;
}
return this;
}
insertData(data, before) {
return this.insert(List_List.createItem(data), before);
}
remove(item) {
// item
// ^
// prev next
this.updateCursors(item, item.prev, item, item.next);
if (item.prev !== null) {
item.prev.next = item.next;
} else {
if (this.head !== item) {
throw new Error('item doesn\'t belong to list');
}
this.head = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
} else {
if (this.tail !== item) {
throw new Error('item doesn\'t belong to list');
}
this.tail = item.prev;
}
item.prev = null;
item.next = null;
return item;
}
push(data) {
this.insert(List_List.createItem(data));
}
pop() {
return this.tail !== null ? this.remove(this.tail) : null;
}
unshift(data) {
this.prepend(List_List.createItem(data));
}
shift() {
return this.head !== null ? this.remove(this.head) : null;
}
prependList(list) {
return this.insertList(list, this.head);
}
appendList(list) {
return this.insertList(list);
}
insertList(list, before) {
// ignore empty lists
if (list.head === null) {
return this;
}
if (before !== undefined && before !== null) {
this.updateCursors(before.prev, list.tail, before, list.head);
// insert in the middle of dist list
if (before.prev !== null) {
// before.prev <-> list.head
before.prev.next = list.head;
list.head.prev = before.prev;
} else {
this.head = list.head;
}
before.prev = list.tail;
list.tail.next = before;
} else {
this.updateCursors(this.tail, list.tail, null, list.head);
// insert to end of the list
if (this.tail !== null) {
// if destination list has a tail, then it also has a head,
// but head doesn't change
// dest tail -> source head
this.tail.next = list.head;
// dest tail <- source head
list.head.prev = this.tail;
} else {
// if list has no a tail, then it also has no a head
// in this case points head to new item
this.head = list.head;
}
// tail always start point to new item
this.tail = list.tail;
}
list.head = null;
list.tail = null;
return this;
}
replace(oldItem, newItemOrList) {
if ('head' in newItemOrList) {
this.insertList(newItemOrList, oldItem);
} else {
this.insert(newItemOrList, oldItem);
}
this.remove(oldItem);
}
}
;// ./node_modules/css-tree/lib/utils/create-custom-error.js
function createCustomError(name, message) {
// use Object.create(), because some VMs prevent setting line/column otherwise
// (iOS Safari 10 even throws an exception)
const error = Object.create(SyntaxError.prototype);
const errorStack = new Error();
return Object.assign(error, {
name,
message,
get stack() {
return (errorStack.stack || '').replace(/^(.+\n){1,3}/, `${name}: ${message}\n`);
}
});
};
;// ./node_modules/css-tree/lib/parser/SyntaxError.js
const MAX_LINE_LENGTH = 100;
const OFFSET_CORRECTION = 60;
const TAB_REPLACEMENT = ' ';
function sourceFragment({ source, line, column }, extraLines) {
function processLines(start, end) {
return lines
.slice(start, end)
.map((line, idx) =>
String(start + idx + 1).padStart(maxNumLength) + ' |' + line
).join('\n');
}
const lines = source.split(/\r\n?|\n|\f/);
const startLine = Math.max(1, line - extraLines) - 1;
const endLine = Math.min(line + extraLines, lines.length + 1);
const maxNumLength = Math.max(4, String(endLine).length) + 1;
let cutLeft = 0;
// column correction according to replaced tab before column
column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
if (column > MAX_LINE_LENGTH) {
cutLeft = column - OFFSET_CORRECTION + 3;
column = OFFSET_CORRECTION - 2;
}
for (let i = startLine; i <= endLine; i++) {
if (i >= 0 && i < lines.length) {
lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
lines[i] =
(cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
(lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
}
}
return [
processLines(startLine, line),
new Array(column + maxNumLength + 2).join('-') + '^',
processLines(line, endLine)
].filter(Boolean).join('\n');
}
function SyntaxError_SyntaxError(message, source, offset, line, column) {
const error = Object.assign(createCustomError('SyntaxError', message), {
source,
offset,
line,
column,
sourceFragment(extraLines) {
return sourceFragment({ source, line, column }, isNaN(extraLines) ? 0 : extraLines);
},
get formattedMessage() {
return (
`Parse error: ${message}\n` +
sourceFragment({ source, line, column }, 2)
);
}
});
return error;
}
;// ./node_modules/css-tree/lib/parser/sequence.js
function readSequence(recognizer) {
const children = this.createList();
let space = false;
const context = {
recognizer
};
while (!this.eof) {
switch (this.tokenType) {
case Comment:
this.next();
continue;
case WhiteSpace:
space = true;
this.next();
continue;
}
let child = recognizer.getNode.call(this, context);
if (child === undefined) {
break;
}
if (space) {
if (recognizer.onWhiteSpace) {
recognizer.onWhiteSpace.call(this, child, children, context);
}
space = false;
}
children.push(child);
}
if (space && recognizer.onWhiteSpace) {
recognizer.onWhiteSpace.call(this, null, children, context);
}
return children;
};
;// ./node_modules/css-tree/lib/parser/create.js
const NOOP = () => {};
const EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!)
const NUMBERSIGN = 0x0023; // U+0023 NUMBER SIGN (#)
const SEMICOLON = 0x003B; // U+003B SEMICOLON (;)
const LEFTCURLYBRACKET = 0x007B; // U+007B LEFT CURLY BRACKET ({)
const NULL = 0;
function createParseContext(name) {
return function() {
return this[name]();
};
}
function fetchParseValues(dict) {
const result = Object.create(null);
for (const name in dict) {
const item = dict[name];
const fn = item.parse || item;
if (fn) {
result[name] = fn;
}
}
return result;
}
function processConfig(config) {
const parseConfig = {
context: Object.create(null),
scope: Object.assign(Object.create(null), config.scope),
atrule: fetchParseValues(config.atrule),
pseudo: fetchParseValues(config.pseudo),
node: fetchParseValues(config.node)
};
for (const name in config.parseContext) {
switch (typeof config.parseContext[name]) {
case 'function':
parseConfig.context[name] = config.parseContext[name];
break;
case 'string':
parseConfig.context[name] = createParseContext(config.parseContext[name]);
break;
}
}
return {
config: parseConfig,
...parseConfig,
...parseConfig.node
};
}
function createParser(config) {
let source = '';
let filename = '<unknown>';
let needPositions = false;
let onParseError = NOOP;
let onParseErrorThrow = false;
const locationMap = new OffsetToLocation();
const parser = Object.assign(new TokenStream(), processConfig(config || {}), {
parseAtrulePrelude: true,
parseRulePrelude: true,
parseValue: true,
parseCustomProperty: false,
readSequence: readSequence,
consumeUntilBalanceEnd: () => 0,
consumeUntilLeftCurlyBracket(code) {
return code === LEFTCURLYBRACKET ? 1 : 0;
},
consumeUntilLeftCurlyBracketOrSemicolon(code) {
return code === LEFTCURLYBRACKET || code === SEMICOLON ? 1 : 0;
},
consumeUntilExclamationMarkOrSemicolon(code) {
return code === EXCLAMATIONMARK || code === SEMICOLON ? 1 : 0;
},
consumeUntilSemicolonIncluded(code) {
return code === SEMICOLON ? 2 : 0;
},
createList() {
return new List_List();
},
createSingleNodeList(node) {
return new List_List().appendData(node);
},
getFirstListNode(list) {
return list && list.first;
},
getLastListNode(list) {
return list && list.last;
},
parseWithFallback(consumer, fallback) {
const startToken = this.tokenIndex;
try {
return consumer.call(this);
} catch (e) {
if (onParseErrorThrow) {
throw e;
}
const fallbackNode = fallback.call(this, startToken);
onParseErrorThrow = true;
onParseError(e, fallbackNode);
onParseErrorThrow = false;
return fallbackNode;
}
},
lookupNonWSType(offset) {
let type;
do {
type = this.lookupType(offset++);
if (type !== WhiteSpace) {
return type;
}
} while (type !== NULL);
return NULL;
},
charCodeAt(offset) {
return offset >= 0 && offset < source.length ? source.charCodeAt(offset) : 0;
},
substring(offsetStart, offsetEnd) {
return source.substring(offsetStart, offsetEnd);
},
substrToCursor(start) {
return this.source.substring(start, this.tokenStart);
},
cmpChar(offset, charCode) {
return cmpChar(source, offset, charCode);
},
cmpStr(offsetStart, offsetEnd, str) {
return cmpStr(source, offsetStart, offsetEnd, str);
},
consume(tokenType) {
const start = this.tokenStart;
this.eat(tokenType);
return this.substrToCursor(start);
},
consumeFunctionName() {
const name = source.substring(this.tokenStart, this.tokenEnd - 1);
this.eat(Function);
return name;
},
consumeNumber(type) {
const number = source.substring(this.tokenStart, consumeNumber(source, this.tokenStart));
this.eat(type);
return number;
},
eat(tokenType) {
if (this.tokenType !== tokenType) {
const tokenName = names[tokenType].slice(0, -6).replace(/-/g, ' ').replace(/^./, m => m.toUpperCase());
let message = `${/[[\](){}]/.test(tokenName) ? `"${tokenName}"` : tokenName} is expected`;
let offset = this.tokenStart;
// tweak message and offset
switch (tokenType) {
case Ident:
// when identifier is expected but there is a function or url
if (this.tokenType === Function || this.tokenType === Url) {
offset = this.tokenEnd - 1;
message = 'Identifier is expected but function found';
} else {
message = 'Identifier is expected';
}
break;
case Hash:
if (this.isDelim(NUMBERSIGN)) {
this.next();
offset++;
message = 'Name is expected';
}
break;
case Percentage:
if (this.tokenType === types_Number) {
offset = this.tokenEnd;
message = 'Percent sign is expected';
}
break;
}
this.error(message, offset);
}
this.next();
},
eatIdent(name) {
if (this.tokenType !== Ident || this.lookupValue(0, name) === false) {
this.error(`Identifier "${name}" is expected`);
}
this.next();
},
eatDelim(code) {
if (!this.isDelim(code)) {
this.error(`Delim "${String.fromCharCode(code)}" is expected`);
}
this.next();
},
getLocation(start, end) {
if (needPositions) {
return locationMap.getLocationRange(
start,
end,
filename
);
}
return null;
},
getLocationFromList(list) {
if (needPositions) {
const head = this.getFirstListNode(list);
const tail = this.getLastListNode(list);
return locationMap.getLocationRange(
head !== null ? head.loc.start.offset - locationMap.startOffset : this.tokenStart,
tail !== null ? tail.loc.end.offset - locationMap.startOffset : this.tokenStart,
filename
);
}
return null;
},
error(message, offset) {
const location = typeof offset !== 'undefined' && offset < source.length
? locationMap.getLocation(offset)
: this.eof
? locationMap.getLocation(findWhiteSpaceStart(source, source.length - 1))
: locationMap.getLocation(this.tokenStart);
throw new SyntaxError_SyntaxError(
message || 'Unexpected input',
source,
location.offset,
location.line,
location.column
);
}
});
const parse = function(source_, options) {
source = source_;
options = options || {};
parser.setSource(source, tokenize);
locationMap.setSource(
source,
options.offset,
options.line,
options.column
);
filename = options.filename || '<unknown>';
needPositions = Boolean(options.positions);
onParseError = typeof options.onParseError === 'function' ? options.onParseError : NOOP;
onParseErrorThrow = false;
parser.parseAtrulePrelude = 'parseAtrulePrelude' in options ? Boolean(options.parseAtrulePrelude) : true;
parser.parseRulePrelude = 'parseRulePrelude' in options ? Boolean(options.parseRulePrelude) : true;
parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
const { context = 'default', onComment } = options;
if (context in parser.context === false) {
throw new Error('Unknown context `' + context + '`');
}
if (typeof onComment === 'function') {
parser.forEachToken((type, start, end) => {
if (type === Comment) {
const loc = parser.getLocation(start, end);
const value = cmpStr(source, end - 2, end, '*/')
? source.slice(start + 2, end - 2)
: source.slice(start + 2, end);
onComment(value, loc);
}
});
}
const ast = parser.context[context].call(parser, options);
if (!parser.eof) {
parser.error();
}
return ast;
};
return Object.assign(parse, {
SyntaxError: SyntaxError_SyntaxError,
config: parser.config
});
};
// EXTERNAL MODULE: ./node_modules/source-map-js/lib/source-map-generator.js
var source_map_generator = __webpack_require__("./node_modules/source-map-js/lib/source-map-generator.js");
;// ./node_modules/css-tree/lib/generator/sourceMap.js
const trackNodes = new Set(['Atrule', 'Selector', 'Declaration']);
function generateSourceMap(handlers) {
const map = new source_map_generator/* SourceMapGenerator */.x();
const generated = {
line: 1,
column: 0
};
const original = {
line: 0, // should be zero to add first mapping
column: 0
};
const activatedGenerated = {
line: 1,
column: 0
};
const activatedMapping = {
generated: activatedGenerated
};
let line = 1;
let column = 0;
let sourceMappingActive = false;
const origHandlersNode = handlers.node;
handlers.node = function(node) {
if (node.loc && node.loc.start && trackNodes.has(node.type)) {
const nodeLine = node.loc.start.line;
const nodeColumn = node.loc.start.column - 1;
if (original.line !== nodeLine ||
original.column !== nodeColumn) {
original.line = nodeLine;
original.column = nodeColumn;
generated.line = line;
generated.column = column;
if (sourceMappingActive) {
sourceMappingActive = false;
if (generated.line !== activatedGenerated.line ||
generated.column !== activatedGenerated.column) {
map.addMapping(activatedMapping);
}
}
sourceMappingActive = true;
map.addMapping({
source: node.loc.source,
original,
generated
});
}
}
origHandlersNode.call(this, node);
if (sourceMappingActive && trackNodes.has(node.type)) {
activatedGenerated.line = line;
activatedGenerated.column = column;
}
};
const origHandlersEmit = handlers.emit;
handlers.emit = function(value, type, auto) {
for (let i = 0; i < value.length; i++) {
if (value.charCodeAt(i) === 10) { // \n
line++;
column = 0;
} else {
column++;
}
}
origHandlersEmit(value, type, auto);
};
const origHandlersResult = handlers.result;
handlers.result = function() {
if (sourceMappingActive) {
map.addMapping(activatedMapping);
}
return {
css: origHandlersResult(),
map
};
};
return handlers;
};
;// ./node_modules/css-tree/lib/generator/token-before.js
const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
const code = (type, value) => {
if (type === Delim) {
type = value;
}
if (typeof type === 'string') {
const charCode = type.charCodeAt(0);
return charCode > 0x7F ? 0x8000 : charCode << 8;
}
return type;
};
// https://www.w3.org/TR/css-syntax-3/#serialization
// The only requirement for serialization is that it must "round-trip" with parsing,
// that is, parsing the stylesheet must produce the same data structures as parsing,
// serializing, and parsing again, except for consecutive <whitespace-token>s,
// which may be collapsed into a single token.
const specPairs = [
[Ident, Ident],
[Ident, Function],
[Ident, Url],
[Ident, BadUrl],
[Ident, '-'],
[Ident, types_Number],
[Ident, Percentage],
[Ident, Dimension],
[Ident, CDC],
[Ident, LeftParenthesis],
[AtKeyword, Ident],
[AtKeyword, Function],
[AtKeyword, Url],
[AtKeyword, BadUrl],
[AtKeyword, '-'],
[AtKeyword, types_Number],
[AtKeyword, Percentage],
[AtKeyword, Dimension],
[AtKeyword, CDC],
[Hash, Ident],
[Hash, Function],
[Hash, Url],
[Hash, BadUrl],
[Hash, '-'],
[Hash, types_Number],
[Hash, Percentage],
[Hash, Dimension],
[Hash, CDC],
[Dimension, Ident],
[Dimension, Function],
[Dimension, Url],
[Dimension, BadUrl],
[Dimension, '-'],
[Dimension, types_Number],
[Dimension, Percentage],
[Dimension, Dimension],
[Dimension, CDC],
['#', Ident],
['#', Function],
['#', Url],
['#', BadUrl],
['#', '-'],
['#', types_Number],
['#', Percentage],
['#', Dimension],
['#', CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['-', Ident],
['-', Function],
['-', Url],
['-', BadUrl],
['-', '-'],
['-', types_Number],
['-', Percentage],
['-', Dimension],
['-', CDC], // https://github.com/w3c/csswg-drafts/pull/6874
[types_Number, Ident],
[types_Number, Function],
[types_Number, Url],
[types_Number, BadUrl],
[types_Number, types_Number],
[types_Number, Percentage],
[types_Number, Dimension],
[types_Number, '%'],
[types_Number, CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['@', Ident],
['@', Function],
['@', Url],
['@', BadUrl],
['@', '-'],
['@', CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['.', types_Number],
['.', Percentage],
['.', Dimension],
['+', types_Number],
['+', Percentage],
['+', Dimension],
['/', '*']
];
// validate with scripts/generate-safe
const safePairs = specPairs.concat([
[Ident, Hash],
[Dimension, Hash],
[Hash, Hash],
[AtKeyword, LeftParenthesis],
[AtKeyword, types_String],
[AtKeyword, Colon],
[Percentage, Percentage],
[Percentage, Dimension],
[Percentage, Function],
[Percentage, '-'],
[RightParenthesis, Ident],
[RightParenthesis, Function],
[RightParenthesis, Percentage],
[RightParenthesis, Dimension],
[RightParenthesis, Hash],
[RightParenthesis, '-']
]);
function createMap(pairs) {
const isWhiteSpaceRequired = new Set(
pairs.map(([prev, next]) => (code(prev) << 16 | code(next)))
);
return function(prevCode, type, value) {
const nextCode = code(type, value);
const nextCharCode = value.charCodeAt(0);
const emitWs =
(nextCharCode === HYPHENMINUS &&
type !== Ident &&
type !== Function &&
type !== CDC) ||
(nextCharCode === PLUSSIGN)
? isWhiteSpaceRequired.has(prevCode << 16 | nextCharCode << 8)
: isWhiteSpaceRequired.has(prevCode << 16 | nextCode);
if (emitWs) {
this.emit(' ', WhiteSpace, true);
}
return nextCode;
};
}
const spec = createMap(specPairs);
const safe = createMap(safePairs);
;// ./node_modules/css-tree/lib/generator/create.js
const REVERSESOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
function processChildren(node, delimeter) {
if (typeof delimeter === 'function') {
let prev = null;
node.children.forEach(node => {
if (prev !== null) {
delimeter.call(this, prev);
}
this.node(node);
prev = node;
});
return;
}
node.children.forEach(this.node, this);
}
function processChunk(chunk) {
tokenize(chunk, (type, start, end) => {
this.token(type, chunk.slice(start, end));
});
}
function createGenerator(config) {
const types = new Map();
for (let name in config.node) {
const item = config.node[name];
const fn = item.generate || item;
if (typeof fn === 'function') {
types.set(name, item.generate || item);
}
}
return function(node, options) {
let buffer = '';
let prevCode = 0;
let handlers = {
node(node) {
if (types.has(node.type)) {
types.get(node.type).call(publicApi, node);
} else {
throw new Error('Unknown node type: ' + node.type);
}
},
tokenBefore: safe,
token(type, value) {
prevCode = this.tokenBefore(prevCode, type, value);
this.emit(value, type, false);
if (type === Delim && value.charCodeAt(0) === REVERSESOLIDUS) {
this.emit('\n', WhiteSpace, true);
}
},
emit(value) {
buffer += value;
},
result() {
return buffer;
}
};
if (options) {
if (typeof options.decorator === 'function') {
handlers = options.decorator(handlers);
}
if (options.sourceMap) {
handlers = generateSourceMap(handlers);
}
if (options.mode in token_before_namespaceObject) {
handlers.tokenBefore = token_before_namespaceObject[options.mode];
}
}
const publicApi = {
node: (node) => handlers.node(node),
children: processChildren,
token: (type, value) => handlers.token(type, value),
tokenize: processChunk
};
handlers.node(node);
return handlers.result();
};
};
;// ./node_modules/css-tree/lib/convertor/create.js
function createConvertor(walk) {
return {
fromPlainObject(ast) {
walk(ast, {
enter(node) {
if (node.children && node.children instanceof List_List === false) {
node.children = new List_List().fromArray(node.children);
}
}
});
return ast;
},
toPlainObject(ast) {
walk(ast, {
leave(node) {
if (node.children && node.children instanceof List_List) {
node.children = node.children.toArray();
}
}
});
return ast;
}
};
};
;// ./node_modules/css-tree/lib/walker/create.js
const { hasOwnProperty: create_hasOwnProperty } = Object.prototype;
const noop = function() {};
function ensureFunction(value) {
return typeof value === 'function' ? value : noop;
}
function invokeForType(fn, type) {
return function(node, item, list) {
if (node.type === type) {
fn.call(this, node, item, list);
}
};
}
function getWalkersFromStructure(name, nodeType) {
const structure = nodeType.structure;
const walkers = [];
for (const key in structure) {
if (create_hasOwnProperty.call(structure, key) === false) {
continue;
}
let fieldTypes = structure[key];
const walker = {
name: key,
type: false,
nullable: false
};
if (!Array.isArray(fieldTypes)) {
fieldTypes = [fieldTypes];
}
for (const fieldType of fieldTypes) {
if (fieldType === null) {
walker.nullable = true;
} else if (typeof fieldType === 'string') {
walker.type = 'node';
} else if (Array.isArray(fieldType)) {
walker.type = 'list';
}
}
if (walker.type) {
walkers.push(walker);
}
}
if (walkers.length) {
return {
context: nodeType.walkContext,
fields: walkers
};
}
return null;
}
function getTypesFromConfig(config) {
const types = {};
for (const name in config.node) {
if (create_hasOwnProperty.call(config.node, name)) {
const nodeType = config.node[name];
if (!nodeType.structure) {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
types[name] = getWalkersFromStructure(name, nodeType);
}
}
return types;
}
function createTypeIterator(config, reverse) {
const fields = config.fields.slice();
const contextName = config.context;
const useContext = typeof contextName === 'string';
if (reverse) {
fields.reverse();
}
return function(node, context, walk, walkReducer) {
let prevContextValue;
if (useContext) {
prevContextValue = context[contextName];
context[contextName] = node;
}
for (const field of fields) {
const ref = node[field.name];
if (!field.nullable || ref) {
if (field.type === 'list') {
const breakWalk = reverse
? ref.reduceRight(walkReducer, false)
: ref.reduce(walkReducer, false);
if (breakWalk) {
return true;
}
} else if (walk(ref)) {
return true;
}
}
}
if (useContext) {
context[contextName] = prevContextValue;
}
};
}
function createFastTraveralMap({
StyleSheet,
Atrule,
Rule,
Block,
DeclarationList
}) {
return {
Atrule: {
StyleSheet,
Atrule,
Rule,
Block
},
Rule: {
StyleSheet,
Atrule,
Rule,
Block
},
Declaration: {
StyleSheet,
Atrule,
Rule,
Block,
DeclarationList
}
};
}
function createWalker(config) {
const types = getTypesFromConfig(config);
const iteratorsNatural = {};
const iteratorsReverse = {};
const breakWalk = Symbol('break-walk');
const skipNode = Symbol('skip-node');
for (const name in types) {
if (create_hasOwnProperty.call(types, name) && types[name] !== null) {
iteratorsNatural[name] = createTypeIterator(types[name], false);
iteratorsReverse[name] = createTypeIterator(types[name], true);
}
}
const fastTraversalIteratorsNatural = createFastTraveralMap(iteratorsNatural);
const fastTraversalIteratorsReverse = createFastTraveralMap(iteratorsReverse);
const walk = function(root, options) {
function walkNode(node, item, list) {
const enterRet = enter.call(context, node, item, list);
if (enterRet === breakWalk) {
return true;
}
if (enterRet === skipNode) {
return false;
}
if (iterators.hasOwnProperty(node.type)) {
if (iterators[node.type](node, context, walkNode, walkReducer)) {
return true;
}
}
if (leave.call(context, node, item, list) === breakWalk) {
return true;
}
return false;
}
let enter = noop;
let leave = noop;
let iterators = iteratorsNatural;
let walkReducer = (ret, data, item, list) => ret || walkNode(data, item, list);
const context = {
break: breakWalk,
skip: skipNode,
root,
stylesheet: null,
atrule: null,
atrulePrelude: null,
rule: null,
selector: null,
block: null,
declaration: null,
function: null
};
if (typeof options === 'function') {
enter = options;
} else if (options) {
enter = ensureFunction(options.enter);
leave = ensureFunction(options.leave);
if (options.reverse) {
iterators = iteratorsReverse;
}
if (options.visit) {
if (fastTraversalIteratorsNatural.hasOwnProperty(options.visit)) {
iterators = options.reverse
? fastTraversalIteratorsReverse[options.visit]
: fastTraversalIteratorsNatural[options.visit];
} else if (!types.hasOwnProperty(options.visit)) {
throw new Error('Bad value `' + options.visit + '` for `visit` option (should be: ' + Object.keys(types).sort().join(', ') + ')');
}
enter = invokeForType(enter, options.visit);
leave = invokeForType(leave, options.visit);
}
}
if (enter === noop && leave === noop) {
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
}
walkNode(root);
};
walk.break = breakWalk;
walk.skip = skipNode;
walk.find = function(ast, fn) {
let found = null;
walk(ast, function(node, item, list) {
if (fn.call(this, node, item, list)) {
found = node;
return breakWalk;
}
});
return found;
};
walk.findLast = function(ast, fn) {
let found = null;
walk(ast, {
reverse: true,
enter(node, item, list) {
if (fn.call(this, node, item, list)) {
found = node;
return breakWalk;
}
}
});
return found;
};
walk.findAll = function(ast, fn) {
const found = [];
walk(ast, function(node, item, list) {
if (fn.call(this, node, item, list)) {
found.push(node);
}
});
return found;
};
return walk;
};
;// ./node_modules/css-tree/lib/definition-syntax/generate.js
function generate_noop(value) {
return value;
}
function generateMultiplier(multiplier) {
const { min, max, comma } = multiplier;
if (min === 0 && max === 0) {
return comma ? '#?' : '*';
}
if (min === 0 && max === 1) {
return '?';
}
if (min === 1 && max === 0) {
return comma ? '#' : '+';
}
if (min === 1 && max === 1) {
return '';
}
return (
(comma ? '#' : '') +
(min === max
? '{' + min + '}'
: '{' + min + ',' + (max !== 0 ? max : '') + '}'
)
);
}
function generateTypeOpts(node) {
switch (node.type) {
case 'Range':
return (
' [' +
(node.min === null ? '-∞' : node.min) +
',' +
(node.max === null ? '∞' : node.max) +
']'
);
default:
throw new Error('Unknown node type `' + node.type + '`');
}
}
function generateSequence(node, decorate, forceBraces, compact) {
const combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' ';
const result = node.terms
.map(term => internalGenerate(term, decorate, forceBraces, compact))
.join(combinator);
if (node.explicit || forceBraces) {
return (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]');
}
return result;
}
function internalGenerate(node, decorate, forceBraces, compact) {
let result;
switch (node.type) {
case 'Group':
result =
generateSequence(node, decorate, forceBraces, compact) +
(node.disallowEmpty ? '!' : '');
break;
case 'Multiplier':
// return since node is a composition
return (
internalGenerate(node.term, decorate, forceBraces, compact) +
decorate(generateMultiplier(node), node)
);
case 'Type':
result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>';
break;
case 'Property':
result = '<\'' + node.name + '\'>';
break;
case 'Keyword':
result = node.name;
break;
case 'AtKeyword':
result = '@' + node.name;
break;
case 'Function':
result = node.name + '(';
break;
case 'String':
case 'Token':
result = node.value;
break;
case 'Comma':
result = ',';
break;
default:
throw new Error('Unknown node type `' + node.type + '`');
}
return decorate(result, node);
}
function generate(node, options) {
let decorate = generate_noop;
let forceBraces = false;
let compact = false;
if (typeof options === 'function') {
decorate = options;
} else if (options) {
forceBraces = Boolean(options.forceBraces);
compact = Boolean(options.compact);
if (typeof options.decorate === 'function') {
decorate = options.decorate;
}
}
return internalGenerate(node, decorate, forceBraces, compact);
};
;// ./node_modules/css-tree/lib/lexer/error.js
const defaultLoc = { offset: 0, line: 1, column: 1 };
function locateMismatch(matchResult, node) {
const tokens = matchResult.tokens;
const longestMatch = matchResult.longestMatch;
const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null;
const badNode = mismatchNode !== node ? mismatchNode : null;
let mismatchOffset = 0;
let mismatchLength = 0;
let entries = 0;
let css = '';
let start;
let end;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i].value;
if (i === longestMatch) {
mismatchLength = token.length;
mismatchOffset = css.length;
}
if (badNode !== null && tokens[i].node === badNode) {
if (i <= longestMatch) {
entries++;
} else {
entries = 0;
}
}
css += token;
}
if (longestMatch === tokens.length || entries > 1) { // last
start = fromLoc(badNode || node, 'end') || buildLoc(defaultLoc, css);
end = buildLoc(start);
} else {
start = fromLoc(badNode, 'start') ||
buildLoc(fromLoc(node, 'start') || defaultLoc, css.slice(0, mismatchOffset));
end = fromLoc(badNode, 'end') ||
buildLoc(start, css.substr(mismatchOffset, mismatchLength));
}
return {
css,
mismatchOffset,
mismatchLength,
start,
end
};
}
function fromLoc(node, point) {
const value = node && node.loc && node.loc[point];
if (value) {
return 'line' in value ? buildLoc(value) : value;
}
return null;
}
function buildLoc({ offset, line, column }, extra) {
const loc = {
offset,
line,
column
};
if (extra) {
const lines = extra.split(/\n|\r\n?|\f/);
loc.offset += extra.length;
loc.line += lines.length - 1;
loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1;
}
return loc;
}
const SyntaxReferenceError = function(type, referenceName) {
const error = createCustomError(
'SyntaxReferenceError',
type + (referenceName ? ' `' + referenceName + '`' : '')
);
error.reference = referenceName;
return error;
};
const SyntaxMatchError = function(message, syntax, node, matchResult) {
const error = createCustomError('SyntaxMatchError', message);
const {
css,
mismatchOffset,
mismatchLength,
start,
end
} = locateMismatch(matchResult, node);
error.rawMessage = message;
error.syntax = syntax ? generate(syntax) : '<generic>';
error.css = css;
error.mismatchOffset = mismatchOffset;
error.mismatchLength = mismatchLength;
error.message = message + '\n' +
' syntax: ' + error.syntax + '\n' +
' value: ' + (css || '<empty string>') + '\n' +
' --------' + new Array(error.mismatchOffset + 1).join('-') + '^';
Object.assign(error, start);
error.loc = {
source: (node && node.loc && node.loc.source) || '<unknown>',
start,
end
};
return error;
};
;// ./node_modules/css-tree/lib/utils/names.js
const keywords = new Map();
const properties = new Map();
const names_HYPHENMINUS = 45; // '-'.charCodeAt()
const keyword = getKeywordDescriptor;
const names_property = getPropertyDescriptor;
const vendorPrefix = (/* unused pure expression or super */ null && (getVendorPrefix));
function isCustomProperty(str, offset) {
offset = offset || 0;
return str.length - offset >= 2 &&
str.charCodeAt(offset) === names_HYPHENMINUS &&
str.charCodeAt(offset + 1) === names_HYPHENMINUS;
}
function getVendorPrefix(str, offset) {
offset = offset || 0;
// verdor prefix should be at least 3 chars length
if (str.length - offset >= 3) {
// vendor prefix starts with hyper minus following non-hyper minus
if (str.charCodeAt(offset) === names_HYPHENMINUS &&
str.charCodeAt(offset + 1) !== names_HYPHENMINUS) {
// vendor prefix should contain a hyper minus at the ending
const secondDashIndex = str.indexOf('-', offset + 2);
if (secondDashIndex !== -1) {
return str.substring(offset, secondDashIndex + 1);
}
}
}
return '';
}
function getKeywordDescriptor(keyword) {
if (keywords.has(keyword)) {
return keywords.get(keyword);
}
const name = keyword.toLowerCase();
let descriptor = keywords.get(name);
if (descriptor === undefined) {
const custom = isCustomProperty(name, 0);
const vendor = !custom ? getVendorPrefix(name, 0) : '';
descriptor = Object.freeze({
basename: name.substr(vendor.length),
name,
prefix: vendor,
vendor,
custom
});
}
keywords.set(keyword, descriptor);
return descriptor;
}
function getPropertyDescriptor(property) {
if (properties.has(property)) {
return properties.get(property);
}
let name = property;
let hack = property[0];
if (hack === '/') {
hack = property[1] === '/' ? '//' : '/';
} else if (hack !== '_' &&
hack !== '*' &&
hack !== '$' &&
hack !== '#' &&
hack !== '+' &&
hack !== '&') {
hack = '';
}
const custom = isCustomProperty(name, hack.length);
// re-use result when possible (the same as for lower case)
if (!custom) {
name = name.toLowerCase();
if (properties.has(name)) {
const descriptor = properties.get(name);
properties.set(property, descriptor);
return descriptor;
}
}
const vendor = !custom ? getVendorPrefix(name, hack.length) : '';
const prefix = name.substr(0, hack.length + vendor.length);
const descriptor = Object.freeze({
basename: name.substr(prefix.length),
name: name.substr(hack.length),
hack,
vendor,
prefix,
custom
});
properties.set(property, descriptor);
return descriptor;
}
;// ./node_modules/css-tree/lib/lexer/generic-const.js
// https://drafts.csswg.org/css-cascade-5/
const cssWideKeywords = [
'initial',
'inherit',
'unset',
'revert',
'revert-layer'
];
;// ./node_modules/css-tree/lib/lexer/generic-an-plus-b.js
const generic_an_plus_b_PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
const generic_an_plus_b_HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
const generic_an_plus_b_N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
const DISALLOW_SIGN = true;
const ALLOW_SIGN = false;
function isDelim(token, code) {
return token !== null && token.type === Delim && token.value.charCodeAt(0) === code;
}
function skipSC(token, offset, getNextToken) {
while (token !== null && (token.type === WhiteSpace || token.type === Comment)) {
token = getNextToken(++offset);
}
return offset;
}
function checkInteger(token, valueOffset, disallowSign, offset) {
if (!token) {
return 0;
}
const code = token.value.charCodeAt(valueOffset);
if (code === generic_an_plus_b_PLUSSIGN || code === generic_an_plus_b_HYPHENMINUS) {
if (disallowSign) {
// Number sign is not allowed
return 0;
}
valueOffset++;
}
for (; valueOffset < token.value.length; valueOffset++) {
if (!isDigit(token.value.charCodeAt(valueOffset))) {
// Integer is expected
return 0;
}
}
return offset + 1;
}
// ... <signed-integer>
// ... ['+' | '-'] <signless-integer>
function consumeB(token, offset_, getNextToken) {
let sign = false;
let offset = skipSC(token, offset_, getNextToken);
token = getNextToken(offset);
if (token === null) {
return offset_;
}
if (token.type !== types_Number) {
if (isDelim(token, generic_an_plus_b_PLUSSIGN) || isDelim(token, generic_an_plus_b_HYPHENMINUS)) {
sign = true;
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
if (token === null || token.type !== types_Number) {
return 0;
}
} else {
return offset_;
}
}
if (!sign) {
const code = token.value.charCodeAt(0);
if (code !== generic_an_plus_b_PLUSSIGN && code !== generic_an_plus_b_HYPHENMINUS) {
// Number sign is expected
return 0;
}
}
return checkInteger(token, sign ? 0 : 1, sign, offset);
}
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
function anPlusB(token, getNextToken) {
/* eslint-disable brace-style*/
let offset = 0;
if (!token) {
return 0;
}
// <integer>
if (token.type === types_Number) {
return checkInteger(token, 0, ALLOW_SIGN, offset); // b
}
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
// -n- <signless-integer>
// <dashndashdigit-ident>
else if (token.type === Ident && token.value.charCodeAt(0) === generic_an_plus_b_HYPHENMINUS) {
// expect 1st char is N
if (!cmpChar(token.value, 1, generic_an_plus_b_N)) {
return 0;
}
switch (token.value.length) {
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
case 2:
return consumeB(getNextToken(++offset), offset, getNextToken);
// -n- <signless-integer>
case 3:
if (token.value.charCodeAt(2) !== generic_an_plus_b_HYPHENMINUS) {
return 0;
}
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger(token, 0, DISALLOW_SIGN, offset);
// <dashndashdigit-ident>
default:
if (token.value.charCodeAt(2) !== generic_an_plus_b_HYPHENMINUS) {
return 0;
}
return checkInteger(token, 3, DISALLOW_SIGN, offset);
}
}
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
// '+'? n- <signless-integer>
// '+'? <ndashdigit-ident>
else if (token.type === Ident || (isDelim(token, generic_an_plus_b_PLUSSIGN) && getNextToken(offset + 1).type === Ident)) {
// just ignore a plus
if (token.type !== Ident) {
token = getNextToken(++offset);
}
if (token === null || !cmpChar(token.value, 0, generic_an_plus_b_N)) {
return 0;
}
switch (token.value.length) {
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
case 1:
return consumeB(getNextToken(++offset), offset, getNextToken);
// '+'? n- <signless-integer>
case 2:
if (token.value.charCodeAt(1) !== generic_an_plus_b_HYPHENMINUS) {
return 0;
}
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger(token, 0, DISALLOW_SIGN, offset);
// '+'? <ndashdigit-ident>
default:
if (token.value.charCodeAt(1) !== generic_an_plus_b_HYPHENMINUS) {
return 0;
}
return checkInteger(token, 2, DISALLOW_SIGN, offset);
}
}
// <ndashdigit-dimension>
// <ndash-dimension> <signless-integer>
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
else if (token.type === Dimension) {
let code = token.value.charCodeAt(0);
let sign = code === generic_an_plus_b_PLUSSIGN || code === generic_an_plus_b_HYPHENMINUS ? 1 : 0;
let i = sign;
for (; i < token.value.length; i++) {
if (!isDigit(token.value.charCodeAt(i))) {
break;
}
}
if (i === sign) {
// Integer is expected
return 0;
}
if (!cmpChar(token.value, i, generic_an_plus_b_N)) {
return 0;
}
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
if (i + 1 === token.value.length) {
return consumeB(getNextToken(++offset), offset, getNextToken);
} else {
if (token.value.charCodeAt(i + 1) !== generic_an_plus_b_HYPHENMINUS) {
return 0;
}
// <ndash-dimension> <signless-integer>
if (i + 2 === token.value.length) {
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger(token, 0, DISALLOW_SIGN, offset);
}
// <ndashdigit-dimension>
else {
return checkInteger(token, i + 2, DISALLOW_SIGN, offset);
}
}
}
return 0;
};
;// ./node_modules/css-tree/lib/lexer/generic-urange.js
const generic_urange_PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
const generic_urange_HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
const QUESTIONMARK = 0x003F; // U+003F QUESTION MARK (?)
const U = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
function generic_urange_isDelim(token, code) {
return token !== null && token.type === Delim && token.value.charCodeAt(0) === code;
}
function startsWith(token, code) {
return token.value.charCodeAt(0) === code;
}
function hexSequence(token, offset, allowDash) {
let hexlen = 0;
for (let pos = offset; pos < token.value.length; pos++) {
const code = token.value.charCodeAt(pos);
if (code === generic_urange_HYPHENMINUS && allowDash && hexlen !== 0) {
hexSequence(token, offset + hexlen + 1, false);
return 6; // dissallow following question marks
}
if (!isHexDigit(code)) {
return 0; // not a hex digit
}
if (++hexlen > 6) {
return 0; // too many hex digits
};
}
return hexlen;
}
function withQuestionMarkSequence(consumed, length, getNextToken) {
if (!consumed) {
return 0; // nothing consumed
}
while (generic_urange_isDelim(getNextToken(length), QUESTIONMARK)) {
if (++consumed > 6) {
return 0; // too many question marks
}
length++;
}
return length;
}
// https://drafts.csswg.org/css-syntax/#urange
// Informally, the <urange> production has three forms:
// U+0001
// Defines a range consisting of a single code point, in this case the code point "1".
// U+0001-00ff
// Defines a range of codepoints between the first and the second value, in this case
// the range between "1" and "ff" (255 in decimal) inclusive.
// U+00??
// Defines a range of codepoints where the "?" characters range over all hex digits,
// in this case defining the same as the value U+0000-00ff.
// In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
//
// <urange> =
// u '+' <ident-token> '?'* |
// u <dimension-token> '?'* |
// u <number-token> '?'* |
// u <number-token> <dimension-token> |
// u <number-token> <number-token> |
// u '+' '?'+
function urange(token, getNextToken) {
let length = 0;
// should start with `u` or `U`
if (token === null || token.type !== Ident || !cmpChar(token.value, 0, U)) {
return 0;
}
token = getNextToken(++length);
if (token === null) {
return 0;
}
// u '+' <ident-token> '?'*
// u '+' '?'+
if (generic_urange_isDelim(token, generic_urange_PLUSSIGN)) {
token = getNextToken(++length);
if (token === null) {
return 0;
}
if (token.type === Ident) {
// u '+' <ident-token> '?'*
return withQuestionMarkSequence(hexSequence(token, 0, true), ++length, getNextToken);
}
if (generic_urange_isDelim(token, QUESTIONMARK)) {
// u '+' '?'+
return withQuestionMarkSequence(1, ++length, getNextToken);
}
// Hex digit or question mark is expected
return 0;
}
// u <number-token> '?'*
// u <number-token> <dimension-token>
// u <number-token> <number-token>
if (token.type === types_Number) {
const consumedHexLength = hexSequence(token, 1, true);
if (consumedHexLength === 0) {
return 0;
}
token = getNextToken(++length);
if (token === null) {
// u <number-token> <eof>
return length;
}
if (token.type === Dimension || token.type === types_Number) {
// u <number-token> <dimension-token>
// u <number-token> <number-token>
if (!startsWith(token, generic_urange_HYPHENMINUS) || !hexSequence(token, 1, false)) {
return 0;
}
return length + 1;
}
// u <number-token> '?'*
return withQuestionMarkSequence(consumedHexLength, length, getNextToken);
}
// u <dimension-token> '?'*
if (token.type === Dimension) {
return withQuestionMarkSequence(hexSequence(token, 1, true), ++length, getNextToken);
}
return 0;
};
;// ./node_modules/css-tree/lib/lexer/generic.js
const calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc('];
const generic_balancePair = new Map([
[Function, RightParenthesis],
[LeftParenthesis, RightParenthesis],
[LeftSquareBracket, RightSquareBracket],
[LeftCurlyBracket, RightCurlyBracket]
]);
// safe char code getter
function charCodeAt(str, index) {
return index < str.length ? str.charCodeAt(index) : 0;
}
function eqStr(actual, expected) {
return cmpStr(actual, 0, actual.length, expected);
}
function eqStrAny(actual, expected) {
for (let i = 0; i < expected.length; i++) {
if (eqStr(actual, expected[i])) {
return true;
}
}
return false;
}
// IE postfix hack, i.e. 123\0 or 123px\9
function isPostfixIeHack(str, offset) {
if (offset !== str.length - 2) {
return false;
}
return (
charCodeAt(str, offset) === 0x005C && // U+005C REVERSE SOLIDUS (\)
isDigit(charCodeAt(str, offset + 1))
);
}
function outOfRange(opts, value, numEnd) {
if (opts && opts.type === 'Range') {
const num = Number(
numEnd !== undefined && numEnd !== value.length
? value.substr(0, numEnd)
: value
);
if (isNaN(num)) {
return true;
}
// FIXME: when opts.min is a string it's a dimension, skip a range validation
// for now since it requires a type covertation which is not implmented yet
if (opts.min !== null && num < opts.min && typeof opts.min !== 'string') {
return true;
}
// FIXME: when opts.max is a string it's a dimension, skip a range validation
// for now since it requires a type covertation which is not implmented yet
if (opts.max !== null && num > opts.max && typeof opts.max !== 'string') {
return true;
}
}
return false;
}
function consumeFunction(token, getNextToken) {
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// balanced token consuming
scan:
do {
switch (token.type) {
case RightCurlyBracket:
case RightParenthesis:
case RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
if (balanceStash.length === 0) {
length++;
break scan;
}
break;
case Function:
case LeftParenthesis:
case LeftSquareBracket:
case LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = generic_balancePair.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// TODO: implement
// can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
// https://drafts.csswg.org/css-values/#calc-notation
function calc(next) {
return function(token, getNextToken, opts) {
if (token === null) {
return 0;
}
if (token.type === Function && eqStrAny(token.value, calcFunctionNames)) {
return consumeFunction(token, getNextToken);
}
return next(token, getNextToken, opts);
};
}
function tokenType(expectedTokenType) {
return function(token) {
if (token === null || token.type !== expectedTokenType) {
return 0;
}
return 1;
};
}
// =========================
// Complex types
//
// https://drafts.csswg.org/css-values-4/#custom-idents
// 4.2. Author-defined Identifiers: the <custom-ident> type
// Some properties accept arbitrary author-defined identifiers as a component value.
// This generic data type is denoted by <custom-ident>, and represents any valid CSS identifier
// that would not be misinterpreted as a pre-defined keyword in that property’s value definition.
//
// See also: https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
function customIdent(token) {
if (token === null || token.type !== Ident) {
return 0;
}
const name = token.value.toLowerCase();
// The CSS-wide keywords are not valid <custom-ident>s
if (eqStrAny(name, cssWideKeywords)) {
return 0;
}
// The default keyword is reserved and is also not a valid <custom-ident>
if (eqStr(name, 'default')) {
return 0;
}
// TODO: ignore property specific keywords (as described https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)
// Specifications using <custom-ident> must specify clearly what other keywords
// are excluded from <custom-ident>, if any—for example by saying that any pre-defined keywords
// in that property’s value definition are excluded. Excluded keywords are excluded
// in all ASCII case permutations.
return 1;
}
// https://drafts.csswg.org/css-variables/#typedef-custom-property-name
// A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
// The <custom-property-name> production corresponds to this: it’s defined as any valid identifier
// that starts with two dashes, except -- itself, which is reserved for future use by CSS.
// NOTE: Current implementation treat `--` as a valid name since most (all?) major browsers treat it as valid.
function customPropertyName(token) {
// ... defined as any valid identifier
if (token === null || token.type !== Ident) {
return 0;
}
// ... that starts with two dashes (U+002D HYPHEN-MINUS)
if (charCodeAt(token.value, 0) !== 0x002D || charCodeAt(token.value, 1) !== 0x002D) {
return 0;
}
return 1;
}
// https://drafts.csswg.org/css-color-4/#hex-notation
// The syntax of a <hex-color> is a <hash-token> token whose value consists of 3, 4, 6, or 8 hexadecimal digits.
// In other words, a hex color is written as a hash character, "#", followed by some number of digits 0-9 or
// letters a-f (the case of the letters doesn’t matter - #00ff00 is identical to #00FF00).
function hexColor(token) {
if (token === null || token.type !== Hash) {
return 0;
}
const length = token.value.length;
// valid values (length): #rgb (4), #rgba (5), #rrggbb (7), #rrggbbaa (9)
if (length !== 4 && length !== 5 && length !== 7 && length !== 9) {
return 0;
}
for (let i = 1; i < length; i++) {
if (!isHexDigit(charCodeAt(token.value, i))) {
return 0;
}
}
return 1;
}
function idSelector(token) {
if (token === null || token.type !== Hash) {
return 0;
}
if (!isIdentifierStart(charCodeAt(token.value, 1), charCodeAt(token.value, 2), charCodeAt(token.value, 3))) {
return 0;
}
return 1;
}
// https://drafts.csswg.org/css-syntax/#any-value
// It represents the entirety of what a valid declaration can have as its value.
function declarationValue(token, getNextToken) {
if (!token) {
return 0;
}
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// The <declaration-value> production matches any sequence of one or more tokens,
// so long as the sequence does not contain ...
scan:
do {
switch (token.type) {
// ... <bad-string-token>, <bad-url-token>,
case BadString:
case BadUrl:
break scan;
// ... unmatched <)-token>, <]-token>, or <}-token>,
case RightCurlyBracket:
case RightParenthesis:
case RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
break;
// ... or top-level <semicolon-token> tokens
case Semicolon:
if (balanceCloseType === 0) {
break scan;
}
break;
// ... or <delim-token> tokens with a value of "!"
case Delim:
if (balanceCloseType === 0 && token.value === '!') {
break scan;
}
break;
case Function:
case LeftParenthesis:
case LeftSquareBracket:
case LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = generic_balancePair.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// https://drafts.csswg.org/css-syntax/#any-value
// The <any-value> production is identical to <declaration-value>, but also
// allows top-level <semicolon-token> tokens and <delim-token> tokens
// with a value of "!". It represents the entirety of what valid CSS can be in any context.
function anyValue(token, getNextToken) {
if (!token) {
return 0;
}
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// The <any-value> production matches any sequence of one or more tokens,
// so long as the sequence ...
scan:
do {
switch (token.type) {
// ... does not contain <bad-string-token>, <bad-url-token>,
case BadString:
case BadUrl:
break scan;
// ... unmatched <)-token>, <]-token>, or <}-token>,
case RightCurlyBracket:
case RightParenthesis:
case RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
break;
case Function:
case LeftParenthesis:
case LeftSquareBracket:
case LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = generic_balancePair.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// =========================
// Dimensions
//
function dimension(type) {
if (type) {
type = new Set(type);
}
return function(token, getNextToken, opts) {
if (token === null || token.type !== Dimension) {
return 0;
}
const numberEnd = consumeNumber(token.value, 0);
// check unit
if (type !== null) {
// check for IE postfix hack, i.e. 123px\0 or 123px\9
const reverseSolidusOffset = token.value.indexOf('\\', numberEnd);
const unit = reverseSolidusOffset === -1 || !isPostfixIeHack(token.value, reverseSolidusOffset)
? token.value.substr(numberEnd)
: token.value.substring(numberEnd, reverseSolidusOffset);
if (type.has(unit.toLowerCase()) === false) {
return 0;
}
}
// check range if specified
if (outOfRange(opts, token.value, numberEnd)) {
return 0;
}
return 1;
};
}
// =========================
// Percentage
//
// §5.5. Percentages: the <percentage> type
// https://drafts.csswg.org/css-values-4/#percentages
function percentage(token, getNextToken, opts) {
// ... corresponds to the <percentage-token> production
if (token === null || token.type !== Percentage) {
return 0;
}
// check range if specified
if (outOfRange(opts, token.value, token.value.length - 1)) {
return 0;
}
return 1;
}
// =========================
// Numeric
//
// https://drafts.csswg.org/css-values-4/#numbers
// The value <zero> represents a literal number with the value 0. Expressions that merely
// evaluate to a <number> with the value 0 (for example, calc(0)) do not match <zero>;
// only literal <number-token>s do.
function zero(next) {
if (typeof next !== 'function') {
next = function() {
return 0;
};
}
return function(token, getNextToken, opts) {
if (token !== null && token.type === types_Number) {
if (Number(token.value) === 0) {
return 1;
}
}
return next(token, getNextToken, opts);
};
}
// § 5.3. Real Numbers: the <number> type
// https://drafts.csswg.org/css-values-4/#numbers
// Number values are denoted by <number>, and represent real numbers, possibly with a fractional component.
// ... It corresponds to the <number-token> production
function number(token, getNextToken, opts) {
if (token === null) {
return 0;
}
const numberEnd = consumeNumber(token.value, 0);
const isNumber = numberEnd === token.value.length;
if (!isNumber && !isPostfixIeHack(token.value, numberEnd)) {
return 0;
}
// check range if specified
if (outOfRange(opts, token.value, numberEnd)) {
return 0;
}
return 1;
}
// §5.2. Integers: the <integer> type
// https://drafts.csswg.org/css-values-4/#integers
function integer(token, getNextToken, opts) {
// ... corresponds to a subset of the <number-token> production
if (token === null || token.type !== types_Number) {
return 0;
}
// The first digit of an integer may be immediately preceded by `-` or `+` to indicate the integer’s sign.
let i = charCodeAt(token.value, 0) === 0x002B || // U+002B PLUS SIGN (+)
charCodeAt(token.value, 0) === 0x002D ? 1 : 0; // U+002D HYPHEN-MINUS (-)
// When written literally, an integer is one or more decimal digits 0 through 9 ...
for (; i < token.value.length; i++) {
if (!isDigit(charCodeAt(token.value, i))) {
return 0;
}
}
// check range if specified
if (outOfRange(opts, token.value, i)) {
return 0;
}
return 1;
}
// token types
const tokenTypes = {
'ident-token': tokenType(Ident),
'function-token': tokenType(Function),
'at-keyword-token': tokenType(AtKeyword),
'hash-token': tokenType(Hash),
'string-token': tokenType(types_String),
'bad-string-token': tokenType(BadString),
'url-token': tokenType(Url),
'bad-url-token': tokenType(BadUrl),
'delim-token': tokenType(Delim),
'number-token': tokenType(types_Number),
'percentage-token': tokenType(Percentage),
'dimension-token': tokenType(Dimension),
'whitespace-token': tokenType(WhiteSpace),
'CDO-token': tokenType(CDO),
'CDC-token': tokenType(CDC),
'colon-token': tokenType(Colon),
'semicolon-token': tokenType(Semicolon),
'comma-token': tokenType(Comma),
'[-token': tokenType(LeftSquareBracket),
']-token': tokenType(RightSquareBracket),
'(-token': tokenType(LeftParenthesis),
')-token': tokenType(RightParenthesis),
'{-token': tokenType(LeftCurlyBracket),
'}-token': tokenType(RightCurlyBracket)
};
// token production types
const productionTypes = {
// token type aliases
'string': tokenType(types_String),
'ident': tokenType(Ident),
// percentage
'percentage': calc(percentage),
// numeric
'zero': zero(),
'number': calc(number),
'integer': calc(integer),
// complex types
'custom-ident': customIdent,
'custom-property-name': customPropertyName,
'hex-color': hexColor,
'id-selector': idSelector, // element( <id-selector> )
'an-plus-b': anPlusB,
'urange': urange,
'declaration-value': declarationValue,
'any-value': anyValue
};
const unitGroups = (/* unused pure expression or super */ null && ([
'length',
'angle',
'time',
'frequency',
'resolution',
'flex',
'decibel',
'semitones'
]));
// dimensions types depend on units set
function createDemensionTypes(units) {
const {
angle,
decibel,
frequency,
flex,
length,
resolution,
semitones,
time
} = units || {};
return {
'dimension': calc(dimension(null)),
'angle': calc(dimension(angle)),
'decibel': calc(dimension(decibel)),
'frequency': calc(dimension(frequency)),
'flex': calc(dimension(flex)),
'length': calc(zero(dimension(length))),
'resolution': calc(dimension(resolution)),
'semitones': calc(dimension(semitones)),
'time': calc(dimension(time))
};
}
function createGenericTypes(units) {
return {
...tokenTypes,
...productionTypes,
...createDemensionTypes(units)
};
};
;// ./node_modules/css-tree/lib/lexer/units.js
const units_length = [
// absolute length units https://www.w3.org/TR/css-values-3/#lengths
'cm', 'mm', 'q', 'in', 'pt', 'pc', 'px',
// font-relative length units https://drafts.csswg.org/css-values-4/#font-relative-lengths
'em', 'rem',
'ex', 'rex',
'cap', 'rcap',
'ch', 'rch',
'ic', 'ric',
'lh', 'rlh',
// viewport-percentage lengths https://drafts.csswg.org/css-values-4/#viewport-relative-lengths
'vw', 'svw', 'lvw', 'dvw',
'vh', 'svh', 'lvh', 'dvh',
'vi', 'svi', 'lvi', 'dvi',
'vb', 'svb', 'lvb', 'dvb',
'vmin', 'svmin', 'lvmin', 'dvmin',
'vmax', 'svmax', 'lvmax', 'dvmax',
// container relative lengths https://drafts.csswg.org/css-contain-3/#container-lengths
'cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'
];
const angle = ['deg', 'grad', 'rad', 'turn']; // https://www.w3.org/TR/css-values-3/#angles
const time = ['s', 'ms']; // https://www.w3.org/TR/css-values-3/#time
const frequency = ['hz', 'khz']; // https://www.w3.org/TR/css-values-3/#frequency
const resolution = ['dpi', 'dpcm', 'dppx', 'x']; // https://www.w3.org/TR/css-values-3/#resolution
const flex = ['fr']; // https://drafts.csswg.org/css-grid/#fr-unit
const decibel = ['db']; // https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume
const semitones = ['st']; // https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch
;// ./node_modules/css-tree/lib/definition-syntax/SyntaxError.js
function definition_syntax_SyntaxError_SyntaxError(message, input, offset) {
return Object.assign(createCustomError('SyntaxError', message), {
input,
offset,
rawMessage: message,
message: message + '\n' +
' ' + input + '\n' +
'--' + new Array((offset || input.length) + 1).join('-') + '^'
});
};
;// ./node_modules/css-tree/lib/definition-syntax/tokenizer.js
const TAB = 9;
const tokenizer_N = 10;
const tokenizer_F = 12;
const tokenizer_R = 13;
const SPACE = 32;
class Tokenizer {
constructor(str) {
this.str = str;
this.pos = 0;
}
charCodeAt(pos) {
return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
}
charCode() {
return this.charCodeAt(this.pos);
}
nextCharCode() {
return this.charCodeAt(this.pos + 1);
}
nextNonWsCode(pos) {
return this.charCodeAt(this.findWsEnd(pos));
}
findWsEnd(pos) {
for (; pos < this.str.length; pos++) {
const code = this.str.charCodeAt(pos);
if (code !== tokenizer_R && code !== tokenizer_N && code !== tokenizer_F && code !== SPACE && code !== TAB) {
break;
}
}
return pos;
}
substringToPos(end) {
return this.str.substring(this.pos, this.pos = end);
}
eat(code) {
if (this.charCode() !== code) {
this.error('Expect `' + String.fromCharCode(code) + '`');
}
this.pos++;
}
peek() {
return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
}
error(message) {
throw new definition_syntax_SyntaxError_SyntaxError(message, this.str, this.pos);
}
};
;// ./node_modules/css-tree/lib/definition-syntax/parse.js
const parse_TAB = 9;
const parse_N = 10;
const parse_F = 12;
const parse_R = 13;
const parse_SPACE = 32;
const parse_EXCLAMATIONMARK = 33; // !
const parse_NUMBERSIGN = 35; // #
const AMPERSAND = 38; // &
const APOSTROPHE = 39; // '
const LEFTPARENTHESIS = 40; // (
const RIGHTPARENTHESIS = 41; // )
const ASTERISK = 42; // *
const parse_PLUSSIGN = 43; // +
const COMMA = 44; // ,
const HYPERMINUS = 45; // -
const LESSTHANSIGN = 60; // <
const GREATERTHANSIGN = 62; // >
const parse_QUESTIONMARK = 63; // ?
const COMMERCIALAT = 64; // @
const LEFTSQUAREBRACKET = 91; // [
const RIGHTSQUAREBRACKET = 93; // ]
const parse_LEFTCURLYBRACKET = 123; // {
const VERTICALLINE = 124; // |
const RIGHTCURLYBRACKET = 125; // }
const INFINITY = 8734; // ∞
const NAME_CHAR = new Uint8Array(128).map((_, idx) =>
/[a-zA-Z0-9\-]/.test(String.fromCharCode(idx)) ? 1 : 0
);
const COMBINATOR_PRECEDENCE = {
' ': 1,
'&&': 2,
'||': 3,
'|': 4
};
function scanSpaces(tokenizer) {
return tokenizer.substringToPos(
tokenizer.findWsEnd(tokenizer.pos)
);
}
function scanWord(tokenizer) {
let end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
const code = tokenizer.str.charCodeAt(end);
if (code >= 128 || NAME_CHAR[code] === 0) {
break;
}
}
if (tokenizer.pos === end) {
tokenizer.error('Expect a keyword');
}
return tokenizer.substringToPos(end);
}
function scanNumber(tokenizer) {
let end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
const code = tokenizer.str.charCodeAt(end);
if (code < 48 || code > 57) {
break;
}
}
if (tokenizer.pos === end) {
tokenizer.error('Expect a number');
}
return tokenizer.substringToPos(end);
}
function scanString(tokenizer) {
const end = tokenizer.str.indexOf('\'', tokenizer.pos + 1);
if (end === -1) {
tokenizer.pos = tokenizer.str.length;
tokenizer.error('Expect an apostrophe');
}
return tokenizer.substringToPos(end + 1);
}
function readMultiplierRange(tokenizer) {
let min = null;
let max = null;
tokenizer.eat(parse_LEFTCURLYBRACKET);
min = scanNumber(tokenizer);
if (tokenizer.charCode() === COMMA) {
tokenizer.pos++;
if (tokenizer.charCode() !== RIGHTCURLYBRACKET) {
max = scanNumber(tokenizer);
}
} else {
max = min;
}
tokenizer.eat(RIGHTCURLYBRACKET);
return {
min: Number(min),
max: max ? Number(max) : 0
};
}
function readMultiplier(tokenizer) {
let range = null;
let comma = false;
switch (tokenizer.charCode()) {
case ASTERISK:
tokenizer.pos++;
range = {
min: 0,
max: 0
};
break;
case parse_PLUSSIGN:
tokenizer.pos++;
range = {
min: 1,
max: 0
};
break;
case parse_QUESTIONMARK:
tokenizer.pos++;
range = {
min: 0,
max: 1
};
break;
case parse_NUMBERSIGN:
tokenizer.pos++;
comma = true;
if (tokenizer.charCode() === parse_LEFTCURLYBRACKET) {
range = readMultiplierRange(tokenizer);
} else if (tokenizer.charCode() === parse_QUESTIONMARK) {
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > the # and ? multipliers may be stacked as #?
// In this case just treat "#?" as a single multiplier
// { min: 0, max: 0, comma: true }
tokenizer.pos++;
range = {
min: 0,
max: 0
};
} else {
range = {
min: 1,
max: 0
};
}
break;
case parse_LEFTCURLYBRACKET:
range = readMultiplierRange(tokenizer);
break;
default:
return null;
}
return {
type: 'Multiplier',
comma,
min: range.min,
max: range.max,
term: null
};
}
function maybeMultiplied(tokenizer, node) {
const multiplier = readMultiplier(tokenizer);
if (multiplier !== null) {
multiplier.term = node;
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > The + and # multipliers may be stacked as +#;
// Represent "+#" as nested multipliers:
// { ...<multiplier #>,
// term: {
// ...<multipler +>,
// term: node
// }
// }
if (tokenizer.charCode() === parse_NUMBERSIGN &&
tokenizer.charCodeAt(tokenizer.pos - 1) === parse_PLUSSIGN) {
return maybeMultiplied(tokenizer, multiplier);
}
return multiplier;
}
return node;
}
function maybeToken(tokenizer) {
const ch = tokenizer.peek();
if (ch === '') {
return null;
}
return {
type: 'Token',
value: ch
};
}
function readProperty(tokenizer) {
let name;
tokenizer.eat(LESSTHANSIGN);
tokenizer.eat(APOSTROPHE);
name = scanWord(tokenizer);
tokenizer.eat(APOSTROPHE);
tokenizer.eat(GREATERTHANSIGN);
return maybeMultiplied(tokenizer, {
type: 'Property',
name
});
}
// https://drafts.csswg.org/css-values-3/#numeric-ranges
// 4.1. Range Restrictions and Range Definition Notation
//
// Range restrictions can be annotated in the numeric type notation using CSS bracketed
// range notation—[min,max]—within the angle brackets, after the identifying keyword,
// indicating a closed range between (and including) min and max.
// For example, <integer [0, 10]> indicates an integer between 0 and 10, inclusive.
function readTypeRange(tokenizer) {
// use null for Infinity to make AST format JSON serializable/deserializable
let min = null; // -Infinity
let max = null; // Infinity
let sign = 1;
tokenizer.eat(LEFTSQUAREBRACKET);
if (tokenizer.charCode() === HYPERMINUS) {
tokenizer.peek();
sign = -1;
}
if (sign == -1 && tokenizer.charCode() === INFINITY) {
tokenizer.peek();
} else {
min = sign * Number(scanNumber(tokenizer));
if (NAME_CHAR[tokenizer.charCode()] !== 0) {
min += scanWord(tokenizer);
}
}
scanSpaces(tokenizer);
tokenizer.eat(COMMA);
scanSpaces(tokenizer);
if (tokenizer.charCode() === INFINITY) {
tokenizer.peek();
} else {
sign = 1;
if (tokenizer.charCode() === HYPERMINUS) {
tokenizer.peek();
sign = -1;
}
max = sign * Number(scanNumber(tokenizer));
if (NAME_CHAR[tokenizer.charCode()] !== 0) {
max += scanWord(tokenizer);
}
}
tokenizer.eat(RIGHTSQUAREBRACKET);
return {
type: 'Range',
min,
max
};
}
function readType(tokenizer) {
let name;
let opts = null;
tokenizer.eat(LESSTHANSIGN);
name = scanWord(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS &&
tokenizer.nextCharCode() === RIGHTPARENTHESIS) {
tokenizer.pos += 2;
name += '()';
}
if (tokenizer.charCodeAt(tokenizer.findWsEnd(tokenizer.pos)) === LEFTSQUAREBRACKET) {
scanSpaces(tokenizer);
opts = readTypeRange(tokenizer);
}
tokenizer.eat(GREATERTHANSIGN);
return maybeMultiplied(tokenizer, {
type: 'Type',
name,
opts
});
}
function readKeywordOrFunction(tokenizer) {
const name = scanWord(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS) {
tokenizer.pos++;
return {
type: 'Function',
name
};
}
return maybeMultiplied(tokenizer, {
type: 'Keyword',
name
});
}
function regroupTerms(terms, combinators) {
function createGroup(terms, combinator) {
return {
type: 'Group',
terms,
combinator,
disallowEmpty: false,
explicit: false
};
}
let combinator;
combinators = Object.keys(combinators)
.sort((a, b) => COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]);
while (combinators.length > 0) {
combinator = combinators.shift();
let i = 0;
let subgroupStart = 0;
for (; i < terms.length; i++) {
const term = terms[i];
if (term.type === 'Combinator') {
if (term.value === combinator) {
if (subgroupStart === -1) {
subgroupStart = i - 1;
}
terms.splice(i, 1);
i--;
} else {
if (subgroupStart !== -1 && i - subgroupStart > 1) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
i = subgroupStart + 1;
}
subgroupStart = -1;
}
}
}
if (subgroupStart !== -1 && combinators.length) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
}
}
return combinator;
}
function readImplicitGroup(tokenizer) {
const terms = [];
const combinators = {};
let token;
let prevToken = null;
let prevTokenPos = tokenizer.pos;
while (token = peek(tokenizer)) {
if (token.type !== 'Spaces') {
if (token.type === 'Combinator') {
// check for combinator in group beginning and double combinator sequence
if (prevToken === null || prevToken.type === 'Combinator') {
tokenizer.pos = prevTokenPos;
tokenizer.error('Unexpected combinator');
}
combinators[token.value] = true;
} else if (prevToken !== null && prevToken.type !== 'Combinator') {
combinators[' '] = true; // a b
terms.push({
type: 'Combinator',
value: ' '
});
}
terms.push(token);
prevToken = token;
prevTokenPos = tokenizer.pos;
}
}
// check for combinator in group ending
if (prevToken !== null && prevToken.type === 'Combinator') {
tokenizer.pos -= prevTokenPos;
tokenizer.error('Unexpected combinator');
}
return {
type: 'Group',
terms,
combinator: regroupTerms(terms, combinators) || ' ',
disallowEmpty: false,
explicit: false
};
}
function readGroup(tokenizer) {
let result;
tokenizer.eat(LEFTSQUAREBRACKET);
result = readImplicitGroup(tokenizer);
tokenizer.eat(RIGHTSQUAREBRACKET);
result.explicit = true;
if (tokenizer.charCode() === parse_EXCLAMATIONMARK) {
tokenizer.pos++;
result.disallowEmpty = true;
}
return result;
}
function peek(tokenizer) {
let code = tokenizer.charCode();
if (code < 128 && NAME_CHAR[code] === 1) {
return readKeywordOrFunction(tokenizer);
}
switch (code) {
case RIGHTSQUAREBRACKET:
// don't eat, stop scan a group
break;
case LEFTSQUAREBRACKET:
return maybeMultiplied(tokenizer, readGroup(tokenizer));
case LESSTHANSIGN:
return tokenizer.nextCharCode() === APOSTROPHE
? readProperty(tokenizer)
: readType(tokenizer);
case VERTICALLINE:
return {
type: 'Combinator',
value: tokenizer.substringToPos(
tokenizer.pos + (tokenizer.nextCharCode() === VERTICALLINE ? 2 : 1)
)
};
case AMPERSAND:
tokenizer.pos++;
tokenizer.eat(AMPERSAND);
return {
type: 'Combinator',
value: '&&'
};
case COMMA:
tokenizer.pos++;
return {
type: 'Comma'
};
case APOSTROPHE:
return maybeMultiplied(tokenizer, {
type: 'String',
value: scanString(tokenizer)
});
case parse_SPACE:
case parse_TAB:
case parse_N:
case parse_R:
case parse_F:
return {
type: 'Spaces',
value: scanSpaces(tokenizer)
};
case COMMERCIALAT:
code = tokenizer.nextCharCode();
if (code < 128 && NAME_CHAR[code] === 1) {
tokenizer.pos++;
return {
type: 'AtKeyword',
name: scanWord(tokenizer)
};
}
return maybeToken(tokenizer);
case ASTERISK:
case parse_PLUSSIGN:
case parse_QUESTIONMARK:
case parse_NUMBERSIGN:
case parse_EXCLAMATIONMARK:
// prohibited tokens (used as a multiplier start)
break;
case parse_LEFTCURLYBRACKET:
// LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
// check next char isn't a number, because it's likely a disjoined multiplier
code = tokenizer.nextCharCode();
if (code < 48 || code > 57) {
return maybeToken(tokenizer);
}
break;
default:
return maybeToken(tokenizer);
}
}
function parse(source) {
const tokenizer = new Tokenizer(source);
const result = readImplicitGroup(tokenizer);
if (tokenizer.pos !== source.length) {
tokenizer.error('Unexpected input');
}
// reduce redundant groups with single group term
if (result.terms.length === 1 && result.terms[0].type === 'Group') {
return result.terms[0];
}
return result;
};
;// ./node_modules/css-tree/lib/definition-syntax/walk.js
const walk_noop = function() {};
function walk_ensureFunction(value) {
return typeof value === 'function' ? value : walk_noop;
}
function walk(node, options, context) {
function walk(node) {
enter.call(context, node);
switch (node.type) {
case 'Group':
node.terms.forEach(walk);
break;
case 'Multiplier':
walk(node.term);
break;
case 'Type':
case 'Property':
case 'Keyword':
case 'AtKeyword':
case 'Function':
case 'String':
case 'Token':
case 'Comma':
break;
default:
throw new Error('Unknown type: ' + node.type);
}
leave.call(context, node);
}
let enter = walk_noop;
let leave = walk_noop;
if (typeof options === 'function') {
enter = options;
} else if (options) {
enter = walk_ensureFunction(options.enter);
leave = walk_ensureFunction(options.leave);
}
if (enter === walk_noop && leave === walk_noop) {
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
}
walk(node, context);
};
;// ./node_modules/css-tree/lib/definition-syntax/index.js
;// ./node_modules/css-tree/lib/lexer/prepare-tokens.js
const astToTokens = {
decorator(handlers) {
const tokens = [];
let curNode = null;
return {
...handlers,
node(node) {
const tmp = curNode;
curNode = node;
handlers.node.call(this, node);
curNode = tmp;
},
emit(value, type, auto) {
tokens.push({
type,
value,
node: auto ? null : curNode
});
},
result() {
return tokens;
}
};
}
};
function stringToTokens(str) {
const tokens = [];
tokenize(str, (type, start, end) =>
tokens.push({
type,
value: str.slice(start, end),
node: null
})
);
return tokens;
}
/* harmony default export */ function prepare_tokens(value, syntax) {
if (typeof value === 'string') {
return stringToTokens(value);
}
return syntax.generate(value, astToTokens);
};
;// ./node_modules/css-tree/lib/lexer/match-graph.js
const MATCH = { type: 'Match' };
const MISMATCH = { type: 'Mismatch' };
const DISALLOW_EMPTY = { type: 'DisallowEmpty' };
const match_graph_LEFTPARENTHESIS = 40; // (
const match_graph_RIGHTPARENTHESIS = 41; // )
function createCondition(match, thenBranch, elseBranch) {
// reduce node count
if (thenBranch === MATCH && elseBranch === MISMATCH) {
return match;
}
if (match === MATCH && thenBranch === MATCH && elseBranch === MATCH) {
return match;
}
if (match.type === 'If' && match.else === MISMATCH && thenBranch === MATCH) {
thenBranch = match.then;
match = match.match;
}
return {
type: 'If',
match,
then: thenBranch,
else: elseBranch
};
}
function isFunctionType(name) {
return (
name.length > 2 &&
name.charCodeAt(name.length - 2) === match_graph_LEFTPARENTHESIS &&
name.charCodeAt(name.length - 1) === match_graph_RIGHTPARENTHESIS
);
}
function isEnumCapatible(term) {
return (
term.type === 'Keyword' ||
term.type === 'AtKeyword' ||
term.type === 'Function' ||
term.type === 'Type' && isFunctionType(term.name)
);
}
function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
switch (combinator) {
case ' ': {
// Juxtaposing components means that all of them must occur, in the given order.
//
// a b c
// =
// match a
// then match b
// then match c
// then MATCH
// else MISMATCH
// else MISMATCH
// else MISMATCH
let result = MATCH;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
result = createCondition(
term,
result,
MISMATCH
);
};
return result;
}
case '|': {
// A bar (|) separates two or more alternatives: exactly one of them must occur.
//
// a | b | c
// =
// match a
// then MATCH
// else match b
// then MATCH
// else match c
// then MATCH
// else MISMATCH
let result = MISMATCH;
let map = null;
for (let i = terms.length - 1; i >= 0; i--) {
let term = terms[i];
// reduce sequence of keywords into a Enum
if (isEnumCapatible(term)) {
if (map === null && i > 0 && isEnumCapatible(terms[i - 1])) {
map = Object.create(null);
result = createCondition(
{
type: 'Enum',
map
},
MATCH,
result
);
}
if (map !== null) {
const key = (isFunctionType(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase();
if (key in map === false) {
map[key] = term;
continue;
}
}
}
map = null;
// create a new conditonal node
result = createCondition(
term,
MATCH,
result
);
};
return result;
}
case '&&': {
// A double ampersand (&&) separates two or more components,
// all of which must occur, in any order.
// Use MatchOnce for groups with a large number of terms,
// since &&-groups produces at least N!-node trees
if (terms.length > 5) {
return {
type: 'MatchOnce',
terms,
all: true
};
}
// Use a combination tree for groups with small number of terms
//
// a && b && c
// =
// match a
// then [b && c]
// else match b
// then [a && c]
// else match c
// then [a && b]
// else MISMATCH
//
// a && b
// =
// match a
// then match b
// then MATCH
// else MISMATCH
// else match b
// then match a
// then MATCH
// else MISMATCH
// else MISMATCH
let result = MISMATCH;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
let thenClause;
if (terms.length > 1) {
thenClause = buildGroupMatchGraph(
combinator,
terms.filter(function(newGroupTerm) {
return newGroupTerm !== term;
}),
false
);
} else {
thenClause = MATCH;
}
result = createCondition(
term,
thenClause,
result
);
};
return result;
}
case '||': {
// A double bar (||) separates two or more options:
// one or more of them must occur, in any order.
// Use MatchOnce for groups with a large number of terms,
// since ||-groups produces at least N!-node trees
if (terms.length > 5) {
return {
type: 'MatchOnce',
terms,
all: false
};
}
// Use a combination tree for groups with small number of terms
//
// a || b || c
// =
// match a
// then [b || c]
// else match b
// then [a || c]
// else match c
// then [a || b]
// else MISMATCH
//
// a || b
// =
// match a
// then match b
// then MATCH
// else MATCH
// else match b
// then match a
// then MATCH
// else MATCH
// else MISMATCH
let result = atLeastOneTermMatched ? MATCH : MISMATCH;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
let thenClause;
if (terms.length > 1) {
thenClause = buildGroupMatchGraph(
combinator,
terms.filter(function(newGroupTerm) {
return newGroupTerm !== term;
}),
true
);
} else {
thenClause = MATCH;
}
result = createCondition(
term,
thenClause,
result
);
};
return result;
}
}
}
function buildMultiplierMatchGraph(node) {
let result = MATCH;
let matchTerm = buildMatchGraphInternal(node.term);
if (node.max === 0) {
// disable repeating of empty match to prevent infinite loop
matchTerm = createCondition(
matchTerm,
DISALLOW_EMPTY,
MISMATCH
);
// an occurrence count is not limited, make a cycle;
// to collect more terms on each following matching mismatch
result = createCondition(
matchTerm,
null, // will be a loop
MISMATCH
);
result.then = createCondition(
MATCH,
MATCH,
result // make a loop
);
if (node.comma) {
result.then.else = createCondition(
{ type: 'Comma', syntax: node },
result,
MISMATCH
);
}
} else {
// create a match node chain for [min .. max] interval with optional matches
for (let i = node.min || 1; i <= node.max; i++) {
if (node.comma && result !== MATCH) {
result = createCondition(
{ type: 'Comma', syntax: node },
result,
MISMATCH
);
}
result = createCondition(
matchTerm,
createCondition(
MATCH,
MATCH,
result
),
MISMATCH
);
}
}
if (node.min === 0) {
// allow zero match
result = createCondition(
MATCH,
MATCH,
result
);
} else {
// create a match node chain to collect [0 ... min - 1] required matches
for (let i = 0; i < node.min - 1; i++) {
if (node.comma && result !== MATCH) {
result = createCondition(
{ type: 'Comma', syntax: node },
result,
MISMATCH
);
}
result = createCondition(
matchTerm,
result,
MISMATCH
);
}
}
return result;
}
function buildMatchGraphInternal(node) {
if (typeof node === 'function') {
return {
type: 'Generic',
fn: node
};
}
switch (node.type) {
case 'Group': {
let result = buildGroupMatchGraph(
node.combinator,
node.terms.map(buildMatchGraphInternal),
false
);
if (node.disallowEmpty) {
result = createCondition(
result,
DISALLOW_EMPTY,
MISMATCH
);
}
return result;
}
case 'Multiplier':
return buildMultiplierMatchGraph(node);
case 'Type':
case 'Property':
return {
type: node.type,
name: node.name,
syntax: node
};
case 'Keyword':
return {
type: node.type,
name: node.name.toLowerCase(),
syntax: node
};
case 'AtKeyword':
return {
type: node.type,
name: '@' + node.name.toLowerCase(),
syntax: node
};
case 'Function':
return {
type: node.type,
name: node.name.toLowerCase() + '(',
syntax: node
};
case 'String':
// convert a one char length String to a Token
if (node.value.length === 3) {
return {
type: 'Token',
value: node.value.charAt(1),
syntax: node
};
}
// otherwise use it as is
return {
type: node.type,
value: node.value.substr(1, node.value.length - 2).replace(/\\'/g, '\''),
syntax: node
};
case 'Token':
return {
type: node.type,
value: node.value,
syntax: node
};
case 'Comma':
return {
type: node.type,
syntax: node
};
default:
throw new Error('Unknown node type:', node.type);
}
}
function buildMatchGraph(syntaxTree, ref) {
if (typeof syntaxTree === 'string') {
syntaxTree = parse(syntaxTree);
}
return {
type: 'MatchGraph',
match: buildMatchGraphInternal(syntaxTree),
syntax: ref || null,
source: syntaxTree
};
}
;// ./node_modules/css-tree/lib/lexer/match.js
const { hasOwnProperty: match_hasOwnProperty } = Object.prototype;
const STUB = 0;
const TOKEN = 1;
const OPEN_SYNTAX = 2;
const CLOSE_SYNTAX = 3;
const EXIT_REASON_MATCH = 'Match';
const EXIT_REASON_MISMATCH = 'Mismatch';
const EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
const ITERATION_LIMIT = 15000;
let totalIterationCount = 0;
function reverseList(list) {
let prev = null;
let next = null;
let item = list;
while (item !== null) {
next = item.prev;
item.prev = prev;
prev = item;
item = next;
}
return prev;
}
function areStringsEqualCaseInsensitive(testStr, referenceStr) {
if (testStr.length !== referenceStr.length) {
return false;
}
for (let i = 0; i < testStr.length; i++) {
const referenceCode = referenceStr.charCodeAt(i);
let testCode = testStr.charCodeAt(i);
// testCode.toLowerCase() for U+0041 LATIN CAPITAL LETTER A (A) .. U+005A LATIN CAPITAL LETTER Z (Z).
if (testCode >= 0x0041 && testCode <= 0x005A) {
testCode = testCode | 32;
}
if (testCode !== referenceCode) {
return false;
}
}
return true;
}
function isContextEdgeDelim(token) {
if (token.type !== Delim) {
return false;
}
// Fix matching for unicode-range: U+30??, U+FF00-FF9F
// Probably we need to check out previous match instead
return token.value !== '?';
}
function isCommaContextStart(token) {
if (token === null) {
return true;
}
return (
token.type === Comma ||
token.type === Function ||
token.type === LeftParenthesis ||
token.type === LeftSquareBracket ||
token.type === LeftCurlyBracket ||
isContextEdgeDelim(token)
);
}
function isCommaContextEnd(token) {
if (token === null) {
return true;
}
return (
token.type === RightParenthesis ||
token.type === RightSquareBracket ||
token.type === RightCurlyBracket ||
(token.type === Delim && token.value === '/')
);
}
function internalMatch(tokens, state, syntaxes) {
function moveToNextToken() {
do {
tokenIndex++;
token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
} while (token !== null && (token.type === WhiteSpace || token.type === Comment));
}
function getNextToken(offset) {
const nextIndex = tokenIndex + offset;
return nextIndex < tokens.length ? tokens[nextIndex] : null;
}
function stateSnapshotFromSyntax(nextState, prev) {
return {
nextState,
matchStack,
syntaxStack,
thenStack,
tokenIndex,
prev
};
}
function pushThenStack(nextState) {
thenStack = {
nextState,
matchStack,
syntaxStack,
prev: thenStack
};
}
function pushElseStack(nextState) {
elseStack = stateSnapshotFromSyntax(nextState, elseStack);
}
function addTokenToMatch() {
matchStack = {
type: TOKEN,
syntax: state.syntax,
token,
prev: matchStack
};
moveToNextToken();
syntaxStash = null;
if (tokenIndex > longestMatch) {
longestMatch = tokenIndex;
}
}
function openSyntax() {
syntaxStack = {
syntax: state.syntax,
opts: state.syntax.opts || (syntaxStack !== null && syntaxStack.opts) || null,
prev: syntaxStack
};
matchStack = {
type: OPEN_SYNTAX,
syntax: state.syntax,
token: matchStack.token,
prev: matchStack
};
}
function closeSyntax() {
if (matchStack.type === OPEN_SYNTAX) {
matchStack = matchStack.prev;
} else {
matchStack = {
type: CLOSE_SYNTAX,
syntax: syntaxStack.syntax,
token: matchStack.token,
prev: matchStack
};
}
syntaxStack = syntaxStack.prev;
}
let syntaxStack = null;
let thenStack = null;
let elseStack = null;
// null – stashing allowed, nothing stashed
// false – stashing disabled, nothing stashed
// anithing else – fail stashable syntaxes, some syntax stashed
let syntaxStash = null;
let iterationCount = 0; // count iterations and prevent infinite loop
let exitReason = null;
let token = null;
let tokenIndex = -1;
let longestMatch = 0;
let matchStack = {
type: STUB,
syntax: null,
token: null,
prev: null
};
moveToNextToken();
while (exitReason === null && ++iterationCount < ITERATION_LIMIT) {
// function mapList(list, fn) {
// const result = [];
// while (list) {
// result.unshift(fn(list));
// list = list.prev;
// }
// return result;
// }
// console.log('--\n',
// '#' + iterationCount,
// require('util').inspect({
// match: mapList(matchStack, x => x.type === TOKEN ? x.token && x.token.value : x.syntax ? ({ [OPEN_SYNTAX]: '<', [CLOSE_SYNTAX]: '</' }[x.type] || x.type) + '!' + x.syntax.name : null),
// token: token && token.value,
// tokenIndex,
// syntax: syntax.type + (syntax.id ? ' #' + syntax.id : '')
// }, { depth: null })
// );
switch (state.type) {
case 'Match':
if (thenStack === null) {
// turn to MISMATCH when some tokens left unmatched
if (token !== null) {
// doesn't mismatch if just one token left and it's an IE hack
if (tokenIndex !== tokens.length - 1 || (token.value !== '\\0' && token.value !== '\\9')) {
state = MISMATCH;
break;
}
}
// break the main loop, return a result - MATCH
exitReason = EXIT_REASON_MATCH;
break;
}
// go to next syntax (`then` branch)
state = thenStack.nextState;
// check match is not empty
if (state === DISALLOW_EMPTY) {
if (thenStack.matchStack === matchStack) {
state = MISMATCH;
break;
} else {
state = MATCH;
}
}
// close syntax if needed
while (thenStack.syntaxStack !== syntaxStack) {
closeSyntax();
}
// pop stack
thenStack = thenStack.prev;
break;
case 'Mismatch':
// when some syntax is stashed
if (syntaxStash !== null && syntaxStash !== false) {
// there is no else branches or a branch reduce match stack
if (elseStack === null || tokenIndex > elseStack.tokenIndex) {
// restore state from the stash
elseStack = syntaxStash;
syntaxStash = false; // disable stashing
}
} else if (elseStack === null) {
// no else branches -> break the main loop
// return a result - MISMATCH
exitReason = EXIT_REASON_MISMATCH;
break;
}
// go to next syntax (`else` branch)
state = elseStack.nextState;
// restore all the rest stack states
thenStack = elseStack.thenStack;
syntaxStack = elseStack.syntaxStack;
matchStack = elseStack.matchStack;
tokenIndex = elseStack.tokenIndex;
token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
// pop stack
elseStack = elseStack.prev;
break;
case 'MatchGraph':
state = state.match;
break;
case 'If':
// IMPORTANT: else stack push must go first,
// since it stores the state of thenStack before changes
if (state.else !== MISMATCH) {
pushElseStack(state.else);
}
if (state.then !== MATCH) {
pushThenStack(state.then);
}
state = state.match;
break;
case 'MatchOnce':
state = {
type: 'MatchOnceBuffer',
syntax: state,
index: 0,
mask: 0
};
break;
case 'MatchOnceBuffer': {
const terms = state.syntax.terms;
if (state.index === terms.length) {
// no matches at all or it's required all terms to be matched
if (state.mask === 0 || state.syntax.all) {
state = MISMATCH;
break;
}
// a partial match is ok
state = MATCH;
break;
}
// all terms are matched
if (state.mask === (1 << terms.length) - 1) {
state = MATCH;
break;
}
for (; state.index < terms.length; state.index++) {
const matchFlag = 1 << state.index;
if ((state.mask & matchFlag) === 0) {
// IMPORTANT: else stack push must go first,
// since it stores the state of thenStack before changes
pushElseStack(state);
pushThenStack({
type: 'AddMatchOnce',
syntax: state.syntax,
mask: state.mask | matchFlag
});
// match
state = terms[state.index++];
break;
}
}
break;
}
case 'AddMatchOnce':
state = {
type: 'MatchOnceBuffer',
syntax: state.syntax,
index: 0,
mask: state.mask
};
break;
case 'Enum':
if (token !== null) {
let name = token.value.toLowerCase();
// drop \0 and \9 hack from keyword name
if (name.indexOf('\\') !== -1) {
name = name.replace(/\\[09].*$/, '');
}
if (match_hasOwnProperty.call(state.map, name)) {
state = state.map[name];
break;
}
}
state = MISMATCH;
break;
case 'Generic': {
const opts = syntaxStack !== null ? syntaxStack.opts : null;
const lastTokenIndex = tokenIndex + Math.floor(state.fn(token, getNextToken, opts));
if (!isNaN(lastTokenIndex) && lastTokenIndex > tokenIndex) {
while (tokenIndex < lastTokenIndex) {
addTokenToMatch();
}
state = MATCH;
} else {
state = MISMATCH;
}
break;
}
case 'Type':
case 'Property': {
const syntaxDict = state.type === 'Type' ? 'types' : 'properties';
const dictSyntax = match_hasOwnProperty.call(syntaxes, syntaxDict) ? syntaxes[syntaxDict][state.name] : null;
if (!dictSyntax || !dictSyntax.match) {
throw new Error(
'Bad syntax reference: ' +
(state.type === 'Type'
? '<' + state.name + '>'
: '<\'' + state.name + '\'>')
);
}
// stash a syntax for types with low priority
if (syntaxStash !== false && token !== null && state.type === 'Type') {
const lowPriorityMatching =
// https://drafts.csswg.org/css-values-4/#custom-idents
// When parsing positionally-ambiguous keywords in a property value, a <custom-ident> production
// can only claim the keyword if no other unfulfilled production can claim it.
(state.name === 'custom-ident' && token.type === Ident) ||
// https://drafts.csswg.org/css-values-4/#lengths
// ... if a `0` could be parsed as either a <number> or a <length> in a property (such as line-height),
// it must parse as a <number>
(state.name === 'length' && token.value === '0');
if (lowPriorityMatching) {
if (syntaxStash === null) {
syntaxStash = stateSnapshotFromSyntax(state, elseStack);
}
state = MISMATCH;
break;
}
}
openSyntax();
state = dictSyntax.match;
break;
}
case 'Keyword': {
const name = state.name;
if (token !== null) {
let keywordName = token.value;
// drop \0 and \9 hack from keyword name
if (keywordName.indexOf('\\') !== -1) {
keywordName = keywordName.replace(/\\[09].*$/, '');
}
if (areStringsEqualCaseInsensitive(keywordName, name)) {
addTokenToMatch();
state = MATCH;
break;
}
}
state = MISMATCH;
break;
}
case 'AtKeyword':
case 'Function':
if (token !== null && areStringsEqualCaseInsensitive(token.value, state.name)) {
addTokenToMatch();
state = MATCH;
break;
}
state = MISMATCH;
break;
case 'Token':
if (token !== null && token.value === state.value) {
addTokenToMatch();
state = MATCH;
break;
}
state = MISMATCH;
break;
case 'Comma':
if (token !== null && token.type === Comma) {
if (isCommaContextStart(matchStack.token)) {
state = MISMATCH;
} else {
addTokenToMatch();
state = isCommaContextEnd(token) ? MISMATCH : MATCH;
}
} else {
state = isCommaContextStart(matchStack.token) || isCommaContextEnd(token) ? MATCH : MISMATCH;
}
break;
case 'String':
let string = '';
let lastTokenIndex = tokenIndex;
for (; lastTokenIndex < tokens.length && string.length < state.value.length; lastTokenIndex++) {
string += tokens[lastTokenIndex].value;
}
if (areStringsEqualCaseInsensitive(string, state.value)) {
while (tokenIndex < lastTokenIndex) {
addTokenToMatch();
}
state = MATCH;
} else {
state = MISMATCH;
}
break;
default:
throw new Error('Unknown node type: ' + state.type);
}
}
totalIterationCount += iterationCount;
switch (exitReason) {
case null:
console.warn('[csstree-match] BREAK after ' + ITERATION_LIMIT + ' iterations');
exitReason = EXIT_REASON_ITERATION_LIMIT;
matchStack = null;
break;
case EXIT_REASON_MATCH:
while (syntaxStack !== null) {
closeSyntax();
}
break;
default:
matchStack = null;
}
return {
tokens,
reason: exitReason,
iterations: iterationCount,
match: matchStack,
longestMatch
};
}
function matchAsList(tokens, matchGraph, syntaxes) {
const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
if (matchResult.match !== null) {
let item = reverseList(matchResult.match).prev;
matchResult.match = [];
while (item !== null) {
switch (item.type) {
case OPEN_SYNTAX:
case CLOSE_SYNTAX:
matchResult.match.push({
type: item.type,
syntax: item.syntax
});
break;
default:
matchResult.match.push({
token: item.token.value,
node: item.token.node
});
break;
}
item = item.prev;
}
}
return matchResult;
}
function matchAsTree(tokens, matchGraph, syntaxes) {
const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
if (matchResult.match === null) {
return matchResult;
}
let item = matchResult.match;
let host = matchResult.match = {
syntax: matchGraph.syntax || null,
match: []
};
const hostStack = [host];
// revert a list and start with 2nd item since 1st is a stub item
item = reverseList(item).prev;
// build a tree
while (item !== null) {
switch (item.type) {
case OPEN_SYNTAX:
host.match.push(host = {
syntax: item.syntax,
match: []
});
hostStack.push(host);
break;
case CLOSE_SYNTAX:
hostStack.pop();
host = hostStack[hostStack.length - 1];
break;
default:
host.match.push({
syntax: item.syntax || null,
token: item.token.value,
node: item.token.node
});
}
item = item.prev;
}
return matchResult;
}
;// ./node_modules/css-tree/lib/lexer/trace.js
function getTrace(node) {
function shouldPutToTrace(syntax) {
if (syntax === null) {
return false;
}
return (
syntax.type === 'Type' ||
syntax.type === 'Property' ||
syntax.type === 'Keyword'
);
}
function hasMatch(matchNode) {
if (Array.isArray(matchNode.match)) {
// use for-loop for better perfomance
for (let i = 0; i < matchNode.match.length; i++) {
if (hasMatch(matchNode.match[i])) {
if (shouldPutToTrace(matchNode.syntax)) {
result.unshift(matchNode.syntax);
}
return true;
}
}
} else if (matchNode.node === node) {
result = shouldPutToTrace(matchNode.syntax)
? [matchNode.syntax]
: [];
return true;
}
return false;
}
let result = null;
if (this.matched !== null) {
hasMatch(this.matched);
}
return result;
}
function isType(node, type) {
return testNode(this, node, match => match.type === 'Type' && match.name === type);
}
function isProperty(node, property) {
return testNode(this, node, match => match.type === 'Property' && match.name === property);
}
function isKeyword(node) {
return testNode(this, node, match => match.type === 'Keyword');
}
function testNode(match, node, fn) {
const trace = getTrace.call(match, node);
if (trace === null) {
return false;
}
return trace.some(fn);
}
;// ./node_modules/css-tree/lib/lexer/search.js
function getFirstMatchNode(matchNode) {
if ('node' in matchNode) {
return matchNode.node;
}
return getFirstMatchNode(matchNode.match[0]);
}
function getLastMatchNode(matchNode) {
if ('node' in matchNode) {
return matchNode.node;
}
return getLastMatchNode(matchNode.match[matchNode.match.length - 1]);
}
function matchFragments(lexer, ast, match, type, name) {
function findFragments(matchNode) {
if (matchNode.syntax !== null &&
matchNode.syntax.type === type &&
matchNode.syntax.name === name) {
const start = getFirstMatchNode(matchNode);
const end = getLastMatchNode(matchNode);
lexer.syntax.walk(ast, function(node, item, list) {
if (node === start) {
const nodes = new List_List();
do {
nodes.appendData(item.data);
if (item.data === end) {
break;
}
item = item.next;
} while (item !== null);
fragments.push({
parent: list,
nodes
});
}
});
}
if (Array.isArray(matchNode.match)) {
matchNode.match.forEach(findFragments);
}
}
const fragments = [];
if (match.matched !== null) {
findFragments(match.matched);
}
return fragments;
}
;// ./node_modules/css-tree/lib/lexer/structure.js
const { hasOwnProperty: structure_hasOwnProperty } = Object.prototype;
function isValidNumber(value) {
// Number.isInteger(value) && value >= 0
return (
typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value &&
value >= 0
);
}
function isValidLocation(loc) {
return (
Boolean(loc) &&
isValidNumber(loc.offset) &&
isValidNumber(loc.line) &&
isValidNumber(loc.column)
);
}
function createNodeStructureChecker(type, fields) {
return function checkNode(node, warn) {
if (!node || node.constructor !== Object) {
return warn(node, 'Type of node should be an Object');
}
for (let key in node) {
let valid = true;
if (structure_hasOwnProperty.call(node, key) === false) {
continue;
}
if (key === 'type') {
if (node.type !== type) {
warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`');
}
} else if (key === 'loc') {
if (node.loc === null) {
continue;
} else if (node.loc && node.loc.constructor === Object) {
if (typeof node.loc.source !== 'string') {
key += '.source';
} else if (!isValidLocation(node.loc.start)) {
key += '.start';
} else if (!isValidLocation(node.loc.end)) {
key += '.end';
} else {
continue;
}
}
valid = false;
} else if (fields.hasOwnProperty(key)) {
valid = false;
for (let i = 0; !valid && i < fields[key].length; i++) {
const fieldType = fields[key][i];
switch (fieldType) {
case String:
valid = typeof node[key] === 'string';
break;
case Boolean:
valid = typeof node[key] === 'boolean';
break;
case null:
valid = node[key] === null;
break;
default:
if (typeof fieldType === 'string') {
valid = node[key] && node[key].type === fieldType;
} else if (Array.isArray(fieldType)) {
valid = node[key] instanceof List_List;
}
}
}
} else {
warn(node, 'Unknown field `' + key + '` for ' + type + ' node type');
}
if (!valid) {
warn(node, 'Bad value for `' + type + '.' + key + '`');
}
}
for (const key in fields) {
if (structure_hasOwnProperty.call(fields, key) &&
structure_hasOwnProperty.call(node, key) === false) {
warn(node, 'Field `' + type + '.' + key + '` is missed');
}
}
};
}
function processStructure(name, nodeType) {
const structure = nodeType.structure;
const fields = {
type: String,
loc: true
};
const docs = {
type: '"' + name + '"'
};
for (const key in structure) {
if (structure_hasOwnProperty.call(structure, key) === false) {
continue;
}
const docsTypes = [];
const fieldTypes = fields[key] = Array.isArray(structure[key])
? structure[key].slice()
: [structure[key]];
for (let i = 0; i < fieldTypes.length; i++) {
const fieldType = fieldTypes[i];
if (fieldType === String || fieldType === Boolean) {
docsTypes.push(fieldType.name);
} else if (fieldType === null) {
docsTypes.push('null');
} else if (typeof fieldType === 'string') {
docsTypes.push('<' + fieldType + '>');
} else if (Array.isArray(fieldType)) {
docsTypes.push('List'); // TODO: use type enum
} else {
throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition');
}
}
docs[key] = docsTypes.join(' | ');
}
return {
docs,
check: createNodeStructureChecker(name, fields)
};
}
function getStructureFromConfig(config) {
const structure = {};
if (config.node) {
for (const name in config.node) {
if (structure_hasOwnProperty.call(config.node, name)) {
const nodeType = config.node[name];
if (nodeType.structure) {
structure[name] = processStructure(name, nodeType);
} else {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
}
}
}
return structure;
};
;// ./node_modules/css-tree/lib/lexer/Lexer.js
const cssWideKeywordsSyntax = buildMatchGraph(cssWideKeywords.join(' | '));
function dumpMapSyntax(map, compact, syntaxAsAst) {
const result = {};
for (const name in map) {
if (map[name].syntax) {
result[name] = syntaxAsAst
? map[name].syntax
: generate(map[name].syntax, { compact });
}
}
return result;
}
function dumpAtruleMapSyntax(map, compact, syntaxAsAst) {
const result = {};
for (const [name, atrule] of Object.entries(map)) {
result[name] = {
prelude: atrule.prelude && (
syntaxAsAst
? atrule.prelude.syntax
: generate(atrule.prelude.syntax, { compact })
),
descriptors: atrule.descriptors && dumpMapSyntax(atrule.descriptors, compact, syntaxAsAst)
};
}
return result;
}
function valueHasVar(tokens) {
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].value.toLowerCase() === 'var(') {
return true;
}
}
return false;
}
function buildMatchResult(matched, error, iterations) {
return {
matched,
iterations,
error,
...trace_namespaceObject
};
}
function matchSyntax(lexer, syntax, value, useCssWideKeywords) {
const tokens = prepare_tokens(value, lexer.syntax);
let result;
if (valueHasVar(tokens)) {
return buildMatchResult(null, new Error('Matching for a tree with var() is not supported'));
}
if (useCssWideKeywords) {
result = matchAsTree(tokens, lexer.cssWideKeywordsSyntax, lexer);
}
if (!useCssWideKeywords || !result.match) {
result = matchAsTree(tokens, syntax.match, lexer);
if (!result.match) {
return buildMatchResult(
null,
new SyntaxMatchError(result.reason, syntax.syntax, value, result),
result.iterations
);
}
}
return buildMatchResult(result.match, null, result.iterations);
}
class Lexer {
constructor(config, syntax, structure) {
this.cssWideKeywordsSyntax = cssWideKeywordsSyntax;
this.syntax = syntax;
this.generic = false;
this.units = { ...units_namespaceObject };
this.atrules = Object.create(null);
this.properties = Object.create(null);
this.types = Object.create(null);
this.structure = structure || getStructureFromConfig(config);
if (config) {
if (config.units) {
for (const group of Object.keys(units_namespaceObject)) {
if (Array.isArray(config.units[group])) {
this.units[group] = config.units[group];
}
}
}
if (config.types) {
for (const name in config.types) {
this.addType_(name, config.types[name]);
}
}
if (config.generic) {
this.generic = true;
for (const [name, value] of Object.entries(createGenericTypes(this.units))) {
this.addType_(name, value);
}
}
if (config.atrules) {
for (const name in config.atrules) {
this.addAtrule_(name, config.atrules[name]);
}
}
if (config.properties) {
for (const name in config.properties) {
this.addProperty_(name, config.properties[name]);
}
}
}
}
checkStructure(ast) {
function collectWarning(node, message) {
warns.push({ node, message });
}
const structure = this.structure;
const warns = [];
this.syntax.walk(ast, function(node) {
if (structure.hasOwnProperty(node.type)) {
structure[node.type].check(node, collectWarning);
} else {
collectWarning(node, 'Unknown node type `' + node.type + '`');
}
});
return warns.length ? warns : false;
}
createDescriptor(syntax, type, name, parent = null) {
const ref = {
type,
name
};
const descriptor = {
type,
name,
parent,
serializable: typeof syntax === 'string' || (syntax && typeof syntax.type === 'string'),
syntax: null,
match: null
};
if (typeof syntax === 'function') {
descriptor.match = buildMatchGraph(syntax, ref);
} else {
if (typeof syntax === 'string') {
// lazy parsing on first access
Object.defineProperty(descriptor, 'syntax', {
get() {
Object.defineProperty(descriptor, 'syntax', {
value: parse(syntax)
});
return descriptor.syntax;
}
});
} else {
descriptor.syntax = syntax;
}
// lazy graph build on first access
Object.defineProperty(descriptor, 'match', {
get() {
Object.defineProperty(descriptor, 'match', {
value: buildMatchGraph(descriptor.syntax, ref)
});
return descriptor.match;
}
});
}
return descriptor;
}
addAtrule_(name, syntax) {
if (!syntax) {
return;
}
this.atrules[name] = {
type: 'Atrule',
name: name,
prelude: syntax.prelude ? this.createDescriptor(syntax.prelude, 'AtrulePrelude', name) : null,
descriptors: syntax.descriptors
? Object.keys(syntax.descriptors).reduce(
(map, descName) => {
map[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name);
return map;
},
Object.create(null)
)
: null
};
}
addProperty_(name, syntax) {
if (!syntax) {
return;
}
this.properties[name] = this.createDescriptor(syntax, 'Property', name);
}
addType_(name, syntax) {
if (!syntax) {
return;
}
this.types[name] = this.createDescriptor(syntax, 'Type', name);
}
checkAtruleName(atruleName) {
if (!this.getAtrule(atruleName)) {
return new SyntaxReferenceError('Unknown at-rule', '@' + atruleName);
}
}
checkAtrulePrelude(atruleName, prelude) {
const error = this.checkAtruleName(atruleName);
if (error) {
return error;
}
const atrule = this.getAtrule(atruleName);
if (!atrule.prelude && prelude) {
return new SyntaxError('At-rule `@' + atruleName + '` should not contain a prelude');
}
if (atrule.prelude && !prelude) {
if (!matchSyntax(this, atrule.prelude, '', false).matched) {
return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude');
}
}
}
checkAtruleDescriptorName(atruleName, descriptorName) {
const error = this.checkAtruleName(atruleName);
if (error) {
return error;
}
const atrule = this.getAtrule(atruleName);
const descriptor = keyword(descriptorName);
if (!atrule.descriptors) {
return new SyntaxError('At-rule `@' + atruleName + '` has no known descriptors');
}
if (!atrule.descriptors[descriptor.name] &&
!atrule.descriptors[descriptor.basename]) {
return new SyntaxReferenceError('Unknown at-rule descriptor', descriptorName);
}
}
checkPropertyName(propertyName) {
if (!this.getProperty(propertyName)) {
return new SyntaxReferenceError('Unknown property', propertyName);
}
}
matchAtrulePrelude(atruleName, prelude) {
const error = this.checkAtrulePrelude(atruleName, prelude);
if (error) {
return buildMatchResult(null, error);
}
const atrule = this.getAtrule(atruleName);
if (!atrule.prelude) {
return buildMatchResult(null, null);
}
return matchSyntax(this, atrule.prelude, prelude || '', false);
}
matchAtruleDescriptor(atruleName, descriptorName, value) {
const error = this.checkAtruleDescriptorName(atruleName, descriptorName);
if (error) {
return buildMatchResult(null, error);
}
const atrule = this.getAtrule(atruleName);
const descriptor = keyword(descriptorName);
return matchSyntax(this, atrule.descriptors[descriptor.name] || atrule.descriptors[descriptor.basename], value, false);
}
matchDeclaration(node) {
if (node.type !== 'Declaration') {
return buildMatchResult(null, new Error('Not a Declaration node'));
}
return this.matchProperty(node.property, node.value);
}
matchProperty(propertyName, value) {
// don't match syntax for a custom property at the moment
if (names_property(propertyName).custom) {
return buildMatchResult(null, new Error('Lexer matching doesn\'t applicable for custom properties'));
}
const error = this.checkPropertyName(propertyName);
if (error) {
return buildMatchResult(null, error);
}
return matchSyntax(this, this.getProperty(propertyName), value, true);
}
matchType(typeName, value) {
const typeSyntax = this.getType(typeName);
if (!typeSyntax) {
return buildMatchResult(null, new SyntaxReferenceError('Unknown type', typeName));
}
return matchSyntax(this, typeSyntax, value, false);
}
match(syntax, value) {
if (typeof syntax !== 'string' && (!syntax || !syntax.type)) {
return buildMatchResult(null, new SyntaxReferenceError('Bad syntax'));
}
if (typeof syntax === 'string' || !syntax.match) {
syntax = this.createDescriptor(syntax, 'Type', 'anonymous');
}
return matchSyntax(this, syntax, value, false);
}
findValueFragments(propertyName, value, type, name) {
return matchFragments(this, value, this.matchProperty(propertyName, value), type, name);
}
findDeclarationValueFragments(declaration, type, name) {
return matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name);
}
findAllFragments(ast, type, name) {
const result = [];
this.syntax.walk(ast, {
visit: 'Declaration',
enter: (declaration) => {
result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name));
}
});
return result;
}
getAtrule(atruleName, fallbackBasename = true) {
const atrule = keyword(atruleName);
const atruleEntry = atrule.vendor && fallbackBasename
? this.atrules[atrule.name] || this.atrules[atrule.basename]
: this.atrules[atrule.name];
return atruleEntry || null;
}
getAtrulePrelude(atruleName, fallbackBasename = true) {
const atrule = this.getAtrule(atruleName, fallbackBasename);
return atrule && atrule.prelude || null;
}
getAtruleDescriptor(atruleName, name) {
return this.atrules.hasOwnProperty(atruleName) && this.atrules.declarators
? this.atrules[atruleName].declarators[name] || null
: null;
}
getProperty(propertyName, fallbackBasename = true) {
const property = names_property(propertyName);
const propertyEntry = property.vendor && fallbackBasename
? this.properties[property.name] || this.properties[property.basename]
: this.properties[property.name];
return propertyEntry || null;
}
getType(name) {
return hasOwnProperty.call(this.types, name) ? this.types[name] : null;
}
validate() {
function validate(syntax, name, broken, descriptor) {
if (broken.has(name)) {
return broken.get(name);
}
broken.set(name, false);
if (descriptor.syntax !== null) {
walk(descriptor.syntax, function(node) {
if (node.type !== 'Type' && node.type !== 'Property') {
return;
}
const map = node.type === 'Type' ? syntax.types : syntax.properties;
const brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties;
if (!hasOwnProperty.call(map, node.name) || validate(syntax, node.name, brokenMap, map[node.name])) {
broken.set(name, true);
}
}, this);
}
}
let brokenTypes = new Map();
let brokenProperties = new Map();
for (const key in this.types) {
validate(this, key, brokenTypes, this.types[key]);
}
for (const key in this.properties) {
validate(this, key, brokenProperties, this.properties[key]);
}
brokenTypes = [...brokenTypes.keys()].filter(name => brokenTypes.get(name));
brokenProperties = [...brokenProperties.keys()].filter(name => brokenProperties.get(name));
if (brokenTypes.length || brokenProperties.length) {
return {
types: brokenTypes,
properties: brokenProperties
};
}
return null;
}
dump(syntaxAsAst, pretty) {
return {
generic: this.generic,
units: this.units,
types: dumpMapSyntax(this.types, !pretty, syntaxAsAst),
properties: dumpMapSyntax(this.properties, !pretty, syntaxAsAst),
atrules: dumpAtruleMapSyntax(this.atrules, !pretty, syntaxAsAst)
};
}
toString() {
return JSON.stringify(this.dump());
}
};
;// ./node_modules/css-tree/lib/syntax/config/mix.js
function appendOrSet(a, b) {
if (typeof b === 'string' && /^\s*\|/.test(b)) {
return typeof a === 'string'
? a + b
: b.replace(/^\s*\|\s*/, '');
}
return b || null;
}
function sliceProps(obj, props) {
const result = Object.create(null);
for (const [key, value] of Object.entries(obj)) {
if (value) {
result[key] = {};
for (const prop of Object.keys(value)) {
if (props.includes(prop)) {
result[key][prop] = value[prop];
}
}
}
}
return result;
}
function mix(dest, src) {
const result = { ...dest };
for (const [prop, value] of Object.entries(src)) {
switch (prop) {
case 'generic':
result[prop] = Boolean(value);
break;
case 'units':
result[prop] = { ...dest[prop] };
for (const [name, patch] of Object.entries(value)) {
result[prop][name] = Array.isArray(patch) ? patch : [];
}
break;
case 'atrules':
result[prop] = { ...dest[prop] };
for (const [name, atrule] of Object.entries(value)) {
const exists = result[prop][name] || {};
const current = result[prop][name] = {
prelude: exists.prelude || null,
descriptors: {
...exists.descriptors
}
};
if (!atrule) {
continue;
}
current.prelude = atrule.prelude
? appendOrSet(current.prelude, atrule.prelude)
: current.prelude || null;
for (const [descriptorName, descriptorValue] of Object.entries(atrule.descriptors || {})) {
current.descriptors[descriptorName] = descriptorValue
? appendOrSet(current.descriptors[descriptorName], descriptorValue)
: null;
}
if (!Object.keys(current.descriptors).length) {
current.descriptors = null;
}
}
break;
case 'types':
case 'properties':
result[prop] = { ...dest[prop] };
for (const [name, syntax] of Object.entries(value)) {
result[prop][name] = appendOrSet(result[prop][name], syntax);
}
break;
case 'scope':
result[prop] = { ...dest[prop] };
for (const [name, props] of Object.entries(value)) {
result[prop][name] = { ...result[prop][name], ...props };
}
break;
case 'parseContext':
result[prop] = {
...dest[prop],
...value
};
break;
case 'atrule':
case 'pseudo':
result[prop] = {
...dest[prop],
...sliceProps(value, ['parse']) };
break;
case 'node':
result[prop] = {
...dest[prop],
...sliceProps(value, ['name', 'structure', 'parse', 'generate', 'walkContext'])
};
break;
}
}
return result;
}
;// ./node_modules/css-tree/lib/syntax/create.js
function createSyntax(config) {
const parse = createParser(config);
const walk = createWalker(config);
const generate = createGenerator(config);
const { fromPlainObject, toPlainObject } = createConvertor(walk);
const syntax = {
lexer: null,
createLexer: config => new Lexer(config, syntax, syntax.lexer.structure),
tokenize: tokenize,
parse,
generate,
walk,
find: walk.find,
findLast: walk.findLast,
findAll: walk.findAll,
fromPlainObject,
toPlainObject,
fork(extension) {
const base = mix({}, config); // copy of config
return createSyntax(
typeof extension === 'function'
? extension(base, Object.assign)
: mix(base, extension)
);
}
};
syntax.lexer = new Lexer({
generic: true,
units: config.units,
types: config.types,
atrules: config.atrules,
properties: config.properties,
node: config.node
}, syntax);
return syntax;
};
/* harmony default export */ const create = (config => createSyntax(mix({}, config)));
;// ./node_modules/css-tree/dist/data.js
/* harmony default export */ const data = ({
"generic": true,
"units": {
"angle": [
"deg",
"grad",
"rad",
"turn"
],
"decibel": [
"db"
],
"flex": [
"fr"
],
"frequency": [
"hz",
"khz"
],
"length": [
"cm",
"mm",
"q",
"in",
"pt",
"pc",
"px",
"em",
"rem",
"ex",
"rex",
"cap",
"rcap",
"ch",
"rch",
"ic",
"ric",
"lh",
"rlh",
"vw",
"svw",
"lvw",
"dvw",
"vh",
"svh",
"lvh",
"dvh",
"vi",
"svi",
"lvi",
"dvi",
"vb",
"svb",
"lvb",
"dvb",
"vmin",
"svmin",
"lvmin",
"dvmin",
"vmax",
"svmax",
"lvmax",
"dvmax",
"cqw",
"cqh",
"cqi",
"cqb",
"cqmin",
"cqmax"
],
"resolution": [
"dpi",
"dpcm",
"dppx",
"x"
],
"semitones": [
"st"
],
"time": [
"s",
"ms"
]
},
"types": {
"abs()": "abs( <calc-sum> )",
"absolute-size": "xx-small|x-small|small|medium|large|x-large|xx-large|xxx-large",
"acos()": "acos( <calc-sum> )",
"alpha-value": "<number>|<percentage>",
"angle-percentage": "<angle>|<percentage>",
"angular-color-hint": "<angle-percentage>",
"angular-color-stop": "<color>&&<color-stop-angle>?",
"angular-color-stop-list": "[<angular-color-stop> [, <angular-color-hint>]?]# , <angular-color-stop>",
"animateable-feature": "scroll-position|contents|<custom-ident>",
"asin()": "asin( <calc-sum> )",
"atan()": "atan( <calc-sum> )",
"atan2()": "atan2( <calc-sum> , <calc-sum> )",
"attachment": "scroll|fixed|local",
"attr()": "attr( <attr-name> <type-or-unit>? [, <attr-fallback>]? )",
"attr-matcher": "['~'|'|'|'^'|'$'|'*']? '='",
"attr-modifier": "i|s",
"attribute-selector": "'[' <wq-name> ']'|'[' <wq-name> <attr-matcher> [<string-token>|<ident-token>] <attr-modifier>? ']'",
"auto-repeat": "repeat( [auto-fill|auto-fit] , [<line-names>? <fixed-size>]+ <line-names>? )",
"auto-track-list": "[<line-names>? [<fixed-size>|<fixed-repeat>]]* <line-names>? <auto-repeat> [<line-names>? [<fixed-size>|<fixed-repeat>]]* <line-names>?",
"axis": "block|inline|vertical|horizontal",
"baseline-position": "[first|last]? baseline",
"basic-shape": "<inset()>|<circle()>|<ellipse()>|<polygon()>|<path()>",
"bg-image": "none|<image>",
"bg-layer": "<bg-image>||<bg-position> [/ <bg-size>]?||<repeat-style>||<attachment>||<box>||<box>",
"bg-position": "[[left|center|right|top|bottom|<length-percentage>]|[left|center|right|<length-percentage>] [top|center|bottom|<length-percentage>]|[center|[left|right] <length-percentage>?]&&[center|[top|bottom] <length-percentage>?]]",
"bg-size": "[<length-percentage>|auto]{1,2}|cover|contain",
"blur()": "blur( <length> )",
"blend-mode": "normal|multiply|screen|overlay|darken|lighten|color-dodge|color-burn|hard-light|soft-light|difference|exclusion|hue|saturation|color|luminosity",
"box": "border-box|padding-box|content-box",
"brightness()": "brightness( <number-percentage> )",
"calc()": "calc( <calc-sum> )",
"calc-sum": "<calc-product> [['+'|'-'] <calc-product>]*",
"calc-product": "<calc-value> ['*' <calc-value>|'/' <number>]*",
"calc-value": "<number>|<dimension>|<percentage>|<calc-constant>|( <calc-sum> )",
"calc-constant": "e|pi|infinity|-infinity|NaN",
"cf-final-image": "<image>|<color>",
"cf-mixing-image": "<percentage>?&&<image>",
"circle()": "circle( [<shape-radius>]? [at <position>]? )",
"clamp()": "clamp( <calc-sum>#{3} )",
"class-selector": "'.' <ident-token>",
"clip-source": "<url>",
"color": "<rgb()>|<rgba()>|<hsl()>|<hsla()>|<hwb()>|<lab()>|<lch()>|<hex-color>|<named-color>|currentcolor|<deprecated-system-color>",
"color-stop": "<color-stop-length>|<color-stop-angle>",
"color-stop-angle": "<angle-percentage>{1,2}",
"color-stop-length": "<length-percentage>{1,2}",
"color-stop-list": "[<linear-color-stop> [, <linear-color-hint>]?]# , <linear-color-stop>",
"combinator": "'>'|'+'|'~'|['||']",
"common-lig-values": "[common-ligatures|no-common-ligatures]",
"compat-auto": "searchfield|textarea|push-button|slider-horizontal|checkbox|radio|square-button|menulist|listbox|meter|progress-bar|button",
"composite-style": "clear|copy|source-over|source-in|source-out|source-atop|destination-over|destination-in|destination-out|destination-atop|xor",
"compositing-operator": "add|subtract|intersect|exclude",
"compound-selector": "[<type-selector>? <subclass-selector>* [<pseudo-element-selector> <pseudo-class-selector>*]*]!",
"compound-selector-list": "<compound-selector>#",
"complex-selector": "<compound-selector> [<combinator>? <compound-selector>]*",
"complex-selector-list": "<complex-selector>#",
"conic-gradient()": "conic-gradient( [from <angle>]? [at <position>]? , <angular-color-stop-list> )",
"contextual-alt-values": "[contextual|no-contextual]",
"content-distribution": "space-between|space-around|space-evenly|stretch",
"content-list": "[<string>|contents|<image>|<counter>|<quote>|<target>|<leader()>|<attr()>]+",
"content-position": "center|start|end|flex-start|flex-end",
"content-replacement": "<image>",
"contrast()": "contrast( [<number-percentage>] )",
"cos()": "cos( <calc-sum> )",
"counter": "<counter()>|<counters()>",
"counter()": "counter( <counter-name> , <counter-style>? )",
"counter-name": "<custom-ident>",
"counter-style": "<counter-style-name>|symbols( )",
"counter-style-name": "<custom-ident>",
"counters()": "counters( <counter-name> , <string> , <counter-style>? )",
"cross-fade()": "cross-fade( <cf-mixing-image> , <cf-final-image>? )",
"cubic-bezier-timing-function": "ease|ease-in|ease-out|ease-in-out|cubic-bezier( <number [0,1]> , <number> , <number [0,1]> , <number> )",
"deprecated-system-color": "ActiveBorder|ActiveCaption|AppWorkspace|Background|ButtonFace|ButtonHighlight|ButtonShadow|ButtonText|CaptionText|GrayText|Highlight|HighlightText|InactiveBorder|InactiveCaption|InactiveCaptionText|InfoBackground|InfoText|Menu|MenuText|Scrollbar|ThreeDDarkShadow|ThreeDFace|ThreeDHighlight|ThreeDLightShadow|ThreeDShadow|Window|WindowFrame|WindowText",
"discretionary-lig-values": "[discretionary-ligatures|no-discretionary-ligatures]",
"display-box": "contents|none",
"display-inside": "flow|flow-root|table|flex|grid|ruby",
"display-internal": "table-row-group|table-header-group|table-footer-group|table-row|table-cell|table-column-group|table-column|table-caption|ruby-base|ruby-text|ruby-base-container|ruby-text-container",
"display-legacy": "inline-block|inline-list-item|inline-table|inline-flex|inline-grid",
"display-listitem": "<display-outside>?&&[flow|flow-root]?&&list-item",
"display-outside": "block|inline|run-in",
"drop-shadow()": "drop-shadow( <length>{2,3} <color>? )",
"east-asian-variant-values": "[jis78|jis83|jis90|jis04|simplified|traditional]",
"east-asian-width-values": "[full-width|proportional-width]",
"element()": "element( <custom-ident> , [first|start|last|first-except]? )|element( <id-selector> )",
"ellipse()": "ellipse( [<shape-radius>{2}]? [at <position>]? )",
"ending-shape": "circle|ellipse",
"env()": "env( <custom-ident> , <declaration-value>? )",
"exp()": "exp( <calc-sum> )",
"explicit-track-list": "[<line-names>? <track-size>]+ <line-names>?",
"family-name": "<string>|<custom-ident>+",
"feature-tag-value": "<string> [<integer>|on|off]?",
"feature-type": "@stylistic|@historical-forms|@styleset|@character-variant|@swash|@ornaments|@annotation",
"feature-value-block": "<feature-type> '{' <feature-value-declaration-list> '}'",
"feature-value-block-list": "<feature-value-block>+",
"feature-value-declaration": "<custom-ident> : <integer>+ ;",
"feature-value-declaration-list": "<feature-value-declaration>",
"feature-value-name": "<custom-ident>",
"fill-rule": "nonzero|evenodd",
"filter-function": "<blur()>|<brightness()>|<contrast()>|<drop-shadow()>|<grayscale()>|<hue-rotate()>|<invert()>|<opacity()>|<saturate()>|<sepia()>",
"filter-function-list": "[<filter-function>|<url>]+",
"final-bg-layer": "<'background-color'>||<bg-image>||<bg-position> [/ <bg-size>]?||<repeat-style>||<attachment>||<box>||<box>",
"fixed-breadth": "<length-percentage>",
"fixed-repeat": "repeat( [<integer [1,∞]>] , [<line-names>? <fixed-size>]+ <line-names>? )",
"fixed-size": "<fixed-breadth>|minmax( <fixed-breadth> , <track-breadth> )|minmax( <inflexible-breadth> , <fixed-breadth> )",
"font-stretch-absolute": "normal|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded|<percentage>",
"font-variant-css21": "[normal|small-caps]",
"font-weight-absolute": "normal|bold|<number [1,1000]>",
"frequency-percentage": "<frequency>|<percentage>",
"general-enclosed": "[<function-token> <any-value> )]|( <ident> <any-value> )",
"generic-family": "serif|sans-serif|cursive|fantasy|monospace|-apple-system",
"generic-name": "serif|sans-serif|cursive|fantasy|monospace",
"geometry-box": "<shape-box>|fill-box|stroke-box|view-box",
"gradient": "<linear-gradient()>|<repeating-linear-gradient()>|<radial-gradient()>|<repeating-radial-gradient()>|<conic-gradient()>|<repeating-conic-gradient()>|<-legacy-gradient>",
"grayscale()": "grayscale( <number-percentage> )",
"grid-line": "auto|<custom-ident>|[<integer>&&<custom-ident>?]|[span&&[<integer>||<custom-ident>]]",
"historical-lig-values": "[historical-ligatures|no-historical-ligatures]",
"hsl()": "hsl( <hue> <percentage> <percentage> [/ <alpha-value>]? )|hsl( <hue> , <percentage> , <percentage> , <alpha-value>? )",
"hsla()": "hsla( <hue> <percentage> <percentage> [/ <alpha-value>]? )|hsla( <hue> , <percentage> , <percentage> , <alpha-value>? )",
"hue": "<number>|<angle>",
"hue-rotate()": "hue-rotate( <angle> )",
"hwb()": "hwb( [<hue>|none] [<percentage>|none] [<percentage>|none] [/ [<alpha-value>|none]]? )",
"hypot()": "hypot( <calc-sum># )",
"image": "<url>|<image()>|<image-set()>|<element()>|<paint()>|<cross-fade()>|<gradient>",
"image()": "image( <image-tags>? [<image-src>? , <color>?]! )",
"image-set()": "image-set( <image-set-option># )",
"image-set-option": "[<image>|<string>] [<resolution>||type( <string> )]",
"image-src": "<url>|<string>",
"image-tags": "ltr|rtl",
"inflexible-breadth": "<length-percentage>|min-content|max-content|auto",
"inset()": "inset( <length-percentage>{1,4} [round <'border-radius'>]? )",
"invert()": "invert( <number-percentage> )",
"keyframes-name": "<custom-ident>|<string>",
"keyframe-block": "<keyframe-selector># { <declaration-list> }",
"keyframe-block-list": "<keyframe-block>+",
"keyframe-selector": "from|to|<percentage>",
"lab()": "lab( [<percentage>|<number>|none] [<percentage>|<number>|none] [<percentage>|<number>|none] [/ [<alpha-value>|none]]? )",
"layer()": "layer( <layer-name> )",
"layer-name": "<ident> ['.' <ident>]*",
"lch()": "lch( [<percentage>|<number>|none] [<percentage>|<number>|none] [<hue>|none] [/ [<alpha-value>|none]]? )",
"leader()": "leader( <leader-type> )",
"leader-type": "dotted|solid|space|<string>",
"length-percentage": "<length>|<percentage>",
"line-names": "'[' <custom-ident>* ']'",
"line-name-list": "[<line-names>|<name-repeat>]+",
"line-style": "none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset",
"line-width": "<length>|thin|medium|thick",
"linear-color-hint": "<length-percentage>",
"linear-color-stop": "<color> <color-stop-length>?",
"linear-gradient()": "linear-gradient( [<angle>|to <side-or-corner>]? , <color-stop-list> )",
"log()": "log( <calc-sum> , <calc-sum>? )",
"mask-layer": "<mask-reference>||<position> [/ <bg-size>]?||<repeat-style>||<geometry-box>||[<geometry-box>|no-clip]||<compositing-operator>||<masking-mode>",
"mask-position": "[<length-percentage>|left|center|right] [<length-percentage>|top|center|bottom]?",
"mask-reference": "none|<image>|<mask-source>",
"mask-source": "<url>",
"masking-mode": "alpha|luminance|match-source",
"matrix()": "matrix( <number>#{6} )",
"matrix3d()": "matrix3d( <number>#{16} )",
"max()": "max( <calc-sum># )",
"media-and": "<media-in-parens> [and <media-in-parens>]+",
"media-condition": "<media-not>|<media-and>|<media-or>|<media-in-parens>",
"media-condition-without-or": "<media-not>|<media-and>|<media-in-parens>",
"media-feature": "( [<mf-plain>|<mf-boolean>|<mf-range>] )",
"media-in-parens": "( <media-condition> )|<media-feature>|<general-enclosed>",
"media-not": "not <media-in-parens>",
"media-or": "<media-in-parens> [or <media-in-parens>]+",
"media-query": "<media-condition>|[not|only]? <media-type> [and <media-condition-without-or>]?",
"media-query-list": "<media-query>#",
"media-type": "<ident>",
"mf-boolean": "<mf-name>",
"mf-name": "<ident>",
"mf-plain": "<mf-name> : <mf-value>",
"mf-range": "<mf-name> ['<'|'>']? '='? <mf-value>|<mf-value> ['<'|'>']? '='? <mf-name>|<mf-value> '<' '='? <mf-name> '<' '='? <mf-value>|<mf-value> '>' '='? <mf-name> '>' '='? <mf-value>",
"mf-value": "<number>|<dimension>|<ident>|<ratio>",
"min()": "min( <calc-sum># )",
"minmax()": "minmax( [<length-percentage>|min-content|max-content|auto] , [<length-percentage>|<flex>|min-content|max-content|auto] )",
"mod()": "mod( <calc-sum> , <calc-sum> )",
"name-repeat": "repeat( [<integer [1,∞]>|auto-fill] , <line-names>+ )",
"named-color": "transparent|aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen|<-non-standard-color>",
"namespace-prefix": "<ident>",
"ns-prefix": "[<ident-token>|'*']? '|'",
"number-percentage": "<number>|<percentage>",
"numeric-figure-values": "[lining-nums|oldstyle-nums]",
"numeric-fraction-values": "[diagonal-fractions|stacked-fractions]",
"numeric-spacing-values": "[proportional-nums|tabular-nums]",
"nth": "<an-plus-b>|even|odd",
"opacity()": "opacity( [<number-percentage>] )",
"overflow-position": "unsafe|safe",
"outline-radius": "<length>|<percentage>",
"page-body": "<declaration>? [; <page-body>]?|<page-margin-box> <page-body>",
"page-margin-box": "<page-margin-box-type> '{' <declaration-list> '}'",
"page-margin-box-type": "@top-left-corner|@top-left|@top-center|@top-right|@top-right-corner|@bottom-left-corner|@bottom-left|@bottom-center|@bottom-right|@bottom-right-corner|@left-top|@left-middle|@left-bottom|@right-top|@right-middle|@right-bottom",
"page-selector-list": "[<page-selector>#]?",
"page-selector": "<pseudo-page>+|<ident> <pseudo-page>*",
"page-size": "A5|A4|A3|B5|B4|JIS-B5|JIS-B4|letter|legal|ledger",
"path()": "path( [<fill-rule> ,]? <string> )",
"paint()": "paint( <ident> , <declaration-value>? )",
"perspective()": "perspective( [<length [0,∞]>|none] )",
"polygon()": "polygon( <fill-rule>? , [<length-percentage> <length-percentage>]# )",
"position": "[[left|center|right]||[top|center|bottom]|[left|center|right|<length-percentage>] [top|center|bottom|<length-percentage>]?|[[left|right] <length-percentage>]&&[[top|bottom] <length-percentage>]]",
"pow()": "pow( <calc-sum> , <calc-sum> )",
"pseudo-class-selector": "':' <ident-token>|':' <function-token> <any-value> ')'",
"pseudo-element-selector": "':' <pseudo-class-selector>",
"pseudo-page": ": [left|right|first|blank]",
"quote": "open-quote|close-quote|no-open-quote|no-close-quote",
"radial-gradient()": "radial-gradient( [<ending-shape>||<size>]? [at <position>]? , <color-stop-list> )",
"ratio": "<number [0,∞]> [/ <number [0,∞]>]?",
"relative-selector": "<combinator>? <complex-selector>",
"relative-selector-list": "<relative-selector>#",
"relative-size": "larger|smaller",
"rem()": "rem( <calc-sum> , <calc-sum> )",
"repeat-style": "repeat-x|repeat-y|[repeat|space|round|no-repeat]{1,2}",
"repeating-conic-gradient()": "repeating-conic-gradient( [from <angle>]? [at <position>]? , <angular-color-stop-list> )",
"repeating-linear-gradient()": "repeating-linear-gradient( [<angle>|to <side-or-corner>]? , <color-stop-list> )",
"repeating-radial-gradient()": "repeating-radial-gradient( [<ending-shape>||<size>]? [at <position>]? , <color-stop-list> )",
"reversed-counter-name": "reversed( <counter-name> )",
"rgb()": "rgb( <percentage>{3} [/ <alpha-value>]? )|rgb( <number>{3} [/ <alpha-value>]? )|rgb( <percentage>#{3} , <alpha-value>? )|rgb( <number>#{3} , <alpha-value>? )",
"rgba()": "rgba( <percentage>{3} [/ <alpha-value>]? )|rgba( <number>{3} [/ <alpha-value>]? )|rgba( <percentage>#{3} , <alpha-value>? )|rgba( <number>#{3} , <alpha-value>? )",
"rotate()": "rotate( [<angle>|<zero>] )",
"rotate3d()": "rotate3d( <number> , <number> , <number> , [<angle>|<zero>] )",
"rotateX()": "rotateX( [<angle>|<zero>] )",
"rotateY()": "rotateY( [<angle>|<zero>] )",
"rotateZ()": "rotateZ( [<angle>|<zero>] )",
"round()": "round( <rounding-strategy>? , <calc-sum> , <calc-sum> )",
"rounding-strategy": "nearest|up|down|to-zero",
"saturate()": "saturate( <number-percentage> )",
"scale()": "scale( [<number>|<percentage>]#{1,2} )",
"scale3d()": "scale3d( [<number>|<percentage>]#{3} )",
"scaleX()": "scaleX( [<number>|<percentage>] )",
"scaleY()": "scaleY( [<number>|<percentage>] )",
"scaleZ()": "scaleZ( [<number>|<percentage>] )",
"scroller": "root|nearest",
"self-position": "center|start|end|self-start|self-end|flex-start|flex-end",
"shape-radius": "<length-percentage>|closest-side|farthest-side",
"sign()": "sign( <calc-sum> )",
"skew()": "skew( [<angle>|<zero>] , [<angle>|<zero>]? )",
"skewX()": "skewX( [<angle>|<zero>] )",
"skewY()": "skewY( [<angle>|<zero>] )",
"sepia()": "sepia( <number-percentage> )",
"shadow": "inset?&&<length>{2,4}&&<color>?",
"shadow-t": "[<length>{2,3}&&<color>?]",
"shape": "rect( <top> , <right> , <bottom> , <left> )|rect( <top> <right> <bottom> <left> )",
"shape-box": "<box>|margin-box",
"side-or-corner": "[left|right]||[top|bottom]",
"sin()": "sin( <calc-sum> )",
"single-animation": "<time>||<easing-function>||<time>||<single-animation-iteration-count>||<single-animation-direction>||<single-animation-fill-mode>||<single-animation-play-state>||[none|<keyframes-name>]",
"single-animation-direction": "normal|reverse|alternate|alternate-reverse",
"single-animation-fill-mode": "none|forwards|backwards|both",
"single-animation-iteration-count": "infinite|<number>",
"single-animation-play-state": "running|paused",
"single-animation-timeline": "auto|none|<timeline-name>|scroll( <axis>? <scroller>? )",
"single-transition": "[none|<single-transition-property>]||<time>||<easing-function>||<time>",
"single-transition-property": "all|<custom-ident>",
"size": "closest-side|farthest-side|closest-corner|farthest-corner|<length>|<length-percentage>{2}",
"sqrt()": "sqrt( <calc-sum> )",
"step-position": "jump-start|jump-end|jump-none|jump-both|start|end",
"step-timing-function": "step-start|step-end|steps( <integer> [, <step-position>]? )",
"subclass-selector": "<id-selector>|<class-selector>|<attribute-selector>|<pseudo-class-selector>",
"supports-condition": "not <supports-in-parens>|<supports-in-parens> [and <supports-in-parens>]*|<supports-in-parens> [or <supports-in-parens>]*",
"supports-in-parens": "( <supports-condition> )|<supports-feature>|<general-enclosed>",
"supports-feature": "<supports-decl>|<supports-selector-fn>",
"supports-decl": "( <declaration> )",
"supports-selector-fn": "selector( <complex-selector> )",
"symbol": "<string>|<image>|<custom-ident>",
"tan()": "tan( <calc-sum> )",
"target": "<target-counter()>|<target-counters()>|<target-text()>",
"target-counter()": "target-counter( [<string>|<url>] , <custom-ident> , <counter-style>? )",
"target-counters()": "target-counters( [<string>|<url>] , <custom-ident> , <string> , <counter-style>? )",
"target-text()": "target-text( [<string>|<url>] , [content|before|after|first-letter]? )",
"time-percentage": "<time>|<percentage>",
"timeline-name": "<custom-ident>|<string>",
"easing-function": "linear|<cubic-bezier-timing-function>|<step-timing-function>",
"track-breadth": "<length-percentage>|<flex>|min-content|max-content|auto",
"track-list": "[<line-names>? [<track-size>|<track-repeat>]]+ <line-names>?",
"track-repeat": "repeat( [<integer [1,∞]>] , [<line-names>? <track-size>]+ <line-names>? )",
"track-size": "<track-breadth>|minmax( <inflexible-breadth> , <track-breadth> )|fit-content( <length-percentage> )",
"transform-function": "<matrix()>|<translate()>|<translateX()>|<translateY()>|<scale()>|<scaleX()>|<scaleY()>|<rotate()>|<skew()>|<skewX()>|<skewY()>|<matrix3d()>|<translate3d()>|<translateZ()>|<scale3d()>|<scaleZ()>|<rotate3d()>|<rotateX()>|<rotateY()>|<rotateZ()>|<perspective()>",
"transform-list": "<transform-function>+",
"translate()": "translate( <length-percentage> , <length-percentage>? )",
"translate3d()": "translate3d( <length-percentage> , <length-percentage> , <length> )",
"translateX()": "translateX( <length-percentage> )",
"translateY()": "translateY( <length-percentage> )",
"translateZ()": "translateZ( <length> )",
"type-or-unit": "string|color|url|integer|number|length|angle|time|frequency|cap|ch|em|ex|ic|lh|rlh|rem|vb|vi|vw|vh|vmin|vmax|mm|Q|cm|in|pt|pc|px|deg|grad|rad|turn|ms|s|Hz|kHz|%",
"type-selector": "<wq-name>|<ns-prefix>? '*'",
"var()": "var( <custom-property-name> , <declaration-value>? )",
"viewport-length": "auto|<length-percentage>",
"visual-box": "content-box|padding-box|border-box",
"wq-name": "<ns-prefix>? <ident-token>",
"-legacy-gradient": "<-webkit-gradient()>|<-legacy-linear-gradient>|<-legacy-repeating-linear-gradient>|<-legacy-radial-gradient>|<-legacy-repeating-radial-gradient>",
"-legacy-linear-gradient": "-moz-linear-gradient( <-legacy-linear-gradient-arguments> )|-webkit-linear-gradient( <-legacy-linear-gradient-arguments> )|-o-linear-gradient( <-legacy-linear-gradient-arguments> )",
"-legacy-repeating-linear-gradient": "-moz-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )|-webkit-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )|-o-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )",
"-legacy-linear-gradient-arguments": "[<angle>|<side-or-corner>]? , <color-stop-list>",
"-legacy-radial-gradient": "-moz-radial-gradient( <-legacy-radial-gradient-arguments> )|-webkit-radial-gradient( <-legacy-radial-gradient-arguments> )|-o-radial-gradient( <-legacy-radial-gradient-arguments> )",
"-legacy-repeating-radial-gradient": "-moz-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )|-webkit-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )|-o-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )",
"-legacy-radial-gradient-arguments": "[<position> ,]? [[[<-legacy-radial-gradient-shape>||<-legacy-radial-gradient-size>]|[<length>|<percentage>]{2}] ,]? <color-stop-list>",
"-legacy-radial-gradient-size": "closest-side|closest-corner|farthest-side|farthest-corner|contain|cover",
"-legacy-radial-gradient-shape": "circle|ellipse",
"-non-standard-font": "-apple-system-body|-apple-system-headline|-apple-system-subheadline|-apple-system-caption1|-apple-system-caption2|-apple-system-footnote|-apple-system-short-body|-apple-system-short-headline|-apple-system-short-subheadline|-apple-system-short-caption1|-apple-system-short-footnote|-apple-system-tall-body",
"-non-standard-color": "-moz-ButtonDefault|-moz-ButtonHoverFace|-moz-ButtonHoverText|-moz-CellHighlight|-moz-CellHighlightText|-moz-Combobox|-moz-ComboboxText|-moz-Dialog|-moz-DialogText|-moz-dragtargetzone|-moz-EvenTreeRow|-moz-Field|-moz-FieldText|-moz-html-CellHighlight|-moz-html-CellHighlightText|-moz-mac-accentdarkestshadow|-moz-mac-accentdarkshadow|-moz-mac-accentface|-moz-mac-accentlightesthighlight|-moz-mac-accentlightshadow|-moz-mac-accentregularhighlight|-moz-mac-accentregularshadow|-moz-mac-chrome-active|-moz-mac-chrome-inactive|-moz-mac-focusring|-moz-mac-menuselect|-moz-mac-menushadow|-moz-mac-menutextselect|-moz-MenuHover|-moz-MenuHoverText|-moz-MenuBarText|-moz-MenuBarHoverText|-moz-nativehyperlinktext|-moz-OddTreeRow|-moz-win-communicationstext|-moz-win-mediatext|-moz-activehyperlinktext|-moz-default-background-color|-moz-default-color|-moz-hyperlinktext|-moz-visitedhyperlinktext|-webkit-activelink|-webkit-focus-ring-color|-webkit-link|-webkit-text",
"-non-standard-image-rendering": "optimize-contrast|-moz-crisp-edges|-o-crisp-edges|-webkit-optimize-contrast",
"-non-standard-overflow": "-moz-scrollbars-none|-moz-scrollbars-horizontal|-moz-scrollbars-vertical|-moz-hidden-unscrollable",
"-non-standard-width": "fill-available|min-intrinsic|intrinsic|-moz-available|-moz-fit-content|-moz-min-content|-moz-max-content|-webkit-min-content|-webkit-max-content",
"-webkit-gradient()": "-webkit-gradient( <-webkit-gradient-type> , <-webkit-gradient-point> [, <-webkit-gradient-point>|, <-webkit-gradient-radius> , <-webkit-gradient-point>] [, <-webkit-gradient-radius>]? [, <-webkit-gradient-color-stop>]* )",
"-webkit-gradient-color-stop": "from( <color> )|color-stop( [<number-zero-one>|<percentage>] , <color> )|to( <color> )",
"-webkit-gradient-point": "[left|center|right|<length-percentage>] [top|center|bottom|<length-percentage>]",
"-webkit-gradient-radius": "<length>|<percentage>",
"-webkit-gradient-type": "linear|radial",
"-webkit-mask-box-repeat": "repeat|stretch|round",
"-webkit-mask-clip-style": "border|border-box|padding|padding-box|content|content-box|text",
"-ms-filter-function-list": "<-ms-filter-function>+",
"-ms-filter-function": "<-ms-filter-function-progid>|<-ms-filter-function-legacy>",
"-ms-filter-function-progid": "'progid:' [<ident-token> '.']* [<ident-token>|<function-token> <any-value>? )]",
"-ms-filter-function-legacy": "<ident-token>|<function-token> <any-value>? )",
"-ms-filter": "<string>",
"age": "child|young|old",
"attr-name": "<wq-name>",
"attr-fallback": "<any-value>",
"bg-clip": "<box>|border|text",
"bottom": "<length>|auto",
"generic-voice": "[<age>? <gender> <integer>?]",
"gender": "male|female|neutral",
"left": "<length>|auto",
"mask-image": "<mask-reference>#",
"paint": "none|<color>|<url> [none|<color>]?|context-fill|context-stroke",
"right": "<length>|auto",
"scroll-timeline-axis": "block|inline|vertical|horizontal",
"scroll-timeline-name": "none|<custom-ident>",
"single-animation-composition": "replace|add|accumulate",
"svg-length": "<percentage>|<length>|<number>",
"svg-writing-mode": "lr-tb|rl-tb|tb-rl|lr|rl|tb",
"top": "<length>|auto",
"x": "<number>",
"y": "<number>",
"declaration": "<ident-token> : <declaration-value>? ['!' important]?",
"declaration-list": "[<declaration>? ';']* <declaration>?",
"url": "url( <string> <url-modifier>* )|<url-token>",
"url-modifier": "<ident>|<function-token> <any-value> )",
"number-zero-one": "<number [0,1]>",
"number-one-or-greater": "<number [1,∞]>",
"-non-standard-display": "-ms-inline-flexbox|-ms-grid|-ms-inline-grid|-webkit-flex|-webkit-inline-flex|-webkit-box|-webkit-inline-box|-moz-inline-stack|-moz-box|-moz-inline-box"
},
"properties": {
"--*": "<declaration-value>",
"-ms-accelerator": "false|true",
"-ms-block-progression": "tb|rl|bt|lr",
"-ms-content-zoom-chaining": "none|chained",
"-ms-content-zooming": "none|zoom",
"-ms-content-zoom-limit": "<'-ms-content-zoom-limit-min'> <'-ms-content-zoom-limit-max'>",
"-ms-content-zoom-limit-max": "<percentage>",
"-ms-content-zoom-limit-min": "<percentage>",
"-ms-content-zoom-snap": "<'-ms-content-zoom-snap-type'>||<'-ms-content-zoom-snap-points'>",
"-ms-content-zoom-snap-points": "snapInterval( <percentage> , <percentage> )|snapList( <percentage># )",
"-ms-content-zoom-snap-type": "none|proximity|mandatory",
"-ms-filter": "<string>",
"-ms-flow-from": "[none|<custom-ident>]#",
"-ms-flow-into": "[none|<custom-ident>]#",
"-ms-grid-columns": "none|<track-list>|<auto-track-list>",
"-ms-grid-rows": "none|<track-list>|<auto-track-list>",
"-ms-high-contrast-adjust": "auto|none",
"-ms-hyphenate-limit-chars": "auto|<integer>{1,3}",
"-ms-hyphenate-limit-lines": "no-limit|<integer>",
"-ms-hyphenate-limit-zone": "<percentage>|<length>",
"-ms-ime-align": "auto|after",
"-ms-overflow-style": "auto|none|scrollbar|-ms-autohiding-scrollbar",
"-ms-scrollbar-3dlight-color": "<color>",
"-ms-scrollbar-arrow-color": "<color>",
"-ms-scrollbar-base-color": "<color>",
"-ms-scrollbar-darkshadow-color": "<color>",
"-ms-scrollbar-face-color": "<color>",
"-ms-scrollbar-highlight-color": "<color>",
"-ms-scrollbar-shadow-color": "<color>",
"-ms-scrollbar-track-color": "<color>",
"-ms-scroll-chaining": "chained|none",
"-ms-scroll-limit": "<'-ms-scroll-limit-x-min'> <'-ms-scroll-limit-y-min'> <'-ms-scroll-limit-x-max'> <'-ms-scroll-limit-y-max'>",
"-ms-scroll-limit-x-max": "auto|<length>",
"-ms-scroll-limit-x-min": "<length>",
"-ms-scroll-limit-y-max": "auto|<length>",
"-ms-scroll-limit-y-min": "<length>",
"-ms-scroll-rails": "none|railed",
"-ms-scroll-snap-points-x": "snapInterval( <length-percentage> , <length-percentage> )|snapList( <length-percentage># )",
"-ms-scroll-snap-points-y": "snapInterval( <length-percentage> , <length-percentage> )|snapList( <length-percentage># )",
"-ms-scroll-snap-type": "none|proximity|mandatory",
"-ms-scroll-snap-x": "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-x'>",
"-ms-scroll-snap-y": "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-y'>",
"-ms-scroll-translation": "none|vertical-to-horizontal",
"-ms-text-autospace": "none|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space",
"-ms-touch-select": "grippers|none",
"-ms-user-select": "none|element|text",
"-ms-wrap-flow": "auto|both|start|end|maximum|clear",
"-ms-wrap-margin": "<length>",
"-ms-wrap-through": "wrap|none",
"-moz-appearance": "none|button|button-arrow-down|button-arrow-next|button-arrow-previous|button-arrow-up|button-bevel|button-focus|caret|checkbox|checkbox-container|checkbox-label|checkmenuitem|dualbutton|groupbox|listbox|listitem|menuarrow|menubar|menucheckbox|menuimage|menuitem|menuitemtext|menulist|menulist-button|menulist-text|menulist-textfield|menupopup|menuradio|menuseparator|meterbar|meterchunk|progressbar|progressbar-vertical|progresschunk|progresschunk-vertical|radio|radio-container|radio-label|radiomenuitem|range|range-thumb|resizer|resizerpanel|scale-horizontal|scalethumbend|scalethumb-horizontal|scalethumbstart|scalethumbtick|scalethumb-vertical|scale-vertical|scrollbarbutton-down|scrollbarbutton-left|scrollbarbutton-right|scrollbarbutton-up|scrollbarthumb-horizontal|scrollbarthumb-vertical|scrollbartrack-horizontal|scrollbartrack-vertical|searchfield|separator|sheet|spinner|spinner-downbutton|spinner-textfield|spinner-upbutton|splitter|statusbar|statusbarpanel|tab|