// ==UserScript==
// @name nHentai Helper
// @name:zh-CN nHentai 助手
// @name:zh-TW nHentai 助手
// @namespace https://github.com/Tsuk1ko
// @version 3.3.8
// @author Jindai Kirin
// @description Download nHentai manga as compression file easily, and add some useful features. Also support some mirror sites.
// @description:zh-CN 为 nHentai 增加压缩打包下载方式以及一些辅助功能,同时还支持一些镜像站
// @description:zh-TW 爲 nHentai 增加壓縮打包下載方式以及一些輔助功能,同時還支援一些鏡像站
// @license GPL-3.0
// @icon https://nhentai.net/favicon.ico
// @homepageURL https://github.com/Tsuk1ko/nhentai-helper
// @supportURL https://github.com/Tsuk1ko/nhentai-helper/issues
// @include /^https:\/\/([^/]*\.)?(nya|dog|cat|bug|qq|fox|ee|yy)hentai[0-9]*\./
// @match https://nhentai.net/*
// @match https://nhentai.xxx/*
// @match https://nhentai.to/*
// @match https://nhentai.website/*
// @require https://fastly.jsdelivr.net/npm/comlink@4.3.1/dist/umd/comlink.min.js
// @require https://fastly.jsdelivr.net/npm/eventemitter3@4.0.7/umd/eventemitter3.min.js
// @require https://fastly.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js
// @require https://fastly.jsdelivr.net/npm/jquery@3.6.1/dist/jquery.min.js
// @require https://fastly.jsdelivr.net/npm/jquery-pjax@2.0.1/jquery.pjax.min.js
// @require https://fastly.jsdelivr.net/npm/localforage@1.10.0/dist/localforage.min.js
// @require https://fastly.jsdelivr.net/npm/md5@2.3.0/dist/md5.min.js
// @require https://fastly.jsdelivr.net/npm/noty@3.1.4/lib/noty.min.js
// @require https://fastly.jsdelivr.net/npm/streamsaver@2.0.6/StreamSaver.min.js
// @require https://fastly.jsdelivr.net/npm/vue@3.2.38/dist/vue.global.prod.js
// @connect nhentai.net
// @connect i.nhentai.net
// @connect cdn.nhentai.xxx
// @connect cdn.nload.xyz
// @resource notyCss https://fastly.jsdelivr.net/npm/noty@3.1.4/lib/noty.min.css
// @resource elementPlusJs https://fastly.jsdelivr.net/npm/element-plus@2.2.16/dist/index.full.min.js
// @resource elementPlusCss https://fastly.jsdelivr.net/npm/element-plus@2.2.16/dist/index.css
// @grant GM_addStyle
// @grant GM_getResourceText
// @grant GM_registerMenuCommand
// @grant unsafeWindow
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @run-at document-end
// @noframes
// ==/UserScript==
(t=>{const e=document.createElement("style");e.dataset.source="vite-plugin-monkey",e.innerText=t,document.head.appendChild(e)})('.nhentai-helper-btn:disabled{cursor:wait}.gallery>.nhentai-helper-btn{position:absolute;top:0;min-width:42px;opacity:.8}.gallery:hover>.nhentai-helper-btn{opacity:1}.gallery .download-zip-btn{left:0}.gallery .ignore-btn{right:0}#page-container{position:relative}@media screen and (max-width: 768px){#page-container{padding-top:40px}}#online-view-mode-btn{position:absolute;right:0;top:0;margin:0}.btn-noty-green{background-color:#66bb6a!important}.btn-noty-blue{background-color:#42a5f5!important}.btn-noty:hover{filter:brightness(1.15)}.noty_buttons{padding-top:0!important}.pages-input{-webkit-appearance:none;display:inline-block;border-radius:3px;padding:0 .1em 0 1em;font-size:1em;width:100%;height:40px;border:0;vertical-align:top;margin-top:5px}.gallery.downloaded .caption{color:#999}.download-item[data-v-5e3261cd]{position:relative;white-space:nowrap;padding:2px;overflow:visible}.download-item--can-cancel[data-v-5e3261cd]:hover{width:calc(100% - 30px)}.download-item__cancel[data-v-5e3261cd]{cursor:pointer;position:absolute;top:0;right:-30px;color:#f44336;font-size:20px;line-height:30px;width:30px}.download-item__title[data-v-5e3261cd]{overflow:hidden;text-overflow:ellipsis;text-align:left}.download-item__progress[data-v-5e3261cd]{background-color:#0000ff80;line-height:10px}.download-item--error .download-item__progress[data-v-5e3261cd]{background-color:#ff000080}.download-item--compressing .download-item__progress[data-v-5e3261cd]{background-color:#00ff0080}.download-item__progress-text[data-v-5e3261cd]{transform:scale(.8)}#download-panel[data-v-658acab9]{overflow-x:hidden;position:fixed;top:20vh;right:0;width:calc(50vw - 620px);max-width:300px;min-width:150px;max-height:60vh;background-color:#000000b3;z-index:100;font-size:12px;overflow-y:scroll}#download-panel[data-v-658acab9]::-webkit-scrollbar{width:6px;background-color:#000000b3}#download-panel[data-v-658acab9]::-webkit-scrollbar-thumb{background-color:#fff9}.nhentai-helper-setting-help-buttons{float:left;position:absolute}#nhentai-helper-setting-dialog .asterisk-left:before{content:"*";color:var(--el-color-danger);margin-right:4px}#nhentai-helper-setting-dialog label{font-weight:unset}#nhentai-helper-setting-dialog input:not([type="file"]):not([type="checkbox"]){background:inherit;color:var(--el-input-text-color, var(--el-text-color-regular))}#nhentai-helper-setting-dialog .el-input.is-disabled .el-input__inner{color:var(--el-disabled-text-color)}#nhentai-helper-setting-dialog .el-slider__stop{border:solid 1px var(--el-slider-runway-bg-color)}#nhentai-helper-setting-dialog .el-form-item:last-of-type{margin-bottom:0}#nhentai-helper-setting-dialog .el-form-item.refresh-required>.el-form-item__label-wrap>.el-form-item__label:after{content:"*";color:var(--el-color-danger);margin-left:4px}#nhentai-helper-setting-dialog .el-divider__text{color:var(--el-text-color-secondary);user-select:none}#nhentai-helper-setting-dialog .m-l-16{margin-left:16px}#nhentai-helper-setting-dialog .m-b-32{margin-bottom:32px}#nhentai-helper-setting-dialog .no-sl,#nhentai-helper-setting-dialog .el-form-item__label{user-select:none}');
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
(function($, jqueryPjax, Vue, eventemitter3, fileSaver, localforage, md5, comlink, Noty, streamsaver) {
var _a, _b;
"use strict";
const _interopDefaultLegacy = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
function _interopNamespace(e) {
if (e && e.__esModule)
return e;
const n2 = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
if (e) {
for (const k in e) {
if (k !== "default") {
const d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n2, k, d.get ? d : {
enumerable: true,
get: () => e[k]
});
}
}
}
n2.default = e;
return Object.freeze(n2);
}
const $__default = /* @__PURE__ */ _interopDefaultLegacy($);
const Vue__namespace = /* @__PURE__ */ _interopNamespace(Vue);
const localforage__default = /* @__PURE__ */ _interopDefaultLegacy(localforage);
const md5__default = /* @__PURE__ */ _interopDefaultLegacy(md5);
const Noty__default = /* @__PURE__ */ _interopDefaultLegacy(Noty);
var r = (_a = Reflect.get(document, "__monkeyWindow")) != null ? _a : window;
r.GM;
r.unsafeWindow = (_b = r.unsafeWindow) != null ? _b : window;
var n = r.unsafeWindow;
r.GM_info;
r.GM_cookie;
var u = (...e) => r.GM_setValue(...e), l = (...e) => r.GM_addStyle(...e), m = (...e) => r.GM_registerMenuCommand(...e), b = (...e) => r.GM_xmlhttpRequest(...e), h = (...e) => r.GM_getValue(...e);
const WORKER_THREAD_NUM = Math.max(navigator.hardwareConcurrency - 1, 1);
const { pathname, host } = location;
const IS_PAGE_MANGA_DETAIL = /^\/g\/[0-9]+\/?(\?.*)?$/.test(pathname);
const IS_PAGE_ONLINE_VIEW = /^\/g\/[0-9]+(\/list)?\/[0-9]+\/?(\?.*)?$/.test(pathname);
const IS_PAGE_MANGA_LIST = !IS_PAGE_MANGA_DETAIL && !IS_PAGE_ONLINE_VIEW && document.getElementsByClassName("gallery").length > 0;
const IS_NHENTAI = host === "nhentai.net";
const IS_NHENTAI_TO = host === "nhentai.to" || host === "nhentai.website";
const isNodeOrElement = typeof Node === "function" ? (val) => val instanceof Node : (val) => val && typeof val === "object" && typeof val.nodeType === "number" && typeof val.nodeName === "string";
if (IS_NHENTAI) {
if (h("prevent_console_clear", false) || localStorage.getItem("NHENTAI_HELPER_DEBUG")) {
const c = n.console;
c._clear = c.clear;
c.clear = () => {
};
c._log = c.log;
c.log = (...args) => {
if (args.length === 1 && isNodeOrElement(args[0]))
return;
return c._log(...args);
};
}
}
const logger = {
log: (...args) => console.log("[nhentai-helper]", ...args),
warn: (...args) => console.warn("[nhentai-helper]", ...args),
error: (...args) => console.error("[nhentai-helper]", ...args)
};
const index = "";
const cssLoader = (e) => {
const t = GM_getResourceText(e);
return GM_addStyle(t), t;
}, rawLoader = (e) => GM_getResourceText(e);
cssLoader("notyCss");
var functionOnce = once;
function once(fn) {
var called, value;
if (typeof fn !== "function") {
throw new Error("expected a function but got " + fn);
}
return function wrap() {
if (called) {
return value;
}
called = true;
value = fn.apply(this, arguments);
fn = void 0;
return value;
};
}
let getRandomValues;
const rnds8 = new Uint8Array(16);
function rng() {
if (!getRandomValues) {
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
if (!getRandomValues) {
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
}
}
return getRandomValues(rnds8);
}
const byteToHex = [];
for (let i = 0; i < 256; ++i) {
byteToHex.push((i + 256).toString(16).slice(1));
}
function unsafeStringify(arr, offset = 0) {
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
}
const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
const native = {
randomUUID
};
function v4(options, buf, offset) {
if (native.randomUUID && !buf && !options) {
return native.randomUUID();
}
options = options || {};
const rnds = options.random || (options.rng || rng)();
rnds[6] = rnds[6] & 15 | 64;
rnds[8] = rnds[8] & 63 | 128;
if (buf) {
offset = offset || 0;
for (let i = 0; i < 16; ++i) {
buf[offset + i] = rnds[i];
}
return buf;
}
return unsafeStringify(rnds);
}
const removeAt = (array, index2) => array.splice(index2, 1)[0];
class AsyncQueue {
constructor(thread = 1) {
__publicField(this, "queue", Vue.reactive([]));
__publicField(this, "emitter", new eventemitter3.EventEmitter());
__publicField(this, "canSingleStart", () => true);
__publicField(this, "singleRunning", false);
this.thread = thread;
}
get runningThreadNum() {
return this.queue.filter(({ running }) => running).length;
}
get length() {
return this.queue.length;
}
push(fn, info) {
this.queue.push({
id: v4(),
running: false,
fn,
info
});
}
async start() {
if (this.thread <= 1) {
if (this.singleRunning || this.queue.length === 0)
return;
this.singleRunning = true;
do {
if (!this.canSingleStart()) {
this.singleRunning = false;
return;
}
await this.queue[0].fn();
this.queue.shift();
} while (this.queue.length > 0);
this.singleRunning = false;
this.emitter.emit("finish");
} else {
const running = this.runningThreadNum;
if (running >= this.thread || this.queue.length === running)
return;
const idleItems = this.queue.filter(({ running: running2 }) => !running2);
for (let i = 0; i < Math.min(idleItems.length, this.thread - running); i++) {
const item = idleItems[i];
item.running = true;
item.fn().then(async () => {
removeAt(
this.queue,
this.queue.findIndex(({ id }) => id === item.id)
);
if (this.queue.length)
await this.start();
else
this.emitter.emit("finish");
}).catch(logger.error);
}
}
}
async skipFromError() {
this.queue.shift();
await this.restartFromError();
}
async restartFromError() {
this.singleRunning = false;
await this.start();
}
}
var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
const freeGlobal$1 = freeGlobal;
var freeSelf = typeof self == "object" && self && self.Object === Object && self;
var root = freeGlobal$1 || freeSelf || Function("return this")();
const root$1 = root;
var Symbol$1 = root$1.Symbol;
const Symbol$2 = Symbol$1;
var objectProto$h = Object.prototype;
var hasOwnProperty$d = objectProto$h.hasOwnProperty;
var nativeObjectToString$2 = objectProto$h.toString;
var symToStringTag$1 = Symbol$2 ? Symbol$2.toStringTag : void 0;
function getRawTag(value) {
var isOwn = hasOwnProperty$d.call(value, symToStringTag$1), tag = value[symToStringTag$1];
try {
value[symToStringTag$1] = void 0;
var unmasked = true;
} catch (e) {
}
var result = nativeObjectToString$2.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag$1] = tag;
} else {
delete value[symToStringTag$1];
}
}
return result;
}
var objectProto$g = Object.prototype;
var nativeObjectToString$1 = objectProto$g.toString;
function objectToString(value) {
return nativeObjectToString$1.call(value);
}
var nullTag = "[object Null]", undefinedTag = "[object Undefined]";
var symToStringTag = Symbol$2 ? Symbol$2.toStringTag : void 0;
function baseGetTag(value) {
if (value == null) {
return value === void 0 ? undefinedTag : nullTag;
}
return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
}
function isObjectLike(value) {
return value != null && typeof value == "object";
}
var symbolTag$1 = "[object Symbol]";
function isSymbol(value) {
return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag$1;
}
function arrayMap(array, iteratee) {
var index2 = -1, length = array == null ? 0 : array.length, result = Array(length);
while (++index2 < length) {
result[index2] = iteratee(array[index2], index2, array);
}
return result;
}
var isArray = Array.isArray;
const isArray$1 = isArray;
var INFINITY$1 = 1 / 0;
var symbolProto$1 = Symbol$2 ? Symbol$2.prototype : void 0, symbolToString = symbolProto$1 ? symbolProto$1.toString : void 0;
function baseToString(value) {
if (typeof value == "string") {
return value;
}
if (isArray$1(value)) {
return arrayMap(value, baseToString) + "";
}
if (isSymbol(value)) {
return symbolToString ? symbolToString.call(value) : "";
}
var result = value + "";
return result == "0" && 1 / value == -INFINITY$1 ? "-0" : result;
}
function isObject(value) {
var type = typeof value;
return value != null && (type == "object" || type == "function");
}
function identity(value) {
return value;
}
var asyncTag = "[object AsyncFunction]", funcTag$1 = "[object Function]", genTag = "[object GeneratorFunction]", proxyTag = "[object Proxy]";
function isFunction(value) {
if (!isObject(value)) {
return false;
}
var tag = baseGetTag(value);
return tag == funcTag$1 || tag == genTag || tag == asyncTag || tag == proxyTag;
}
var coreJsData = root$1["__core-js_shared__"];
const coreJsData$1 = coreJsData;
var maskSrcKey = function() {
var uid = /[^.]+$/.exec(coreJsData$1 && coreJsData$1.keys && coreJsData$1.keys.IE_PROTO || "");
return uid ? "Symbol(src)_1." + uid : "";
}();
function isMasked(func) {
return !!maskSrcKey && maskSrcKey in func;
}
var funcProto$2 = Function.prototype;
var funcToString$2 = funcProto$2.toString;
function toSource(func) {
if (func != null) {
try {
return funcToString$2.call(func);
} catch (e) {
}
try {
return func + "";
} catch (e) {
}
}
return "";
}
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
var reIsHostCtor = /^\[object .+?Constructor\]$/;
var funcProto$1 = Function.prototype, objectProto$f = Object.prototype;
var funcToString$1 = funcProto$1.toString;
var hasOwnProperty$c = objectProto$f.hasOwnProperty;
var reIsNative = RegExp(
"^" + funcToString$1.call(hasOwnProperty$c).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
);
function baseIsNative(value) {
if (!isObject(value) || isMasked(value)) {
return false;
}
var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
return pattern.test(toSource(value));
}
function getValue(object, key) {
return object == null ? void 0 : object[key];
}
function getNative(object, key) {
var value = getValue(object, key);
return baseIsNative(value) ? value : void 0;
}
var WeakMap = getNative(root$1, "WeakMap");
const WeakMap$1 = WeakMap;
function apply(func, thisArg, args) {
switch (args.length) {
case 0:
return func.call(thisArg);
case 1:
return func.call(thisArg, args[0]);
case 2:
return func.call(thisArg, args[0], args[1]);
case 3:
return func.call(thisArg, args[0], args[1], args[2]);
}
return func.apply(thisArg, args);
}
var HOT_COUNT = 800, HOT_SPAN = 16;
var nativeNow = Date.now;
function shortOut(func) {
var count = 0, lastCalled = 0;
return function() {
var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled);
lastCalled = stamp;
if (remaining > 0) {
if (++count >= HOT_COUNT) {
return arguments[0];
}
} else {
count = 0;
}
return func.apply(void 0, arguments);
};
}
function constant(value) {
return function() {
return value;
};
}
var defineProperty = function() {
try {
var func = getNative(Object, "defineProperty");
func({}, "", {});
return func;
} catch (e) {
}
}();
const defineProperty$1 = defineProperty;
var baseSetToString = !defineProperty$1 ? identity : function(func, string) {
return defineProperty$1(func, "toString", {
"configurable": true,
"enumerable": false,
"value": constant(string),
"writable": true
});
};
const baseSetToString$1 = baseSetToString;
var setToString = shortOut(baseSetToString$1);
const setToString$1 = setToString;
function arrayEach(array, iteratee) {
var index2 = -1, length = array == null ? 0 : array.length;
while (++index2 < length) {
if (iteratee(array[index2], index2, array) === false) {
break;
}
}
return array;
}
var MAX_SAFE_INTEGER$1 = 9007199254740991;
var reIsUint = /^(?:0|[1-9]\d*)$/;
function isIndex(value, length) {
var type = typeof value;
length = length == null ? MAX_SAFE_INTEGER$1 : length;
return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
}
function baseAssignValue(object, key, value) {
if (key == "__proto__" && defineProperty$1) {
defineProperty$1(object, key, {
"configurable": true,
"enumerable": true,
"value": value,
"writable": true
});
} else {
object[key] = value;
}
}
function eq(value, other) {
return value === other || value !== value && other !== other;
}
var objectProto$e = Object.prototype;
var hasOwnProperty$b = objectProto$e.hasOwnProperty;
function assignValue(object, key, value) {
var objValue = object[key];
if (!(hasOwnProperty$b.call(object, key) && eq(objValue, value)) || value === void 0 && !(key in object)) {
baseAssignValue(object, key, value);
}
}
function copyObject(source, props, object, customizer) {
var isNew = !object;
object || (object = {});
var index2 = -1, length = props.length;
while (++index2 < length) {
var key = props[index2];
var newValue = customizer ? customizer(object[key], source[key], key, object, source) : void 0;
if (newValue === void 0) {
newValue = source[key];
}
if (isNew) {
baseAssignValue(object, key, newValue);
} else {
assignValue(object, key, newValue);
}
}
return object;
}
var nativeMax = Math.max;
function overRest(func, start, transform) {
start = nativeMax(start === void 0 ? func.length - 1 : start, 0);
return function() {
var args = arguments, index2 = -1, length = nativeMax(args.length - start, 0), array = Array(length);
while (++index2 < length) {
array[index2] = args[start + index2];
}
index2 = -1;
var otherArgs = Array(start + 1);
while (++index2 < start) {
otherArgs[index2] = args[index2];
}
otherArgs[start] = transform(array);
return apply(func, this, otherArgs);
};
}
function baseRest(func, start) {
return setToString$1(overRest(func, start, identity), func + "");
}
var MAX_SAFE_INTEGER = 9007199254740991;
function isLength(value) {
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}
function isArrayLike(value) {
return value != null && isLength(value.length) && !isFunction(value);
}
function isIterateeCall(value, index2, object) {
if (!isObject(object)) {
return false;
}
var type = typeof index2;
if (type == "number" ? isArrayLike(object) && isIndex(index2, object.length) : type == "string" && index2 in object) {
return eq(object[index2], value);
}
return false;
}
function createAssigner(assigner) {
return baseRest(function(object, sources) {
var index2 = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : void 0, guard = length > 2 ? sources[2] : void 0;
customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : void 0;
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
customizer = length < 3 ? void 0 : customizer;
length = 1;
}
object = Object(object);
while (++index2 < length) {
var source = sources[index2];
if (source) {
assigner(object, source, index2, customizer);
}
}
return object;
});
}
var objectProto$d = Object.prototype;
function isPrototype(value) {
var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto$d;
return value === proto;
}
function baseTimes(n2, iteratee) {
var index2 = -1, result = Array(n2);
while (++index2 < n2) {
result[index2] = iteratee(index2);
}
return result;
}
var argsTag$2 = "[object Arguments]";
function baseIsArguments(value) {
return isObjectLike(value) && baseGetTag(value) == argsTag$2;
}
var objectProto$c = Object.prototype;
var hasOwnProperty$a = objectProto$c.hasOwnProperty;
var propertyIsEnumerable$1 = objectProto$c.propertyIsEnumerable;
var isArguments = baseIsArguments(function() {
return arguments;
}()) ? baseIsArguments : function(value) {
return isObjectLike(value) && hasOwnProperty$a.call(value, "callee") && !propertyIsEnumerable$1.call(value, "callee");
};
const isArguments$1 = isArguments;
function stubFalse() {
return false;
}
var freeExports$1 = typeof exports == "object" && exports && !exports.nodeType && exports;
var freeModule$1 = freeExports$1 && typeof module == "object" && module && !module.nodeType && module;
var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1;
var Buffer = moduleExports$1 ? root$1.Buffer : void 0;
var nativeIsBuffer = Buffer ? Buffer.isBuffer : void 0;
var isBuffer = nativeIsBuffer || stubFalse;
const isBuffer$1 = isBuffer;
var argsTag$1 = "[object Arguments]", arrayTag$1 = "[object Array]", boolTag$1 = "[object Boolean]", dateTag$1 = "[object Date]", errorTag$2 = "[object Error]", funcTag = "[object Function]", mapTag$2 = "[object Map]", numberTag$1 = "[object Number]", objectTag$3 = "[object Object]", regexpTag$1 = "[object RegExp]", setTag$2 = "[object Set]", stringTag$1 = "[object String]", weakMapTag$1 = "[object WeakMap]";
var arrayBufferTag$1 = "[object ArrayBuffer]", dataViewTag$2 = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag$1] = typedArrayTags[arrayTag$1] = typedArrayTags[arrayBufferTag$1] = typedArrayTags[boolTag$1] = typedArrayTags[dataViewTag$2] = typedArrayTags[dateTag$1] = typedArrayTags[errorTag$2] = typedArrayTags[funcTag] = typedArrayTags[mapTag$2] = typedArrayTags[numberTag$1] = typedArrayTags[objectTag$3] = typedArrayTags[regexpTag$1] = typedArrayTags[setTag$2] = typedArrayTags[stringTag$1] = typedArrayTags[weakMapTag$1] = false;
function baseIsTypedArray(value) {
return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}
function baseUnary(func) {
return function(value) {
return func(value);
};
}
var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports;
var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module;
var moduleExports = freeModule && freeModule.exports === freeExports;
var freeProcess = moduleExports && freeGlobal$1.process;
var nodeUtil = function() {
try {
var types = freeModule && freeModule.require && freeModule.require("util").types;
if (types) {
return types;
}
return freeProcess && freeProcess.binding && freeProcess.binding("util");
} catch (e) {
}
}();
const nodeUtil$1 = nodeUtil;
var nodeIsTypedArray = nodeUtil$1 && nodeUtil$1.isTypedArray;
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
const isTypedArray$1 = isTypedArray;
var objectProto$b = Object.prototype;
var hasOwnProperty$9 = objectProto$b.hasOwnProperty;
function arrayLikeKeys(value, inherited) {
var isArr = isArray$1(value), isArg = !isArr && isArguments$1(value), isBuff = !isArr && !isArg && isBuffer$1(value), isType = !isArr && !isArg && !isBuff && isTypedArray$1(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes(value.length, String) : [], length = result.length;
for (var key in value) {
if ((inherited || hasOwnProperty$9.call(value, key)) && !(skipIndexes && (key == "length" || isBuff && (key == "offset" || key == "parent") || isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || isIndex(key, length)))) {
result.push(key);
}
}
return result;
}
function overArg(func, transform) {
return function(arg) {
return func(transform(arg));
};
}
var nativeKeys = overArg(Object.keys, Object);
const nativeKeys$1 = nativeKeys;
var objectProto$a = Object.prototype;
var hasOwnProperty$8 = objectProto$a.hasOwnProperty;
function baseKeys(object) {
if (!isPrototype(object)) {
return nativeKeys$1(object);
}
var result = [];
for (var key in Object(object)) {
if (hasOwnProperty$8.call(object, key) && key != "constructor") {
result.push(key);
}
}
return result;
}
function keys(object) {
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}
function nativeKeysIn(object) {
var result = [];
if (object != null) {
for (var key in Object(object)) {
result.push(key);
}
}
return result;
}
var objectProto$9 = Object.prototype;
var hasOwnProperty$7 = objectProto$9.hasOwnProperty;
function baseKeysIn(object) {
if (!isObject(object)) {
return nativeKeysIn(object);
}
var isProto = isPrototype(object), result = [];
for (var key in object) {
if (!(key == "constructor" && (isProto || !hasOwnProperty$7.call(object, key)))) {
result.push(key);
}
}
return result;
}
function keysIn(object) {
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
}
var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
copyObject(source, keysIn(source), object, customizer);
});
const extendWith = assignInWith;
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/;
function isKey(value, object) {
if (isArray$1(value)) {
return false;
}
var type = typeof value;
if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol(value)) {
return true;
}
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
}
var nativeCreate = getNative(Object, "create");
const nativeCreate$1 = nativeCreate;
function hashClear() {
this.__data__ = nativeCreate$1 ? nativeCreate$1(null) : {};
this.size = 0;
}
function hashDelete(key) {
var result = this.has(key) && delete this.__data__[key];
this.size -= result ? 1 : 0;
return result;
}
var HASH_UNDEFINED$2 = "__lodash_hash_undefined__";
var objectProto$8 = Object.prototype;
var hasOwnProperty$6 = objectProto$8.hasOwnProperty;
function hashGet(key) {
var data = this.__data__;
if (nativeCreate$1) {
var result = data[key];
return result === HASH_UNDEFINED$2 ? void 0 : result;
}
return hasOwnProperty$6.call(data, key) ? data[key] : void 0;
}
var objectProto$7 = Object.prototype;
var hasOwnProperty$5 = objectProto$7.hasOwnProperty;
function hashHas(key) {
var data = this.__data__;
return nativeCreate$1 ? data[key] !== void 0 : hasOwnProperty$5.call(data, key);
}
var HASH_UNDEFINED$1 = "__lodash_hash_undefined__";
function hashSet(key, value) {
var data = this.__data__;
this.size += this.has(key) ? 0 : 1;
data[key] = nativeCreate$1 && value === void 0 ? HASH_UNDEFINED$1 : value;
return this;
}
function Hash(entries) {
var index2 = -1, length = entries == null ? 0 : entries.length;
this.clear();
while (++index2 < length) {
var entry = entries[index2];
this.set(entry[0], entry[1]);
}
}
Hash.prototype.clear = hashClear;
Hash.prototype["delete"] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;
function listCacheClear() {
this.__data__ = [];
this.size = 0;
}
function assocIndexOf(array, key) {
var length = array.length;
while (length--) {
if (eq(array[length][0], key)) {
return length;
}
}
return -1;
}
var arrayProto = Array.prototype;
var splice = arrayProto.splice;
function listCacheDelete(key) {
var data = this.__data__, index2 = assocIndexOf(data, key);
if (index2 < 0) {
return false;
}
var lastIndex = data.length - 1;
if (index2 == lastIndex) {
data.pop();
} else {
splice.call(data, index2, 1);
}
--this.size;
return true;
}
function listCacheGet(key) {
var data = this.__data__, index2 = assocIndexOf(data, key);
return index2 < 0 ? void 0 : data[index2][1];
}
function listCacheHas(key) {
return assocIndexOf(this.__data__, key) > -1;
}
function listCacheSet(key, value) {
var data = this.__data__, index2 = assocIndexOf(data, key);
if (index2 < 0) {
++this.size;
data.push([key, value]);
} else {
data[index2][1] = value;
}
return this;
}
function ListCache(entries) {
var index2 = -1, length = entries == null ? 0 : entries.length;
this.clear();
while (++index2 < length) {
var entry = entries[index2];
this.set(entry[0], entry[1]);
}
}
ListCache.prototype.clear = listCacheClear;
ListCache.prototype["delete"] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;
var Map = getNative(root$1, "Map");
const Map$1 = Map;
function mapCacheClear() {
this.size = 0;
this.__data__ = {
"hash": new Hash(),
"map": new (Map$1 || ListCache)(),
"string": new Hash()
};
}
function isKeyable(value) {
var type = typeof value;
return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null;
}
function getMapData(map, key) {
var data = map.__data__;
return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
}
function mapCacheDelete(key) {
var result = getMapData(this, key)["delete"](key);
this.size -= result ? 1 : 0;
return result;
}
function mapCacheGet(key) {
return getMapData(this, key).get(key);
}
function mapCacheHas(key) {
return getMapData(this, key).has(key);
}
function mapCacheSet(key, value) {
var data = getMapData(this, key), size = data.size;
data.set(key, value);
this.size += data.size == size ? 0 : 1;
return this;
}
function MapCache(entries) {
var index2 = -1, length = entries == null ? 0 : entries.length;
this.clear();
while (++index2 < length) {
var entry = entries[index2];
this.set(entry[0], entry[1]);
}
}
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype["delete"] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;
var FUNC_ERROR_TEXT = "Expected a function";
function memoize(func, resolver) {
if (typeof func != "function" || resolver != null && typeof resolver != "function") {
throw new TypeError(FUNC_ERROR_TEXT);
}
var memoized = function() {
var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache;
if (cache.has(key)) {
return cache.get(key);
}
var result = func.apply(this, args);
memoized.cache = cache.set(key, result) || cache;
return result;
};
memoized.cache = new (memoize.Cache || MapCache)();
return memoized;
}
memoize.Cache = MapCache;
var MAX_MEMOIZE_SIZE = 500;
function memoizeCapped(func) {
var result = memoize(func, function(key) {
if (cache.size === MAX_MEMOIZE_SIZE) {
cache.clear();
}
return key;
});
var cache = result.cache;
return result;
}
var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
var reEscapeChar = /\\(\\)?/g;
var stringToPath = memoizeCapped(function(string) {
var result = [];
if (string.charCodeAt(0) === 46) {
result.push("");
}
string.replace(rePropName, function(match2, number, quote, subString) {
result.push(quote ? subString.replace(reEscapeChar, "$1") : number || match2);
});
return result;
});
const stringToPath$1 = stringToPath;
function toString(value) {
return value == null ? "" : baseToString(value);
}
function castPath(value, object) {
if (isArray$1(value)) {
return value;
}
return isKey(value, object) ? [value] : stringToPath$1(toString(value));
}
var INFINITY = 1 / 0;
function toKey(value) {
if (typeof value == "string" || isSymbol(value)) {
return value;
}
var result = value + "";
return result == "0" && 1 / value == -INFINITY ? "-0" : result;
}
function baseGet(object, path) {
path = castPath(path, object);
var index2 = 0, length = path.length;
while (object != null && index2 < length) {
object = object[toKey(path[index2++])];
}
return index2 && index2 == length ? object : void 0;
}
function get(object, path, defaultValue) {
var result = object == null ? void 0 : baseGet(object, path);
return result === void 0 ? defaultValue : result;
}
function arrayPush(array, values) {
var index2 = -1, length = values.length, offset = array.length;
while (++index2 < length) {
array[offset + index2] = values[index2];
}
return array;
}
var getPrototype = overArg(Object.getPrototypeOf, Object);
const getPrototype$1 = getPrototype;
var objectTag$2 = "[object Object]";
var funcProto = Function.prototype, objectProto$6 = Object.prototype;
var funcToString = funcProto.toString;
var hasOwnProperty$4 = objectProto$6.hasOwnProperty;
var objectCtorString = funcToString.call(Object);
function isPlainObject(value) {
if (!isObjectLike(value) || baseGetTag(value) != objectTag$2) {
return false;
}
var proto = getPrototype$1(value);
if (proto === null) {
return true;
}
var Ctor = hasOwnProperty$4.call(proto, "constructor") && proto.constructor;
return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
}
var domExcTag = "[object DOMException]", errorTag$1 = "[object Error]";
function isError(value) {
if (!isObjectLike(value)) {
return false;
}
var tag = baseGetTag(value);
return tag == errorTag$1 || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value);
}
var attempt = baseRest(function(func, args) {
try {
return apply(func, void 0, args);
} catch (e) {
return isError(e) ? e : new Error(e);
}
});
const attempt$1 = attempt;
function baseSlice(array, start, end) {
var index2 = -1, length = array.length;
if (start < 0) {
start = -start > length ? 0 : length + start;
}
end = end > length ? length : end;
if (end < 0) {
end += length;
}
length = start > end ? 0 : end - start >>> 0;
start >>>= 0;
var result = Array(length);
while (++index2 < length) {
result[index2] = array[index2 + start];
}
return result;
}
function castSlice(array, start, end) {
var length = array.length;
end = end === void 0 ? length : end;
return !start && end >= length ? array : baseSlice(array, start, end);
}
var rsAstralRange$2 = "\\ud800-\\udfff", rsComboMarksRange$3 = "\\u0300-\\u036f", reComboHalfMarksRange$3 = "\\ufe20-\\ufe2f", rsComboSymbolsRange$3 = "\\u20d0-\\u20ff", rsComboRange$3 = rsComboMarksRange$3 + reComboHalfMarksRange$3 + rsComboSymbolsRange$3, rsVarRange$2 = "\\ufe0e\\ufe0f";
var rsZWJ$2 = "\\u200d";
var reHasUnicode = RegExp("[" + rsZWJ$2 + rsAstralRange$2 + rsComboRange$3 + rsVarRange$2 + "]");
function hasUnicode(string) {
return reHasUnicode.test(string);
}
function asciiToArray(string) {
return string.split("");
}
var rsAstralRange$1 = "\\ud800-\\udfff", rsComboMarksRange$2 = "\\u0300-\\u036f", reComboHalfMarksRange$2 = "\\ufe20-\\ufe2f", rsComboSymbolsRange$2 = "\\u20d0-\\u20ff", rsComboRange$2 = rsComboMarksRange$2 + reComboHalfMarksRange$2 + rsComboSymbolsRange$2, rsVarRange$1 = "\\ufe0e\\ufe0f";
var rsAstral = "[" + rsAstralRange$1 + "]", rsCombo$2 = "[" + rsComboRange$2 + "]", rsFitz$1 = "\\ud83c[\\udffb-\\udfff]", rsModifier$1 = "(?:" + rsCombo$2 + "|" + rsFitz$1 + ")", rsNonAstral$1 = "[^" + rsAstralRange$1 + "]", rsRegional$1 = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair$1 = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsZWJ$1 = "\\u200d";
var reOptMod$1 = rsModifier$1 + "?", rsOptVar$1 = "[" + rsVarRange$1 + "]?", rsOptJoin$1 = "(?:" + rsZWJ$1 + "(?:" + [rsNonAstral$1, rsRegional$1, rsSurrPair$1].join("|") + ")" + rsOptVar$1 + reOptMod$1 + ")*", rsSeq$1 = rsOptVar$1 + reOptMod$1 + rsOptJoin$1, rsSymbol = "(?:" + [rsNonAstral$1 + rsCombo$2 + "?", rsCombo$2, rsRegional$1, rsSurrPair$1, rsAstral].join("|") + ")";
var reUnicode = RegExp(rsFitz$1 + "(?=" + rsFitz$1 + ")|" + rsSymbol + rsSeq$1, "g");
function unicodeToArray(string) {
return string.match(reUnicode) || [];
}
function stringToArray(string) {
return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
}
function createCaseFirst(methodName) {
return function(string) {
string = toString(string);
var strSymbols = hasUnicode(string) ? stringToArray(string) : void 0;
var chr = strSymbols ? strSymbols[0] : string.charAt(0);
var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1);
return chr[methodName]() + trailing;
};
}
var upperFirst = createCaseFirst("toUpperCase");
const upperFirst$1 = upperFirst;
function capitalize(string) {
return upperFirst$1(toString(string).toLowerCase());
}
function arrayReduce(array, iteratee, accumulator, initAccum) {
var index2 = -1, length = array == null ? 0 : array.length;
if (initAccum && length) {
accumulator = array[++index2];
}
while (++index2 < length) {
accumulator = iteratee(accumulator, array[index2], index2, array);
}
return accumulator;
}
function basePropertyOf(object) {
return function(key) {
return object == null ? void 0 : object[key];
};
}
var deburredLetters = {
"\xC0": "A",
"\xC1": "A",
"\xC2": "A",
"\xC3": "A",
"\xC4": "A",
"\xC5": "A",
"\xE0": "a",
"\xE1": "a",
"\xE2": "a",
"\xE3": "a",
"\xE4": "a",
"\xE5": "a",
"\xC7": "C",
"\xE7": "c",
"\xD0": "D",
"\xF0": "d",
"\xC8": "E",
"\xC9": "E",
"\xCA": "E",
"\xCB": "E",
"\xE8": "e",
"\xE9": "e",
"\xEA": "e",
"\xEB": "e",
"\xCC": "I",
"\xCD": "I",
"\xCE": "I",
"\xCF": "I",
"\xEC": "i",
"\xED": "i",
"\xEE": "i",
"\xEF": "i",
"\xD1": "N",
"\xF1": "n",
"\xD2": "O",
"\xD3": "O",
"\xD4": "O",
"\xD5": "O",
"\xD6": "O",
"\xD8": "O",
"\xF2": "o",
"\xF3": "o",
"\xF4": "o",
"\xF5": "o",
"\xF6": "o",
"\xF8": "o",
"\xD9": "U",
"\xDA": "U",
"\xDB": "U",
"\xDC": "U",
"\xF9": "u",
"\xFA": "u",
"\xFB": "u",
"\xFC": "u",
"\xDD": "Y",
"\xFD": "y",
"\xFF": "y",
"\xC6": "Ae",
"\xE6": "ae",
"\xDE": "Th",
"\xFE": "th",
"\xDF": "ss",
"\u0100": "A",
"\u0102": "A",
"\u0104": "A",
"\u0101": "a",
"\u0103": "a",
"\u0105": "a",
"\u0106": "C",
"\u0108": "C",
"\u010A": "C",
"\u010C": "C",
"\u0107": "c",
"\u0109": "c",
"\u010B": "c",
"\u010D": "c",
"\u010E": "D",
"\u0110": "D",
"\u010F": "d",
"\u0111": "d",
"\u0112": "E",
"\u0114": "E",
"\u0116": "E",
"\u0118": "E",
"\u011A": "E",
"\u0113": "e",
"\u0115": "e",
"\u0117": "e",
"\u0119": "e",
"\u011B": "e",
"\u011C": "G",
"\u011E": "G",
"\u0120": "G",
"\u0122": "G",
"\u011D": "g",
"\u011F": "g",
"\u0121": "g",
"\u0123": "g",
"\u0124": "H",
"\u0126": "H",
"\u0125": "h",
"\u0127": "h",
"\u0128": "I",
"\u012A": "I",
"\u012C": "I",
"\u012E": "I",
"\u0130": "I",
"\u0129": "i",
"\u012B": "i",
"\u012D": "i",
"\u012F": "i",
"\u0131": "i",
"\u0134": "J",
"\u0135": "j",
"\u0136": "K",
"\u0137": "k",
"\u0138": "k",
"\u0139": "L",
"\u013B": "L",
"\u013D": "L",
"\u013F": "L",
"\u0141": "L",
"\u013A": "l",
"\u013C": "l",
"\u013E": "l",
"\u0140": "l",
"\u0142": "l",
"\u0143": "N",
"\u0145": "N",
"\u0147": "N",
"\u014A": "N",
"\u0144": "n",
"\u0146": "n",
"\u0148": "n",
"\u014B": "n",
"\u014C": "O",
"\u014E": "O",
"\u0150": "O",
"\u014D": "o",
"\u014F": "o",
"\u0151": "o",
"\u0154": "R",
"\u0156": "R",
"\u0158": "R",
"\u0155": "r",
"\u0157": "r",
"\u0159": "r",
"\u015A": "S",
"\u015C": "S",
"\u015E": "S",
"\u0160": "S",
"\u015B": "s",
"\u015D": "s",
"\u015F": "s",
"\u0161": "s",
"\u0162": "T",
"\u0164": "T",
"\u0166": "T",
"\u0163": "t",
"\u0165": "t",
"\u0167": "t",
"\u0168": "U",
"\u016A": "U",
"\u016C": "U",
"\u016E": "U",
"\u0170": "U",
"\u0172": "U",
"\u0169": "u",
"\u016B": "u",
"\u016D": "u",
"\u016F": "u",
"\u0171": "u",
"\u0173": "u",
"\u0174": "W",
"\u0175": "w",
"\u0176": "Y",
"\u0177": "y",
"\u0178": "Y",
"\u0179": "Z",
"\u017B": "Z",
"\u017D": "Z",
"\u017A": "z",
"\u017C": "z",
"\u017E": "z",
"\u0132": "IJ",
"\u0133": "ij",
"\u0152": "Oe",
"\u0153": "oe",
"\u0149": "'n",
"\u017F": "s"
};
var deburrLetter = basePropertyOf(deburredLetters);
const deburrLetter$1 = deburrLetter;
var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
var rsComboMarksRange$1 = "\\u0300-\\u036f", reComboHalfMarksRange$1 = "\\ufe20-\\ufe2f", rsComboSymbolsRange$1 = "\\u20d0-\\u20ff", rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1;
var rsCombo$1 = "[" + rsComboRange$1 + "]";
var reComboMark = RegExp(rsCombo$1, "g");
function deburr(string) {
string = toString(string);
return string && string.replace(reLatin, deburrLetter$1).replace(reComboMark, "");
}
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
function asciiWords(string) {
return string.match(reAsciiWord) || [];
}
var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
function hasUnicodeWord(string) {
return reHasUnicodeWord.test(string);
}
var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
var rsApos$1 = "['\u2019]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d";
var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos$1 + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos$1 + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [rsDingbat, rsRegional, rsSurrPair].join("|") + ")" + rsSeq;
var reUnicodeWord = RegExp([
rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [rsBreak, rsUpper, "$"].join("|") + ")",
rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [rsBreak, rsUpper + rsMiscLower, "$"].join("|") + ")",
rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower,
rsUpper + "+" + rsOptContrUpper,
rsOrdUpper,
rsOrdLower,
rsDigits,
rsEmoji
].join("|"), "g");
function unicodeWords(string) {
return string.match(reUnicodeWord) || [];
}
function words(string, pattern, guard) {
string = toString(string);
pattern = guard ? void 0 : pattern;
if (pattern === void 0) {
return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
}
return string.match(pattern) || [];
}
var rsApos = "['\u2019]";
var reApos = RegExp(rsApos, "g");
function createCompounder(callback) {
return function(string) {
return arrayReduce(words(deburr(string).replace(reApos, "")), callback, "");
};
}
var camelCase = createCompounder(function(result, word, index2) {
word = word.toLowerCase();
return result + (index2 ? capitalize(word) : word);
});
const camelCase$1 = camelCase;
function stackClear() {
this.__data__ = new ListCache();
this.size = 0;
}
function stackDelete(key) {
var data = this.__data__, result = data["delete"](key);
this.size = data.size;
return result;
}
function stackGet(key) {
return this.__data__.get(key);
}
function stackHas(key) {
return this.__data__.has(key);
}
var LARGE_ARRAY_SIZE = 200;
function stackSet(key, value) {
var data = this.__data__;
if (data instanceof ListCache) {
var pairs = data.__data__;
if (!Map$1 || pairs.length < LARGE_ARRAY_SIZE - 1) {
pairs.push([key, value]);
this.size = ++data.size;
return this;
}
data = this.__data__ = new MapCache(pairs);
}
data.set(key, value);
this.size = data.size;
return this;
}
function Stack(entries) {
var data = this.__data__ = new ListCache(entries);
this.size = data.size;
}
Stack.prototype.clear = stackClear;
Stack.prototype["delete"] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;
function arrayFilter(array, predicate) {
var index2 = -1, length = array == null ? 0 : array.length, resIndex = 0, result = [];
while (++index2 < length) {
var value = array[index2];
if (predicate(value, index2, array)) {
result[resIndex++] = value;
}
}
return result;
}
function stubArray() {
return [];
}
var objectProto$5 = Object.prototype;
var propertyIsEnumerable = objectProto$5.propertyIsEnumerable;
var nativeGetSymbols = Object.getOwnPropertySymbols;
var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
if (object == null) {
return [];
}
object = Object(object);
return arrayFilter(nativeGetSymbols(object), function(symbol) {
return propertyIsEnumerable.call(object, symbol);
});
};
const getSymbols$1 = getSymbols;
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
var result = keysFunc(object);
return isArray$1(object) ? result : arrayPush(result, symbolsFunc(object));
}
function getAllKeys(object) {
return baseGetAllKeys(object, keys, getSymbols$1);
}
var DataView = getNative(root$1, "DataView");
const DataView$1 = DataView;
var Promise$1 = getNative(root$1, "Promise");
const Promise$2 = Promise$1;
var Set = getNative(root$1, "Set");
const Set$1 = Set;
var mapTag$1 = "[object Map]", objectTag$1 = "[object Object]", promiseTag = "[object Promise]", setTag$1 = "[object Set]", weakMapTag = "[object WeakMap]";
var dataViewTag$1 = "[object DataView]";
var dataViewCtorString = toSource(DataView$1), mapCtorString = toSource(Map$1), promiseCtorString = toSource(Promise$2), setCtorString = toSource(Set$1), weakMapCtorString = toSource(WeakMap$1);
var getTag = baseGetTag;
if (DataView$1 && getTag(new DataView$1(new ArrayBuffer(1))) != dataViewTag$1 || Map$1 && getTag(new Map$1()) != mapTag$1 || Promise$2 && getTag(Promise$2.resolve()) != promiseTag || Set$1 && getTag(new Set$1()) != setTag$1 || WeakMap$1 && getTag(new WeakMap$1()) != weakMapTag) {
getTag = function(value) {
var result = baseGetTag(value), Ctor = result == objectTag$1 ? value.constructor : void 0, ctorString = Ctor ? toSource(Ctor) : "";
if (ctorString) {
switch (ctorString) {
case dataViewCtorString:
return dataViewTag$1;
case mapCtorString:
return mapTag$1;
case promiseCtorString:
return promiseTag;
case setCtorString:
return setTag$1;
case weakMapCtorString:
return weakMapTag;
}
}
return result;
};
}
const getTag$1 = getTag;
var Uint8Array$1 = root$1.Uint8Array;
const Uint8Array$2 = Uint8Array$1;
var HASH_UNDEFINED = "__lodash_hash_undefined__";
function setCacheAdd(value) {
this.__data__.set(value, HASH_UNDEFINED);
return this;
}
function setCacheHas(value) {
return this.__data__.has(value);
}
function SetCache(values) {
var index2 = -1, length = values == null ? 0 : values.length;
this.__data__ = new MapCache();
while (++index2 < length) {
this.add(values[index2]);
}
}
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;
function arraySome(array, predicate) {
var index2 = -1, length = array == null ? 0 : array.length;
while (++index2 < length) {
if (predicate(array[index2], index2, array)) {
return true;
}
}
return false;
}
function cacheHas(cache, key) {
return cache.has(key);
}
var COMPARE_PARTIAL_FLAG$5 = 1, COMPARE_UNORDERED_FLAG$3 = 2;
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
var isPartial = bitmask & COMPARE_PARTIAL_FLAG$5, arrLength = array.length, othLength = other.length;
if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
return false;
}
var arrStacked = stack.get(array);
var othStacked = stack.get(other);
if (arrStacked && othStacked) {
return arrStacked == other && othStacked == array;
}
var index2 = -1, result = true, seen = bitmask & COMPARE_UNORDERED_FLAG$3 ? new SetCache() : void 0;
stack.set(array, other);
stack.set(other, array);
while (++index2 < arrLength) {
var arrValue = array[index2], othValue = other[index2];
if (customizer) {
var compared = isPartial ? customizer(othValue, arrValue, index2, other, array, stack) : customizer(arrValue, othValue, index2, array, other, stack);
}
if (compared !== void 0) {
if (compared) {
continue;
}
result = false;
break;
}
if (seen) {
if (!arraySome(other, function(othValue2, othIndex) {
if (!cacheHas(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) {
return seen.push(othIndex);
}
})) {
result = false;
break;
}
} else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
result = false;
break;
}
}
stack["delete"](array);
stack["delete"](other);
return result;
}
function mapToArray(map) {
var index2 = -1, result = Array(map.size);
map.forEach(function(value, key) {
result[++index2] = [key, value];
});
return result;
}
function setToArray(set) {
var index2 = -1, result = Array(set.size);
set.forEach(function(value) {
result[++index2] = value;
});
return result;
}
var COMPARE_PARTIAL_FLAG$4 = 1, COMPARE_UNORDERED_FLAG$2 = 2;
var boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", mapTag = "[object Map]", numberTag = "[object Number]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]";
var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]";
var symbolProto = Symbol$2 ? Symbol$2.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
switch (tag) {
case dataViewTag:
if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
return false;
}
object = object.buffer;
other = other.buffer;
case arrayBufferTag:
if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array$2(object), new Uint8Array$2(other))) {
return false;
}
return true;
case boolTag:
case dateTag:
case numberTag:
return eq(+object, +other);
case errorTag:
return object.name == other.name && object.message == other.message;
case regexpTag:
case stringTag:
return object == other + "";
case mapTag:
var convert = mapToArray;
case setTag:
var isPartial = bitmask & COMPARE_PARTIAL_FLAG$4;
convert || (convert = setToArray);
if (object.size != other.size && !isPartial) {
return false;
}
var stacked = stack.get(object);
if (stacked) {
return stacked == other;
}
bitmask |= COMPARE_UNORDERED_FLAG$2;
stack.set(object, other);
var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
stack["delete"](object);
return result;
case symbolTag:
if (symbolValueOf) {
return symbolValueOf.call(object) == symbolValueOf.call(other);
}
}
return false;
}
var COMPARE_PARTIAL_FLAG$3 = 1;
var objectProto$4 = Object.prototype;
var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
var isPartial = bitmask & COMPARE_PARTIAL_FLAG$3, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(other), othLength = othProps.length;
if (objLength != othLength && !isPartial) {
return false;
}
var index2 = objLength;
while (index2--) {
var key = objProps[index2];
if (!(isPartial ? key in other : hasOwnProperty$3.call(other, key))) {
return false;
}
}
var objStacked = stack.get(object);
var othStacked = stack.get(other);
if (objStacked && othStacked) {
return objStacked == other && othStacked == object;
}
var result = true;
stack.set(object, other);
stack.set(other, object);
var skipCtor = isPartial;
while (++index2 < objLength) {
key = objProps[index2];
var objValue = object[key], othValue = other[key];
if (customizer) {
var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
}
if (!(compared === void 0 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
result = false;
break;
}
skipCtor || (skipCtor = key == "constructor");
}
if (result && !skipCtor) {
var objCtor = object.constructor, othCtor = other.constructor;
if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) {
result = false;
}
}
stack["delete"](object);
stack["delete"](other);
return result;
}
var COMPARE_PARTIAL_FLAG$2 = 1;
var argsTag = "[object Arguments]", arrayTag = "[object Array]", objectTag = "[object Object]";
var objectProto$3 = Object.prototype;
var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
var objIsArr = isArray$1(object), othIsArr = isArray$1(other), objTag = objIsArr ? arrayTag : getTag$1(object), othTag = othIsArr ? arrayTag : getTag$1(other);
objTag = objTag == argsTag ? objectTag : objTag;
othTag = othTag == argsTag ? objectTag : othTag;
var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag;
if (isSameTag && isBuffer$1(object)) {
if (!isBuffer$1(other)) {
return false;
}
objIsArr = true;
objIsObj = false;
}
if (isSameTag && !objIsObj) {
stack || (stack = new Stack());
return objIsArr || isTypedArray$1(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
}
if (!(bitmask & COMPARE_PARTIAL_FLAG$2)) {
var objIsWrapped = objIsObj && hasOwnProperty$2.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty$2.call(other, "__wrapped__");
if (objIsWrapped || othIsWrapped) {
var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other;
stack || (stack = new Stack());
return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
}
}
if (!isSameTag) {
return false;
}
stack || (stack = new Stack());
return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
}
function baseIsEqual(value, other, bitmask, customizer, stack) {
if (value === other) {
return true;
}
if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
return value !== value && other !== other;
}
return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}
var COMPARE_PARTIAL_FLAG$1 = 1, COMPARE_UNORDERED_FLAG$1 = 2;
function baseIsMatch(object, source, matchData, customizer) {
var index2 = matchData.length, length = index2, noCustomizer = !customizer;
if (object == null) {
return !length;
}
object = Object(object);
while (index2--) {
var data = matchData[index2];
if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
return false;
}
}
while (++index2 < length) {
data = matchData[index2];
var key = data[0], objValue = object[key], srcValue = data[1];
if (noCustomizer && data[2]) {
if (objValue === void 0 && !(key in object)) {
return false;
}
} else {
var stack = new Stack();
if (customizer) {
var result = customizer(objValue, srcValue, key, object, source, stack);
}
if (!(result === void 0 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG$1 | COMPARE_UNORDERED_FLAG$1, customizer, stack) : result)) {
return false;
}
}
}
return true;
}
function isStrictComparable(value) {
return value === value && !isObject(value);
}
function getMatchData(object) {
var result = keys(object), length = result.length;
while (length--) {
var key = result[length], value = object[key];
result[length] = [key, value, isStrictComparable(value)];
}
return result;
}
function matchesStrictComparable(key, srcValue) {
return function(object) {
if (object == null) {
return false;
}
return object[key] === srcValue && (srcValue !== void 0 || key in Object(object));
};
}
function baseMatches(source) {
var matchData = getMatchData(source);
if (matchData.length == 1 && matchData[0][2]) {
return matchesStrictComparable(matchData[0][0], matchData[0][1]);
}
return function(object) {
return object === source || baseIsMatch(object, source, matchData);
};
}
function baseHasIn(object, key) {
return object != null && key in Object(object);
}
function hasPath(object, path, hasFunc) {
path = castPath(path, object);
var index2 = -1, length = path.length, result = false;
while (++index2 < length) {
var key = toKey(path[index2]);
if (!(result = object != null && hasFunc(object, key))) {
break;
}
object = object[key];
}
if (result || ++index2 != length) {
return result;
}
length = object == null ? 0 : object.length;
return !!length && isLength(length) && isIndex(key, length) && (isArray$1(object) || isArguments$1(object));
}
function hasIn(object, path) {
return object != null && hasPath(object, path, baseHasIn);
}
var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
function baseMatchesProperty(path, srcValue) {
if (isKey(path) && isStrictComparable(srcValue)) {
return matchesStrictComparable(toKey(path), srcValue);
}
return function(object) {
var objValue = get(object, path);
return objValue === void 0 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
};
}
function baseProperty(key) {
return function(object) {
return object == null ? void 0 : object[key];
};
}
function basePropertyDeep(path) {
return function(object) {
return baseGet(object, path);
};
}
function property(path) {
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}
function baseIteratee(value) {
if (typeof value == "function") {
return value;
}
if (value == null) {
return identity;
}
if (typeof value == "object") {
return isArray$1(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
}
return property(value);
}
function createBaseFor(fromRight) {
return function(object, iteratee, keysFunc) {
var index2 = -1, iterable = Object(object), props = keysFunc(object), length = props.length;
while (length--) {
var key = props[fromRight ? length : ++index2];
if (iteratee(iterable[key], key, iterable) === false) {
break;
}
}
return object;
};
}
var baseFor = createBaseFor();
const baseFor$1 = baseFor;
function baseForOwn(object, iteratee) {
return object && baseFor$1(object, iteratee, keys);
}
function createBaseEach(eachFunc, fromRight) {
return function(collection, iteratee) {
if (collection == null) {
return collection;
}
if (!isArrayLike(collection)) {
return eachFunc(collection, iteratee);
}
var length = collection.length, index2 = fromRight ? length : -1, iterable = Object(collection);
while (fromRight ? index2-- : ++index2 < length) {
if (iteratee(iterable[index2], index2, iterable) === false) {
break;
}
}
return collection;
};
}
var baseEach = createBaseEach(baseForOwn);
const baseEach$1 = baseEach;
function last(array) {
var length = array == null ? 0 : array.length;
return length ? array[length - 1] : void 0;
}
function castFunction(value) {
return typeof value == "function" ? value : identity;
}
function forEach(collection, iteratee) {
var func = isArray$1(collection) ? arrayEach : baseEach$1;
return func(collection, castFunction(iteratee));
}
var htmlEscapes = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'"
};
var escapeHtmlChar = basePropertyOf(htmlEscapes);
const escapeHtmlChar$1 = escapeHtmlChar;
var reUnescapedHtml = /[&<>"']/g, reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
function escape(string) {
string = toString(string);
return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar$1) : string;
}
function baseValues(object, props) {
return arrayMap(props, function(key) {
return object[key];
});
}
function baseInverter(object, setter, iteratee, accumulator) {
baseForOwn(object, function(value, key, object2) {
setter(accumulator, iteratee(value), key, object2);
});
return accumulator;
}
function createInverter(setter, toIteratee) {
return function(object, iteratee) {
return baseInverter(object, setter, toIteratee(iteratee), {});
};
}
var objectProto$2 = Object.prototype;
var nativeObjectToString = objectProto$2.toString;
var invert = createInverter(function(result, value, key) {
if (value != null && typeof value.toString != "function") {
value = nativeObjectToString.call(value);
}
result[value] = key;
}, constant(identity));
const invert$1 = invert;
var kebabCase = createCompounder(function(result, word, index2) {
return result + (index2 ? "-" : "") + word.toLowerCase();
});
const kebabCase$1 = kebabCase;
function mapValues(object, iteratee) {
var result = {};
iteratee = baseIteratee(iteratee);
baseForOwn(object, function(value, key, object2) {
baseAssignValue(result, key, iteratee(value, key, object2));
});
return result;
}
var objectProto$1 = Object.prototype;
var hasOwnProperty$1 = objectProto$1.hasOwnProperty;
function customDefaultsAssignIn(objValue, srcValue, key, object) {
if (objValue === void 0 || eq(objValue, objectProto$1[key]) && !hasOwnProperty$1.call(object, key)) {
return srcValue;
}
return objValue;
}
var stringEscapes = {
"\\": "\\",
"'": "'",
"\n": "n",
"\r": "r",
"\u2028": "u2028",
"\u2029": "u2029"
};
function escapeStringChar(chr) {
return "\\" + stringEscapes[chr];
}
var reInterpolate = /<%=([\s\S]+?)%>/g;
const reInterpolate$1 = reInterpolate;
var reEscape = /<%-([\s\S]+?)%>/g;
const reEscape$1 = reEscape;
var reEvaluate = /<%([\s\S]+?)%>/g;
const reEvaluate$1 = reEvaluate;
var templateSettings = {
"escape": reEscape$1,
"evaluate": reEvaluate$1,
"interpolate": reInterpolate$1,
"variable": "",
"imports": {
"_": { "escape": escape }
}
};
const templateSettings$1 = templateSettings;
var INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
var reNoMatch = /($^)/;
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
var objectProto = Object.prototype;
var hasOwnProperty = objectProto.hasOwnProperty;
function template(string, options, guard) {
var settings2 = templateSettings$1.imports._.templateSettings || templateSettings$1;
if (guard && isIterateeCall(string, options, guard)) {
options = void 0;
}
string = toString(string);
options = extendWith({}, options, settings2, customDefaultsAssignIn);
var imports = extendWith({}, options.imports, settings2.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
var isEscaping, isEvaluating, index2 = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '";
var reDelimiters = RegExp(
(options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate$1 ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$",
"g"
);
var sourceURL = hasOwnProperty.call(options, "sourceURL") ? "//# sourceURL=" + (options.sourceURL + "").replace(/\s/g, " ") + "\n" : "";
string.replace(reDelimiters, function(match2, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
interpolateValue || (interpolateValue = esTemplateValue);
source += string.slice(index2, offset).replace(reUnescapedString, escapeStringChar);
if (escapeValue) {
isEscaping = true;
source += "' +\n__e(" + escapeValue + ") +\n'";
}
if (evaluateValue) {
isEvaluating = true;
source += "';\n" + evaluateValue + ";\n__p += '";
}
if (interpolateValue) {
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
}
index2 = offset + match2.length;
return match2;
});
source += "';\n";
var variable = hasOwnProperty.call(options, "variable") && options.variable;
if (!variable) {
source = "with (obj) {\n" + source + "\n}\n";
} else if (reForbiddenIdentifierChars.test(variable)) {
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
}
source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;");
source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}";
var result = attempt$1(function() {
return Function(importsKeys, sourceURL + "return " + source).apply(void 0, importsValues);
});
result.source = source;
if (isError(result)) {
throw result;
}
return result;
}
var __spreadArray = globalThis && globalThis.__spreadArray || function(to, from, pack) {
if (pack || arguments.length === 2)
for (var i = 0, l2 = from.length, ar; i < l2; i++) {
if (ar || !(i in from)) {
if (!ar)
ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var BrowserInfo = function() {
function BrowserInfo2(name, version, os) {
this.name = name;
this.version = version;
this.os = os;
this.type = "browser";
}
return BrowserInfo2;
}();
var NodeInfo = function() {
function NodeInfo2(version) {
this.version = version;
this.type = "node";
this.name = "node";
this.os = process.platform;
}
return NodeInfo2;
}();
var SearchBotDeviceInfo = function() {
function SearchBotDeviceInfo2(name, version, os, bot) {
this.name = name;
this.version = version;
this.os = os;
this.bot = bot;
this.type = "bot-device";
}
return SearchBotDeviceInfo2;
}();
var BotInfo = function() {
function BotInfo2() {
this.type = "bot";
this.bot = true;
this.name = "bot";
this.version = null;
this.os = null;
}
return BotInfo2;
}();
var ReactNativeInfo = function() {
function ReactNativeInfo2() {
this.type = "react-native";
this.name = "react-native";
this.version = null;
this.os = null;
}
return ReactNativeInfo2;
}();
var SEARCHBOX_UA_REGEX = /alexa|bot|crawl(er|ing)|facebookexternalhit|feedburner|google web preview|nagios|postrank|pingdom|slurp|spider|yahoo!|yandex/;
var SEARCHBOT_OS_REGEX = /(nuhk|curl|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask\ Jeeves\/Teoma|ia_archiver)/;
var REQUIRED_VERSION_PARTS = 3;
var userAgentRules = [
["aol", /AOLShield\/([0-9\._]+)/],
["edge", /Edge\/([0-9\._]+)/],
["edge-ios", /EdgiOS\/([0-9\._]+)/],
["yandexbrowser", /YaBrowser\/([0-9\._]+)/],
["kakaotalk", /KAKAOTALK\s([0-9\.]+)/],
["samsung", /SamsungBrowser\/([0-9\.]+)/],
["silk", /\bSilk\/([0-9._-]+)\b/],
["miui", /MiuiBrowser\/([0-9\.]+)$/],
["beaker", /BeakerBrowser\/([0-9\.]+)/],
["edge-chromium", /EdgA?\/([0-9\.]+)/],
[
"chromium-webview",
/(?!Chrom.*OPR)wv\).*Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/
],
["chrome", /(?!Chrom.*OPR)Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/],
["phantomjs", /PhantomJS\/([0-9\.]+)(:?\s|$)/],
["crios", /CriOS\/([0-9\.]+)(:?\s|$)/],
["firefox", /Firefox\/([0-9\.]+)(?:\s|$)/],
["fxios", /FxiOS\/([0-9\.]+)/],
["opera-mini", /Opera Mini.*Version\/([0-9\.]+)/],
["opera", /Opera\/([0-9\.]+)(?:\s|$)/],
["opera", /OPR\/([0-9\.]+)(:?\s|$)/],
["pie", /^Microsoft Pocket Internet Explorer\/(\d+\.\d+)$/],
["pie", /^Mozilla\/\d\.\d+\s\(compatible;\s(?:MSP?IE|MSInternet Explorer) (\d+\.\d+);.*Windows CE.*\)$/],
["netfront", /^Mozilla\/\d\.\d+.*NetFront\/(\d.\d)/],
["ie", /Trident\/7\.0.*rv\:([0-9\.]+).*\).*Gecko$/],
["ie", /MSIE\s([0-9\.]+);.*Trident\/[4-7].0/],
["ie", /MSIE\s(7\.0)/],
["bb10", /BB10;\sTouch.*Version\/([0-9\.]+)/],
["android", /Android\s([0-9\.]+)/],
["ios", /Version\/([0-9\._]+).*Mobile.*Safari.*/],
["safari", /Version\/([0-9\._]+).*Safari/],
["facebook", /FB[AS]V\/([0-9\.]+)/],
["instagram", /Instagram\s([0-9\.]+)/],
["ios-webview", /AppleWebKit\/([0-9\.]+).*Mobile/],
["ios-webview", /AppleWebKit\/([0-9\.]+).*Gecko\)$/],
["curl", /^curl\/([0-9\.]+)$/],
["searchbot", SEARCHBOX_UA_REGEX]
];
var operatingSystemRules = [
["iOS", /iP(hone|od|ad)/],
["Android OS", /Android/],
["BlackBerry OS", /BlackBerry|BB10/],
["Windows Mobile", /IEMobile/],
["Amazon OS", /Kindle/],
["Windows 3.11", /Win16/],
["Windows 95", /(Windows 95)|(Win95)|(Windows_95)/],
["Windows 98", /(Windows 98)|(Win98)/],
["Windows 2000", /(Windows NT 5.0)|(Windows 2000)/],
["Windows XP", /(Windows NT 5.1)|(Windows XP)/],
["Windows Server 2003", /(Windows NT 5.2)/],
["Windows Vista", /(Windows NT 6.0)/],
["Windows 7", /(Windows NT 6.1)/],
["Windows 8", /(Windows NT 6.2)/],
["Windows 8.1", /(Windows NT 6.3)/],
["Windows 10", /(Windows NT 10.0)/],
["Windows ME", /Windows ME/],
["Windows CE", /Windows CE|WinCE|Microsoft Pocket Internet Explorer/],
["Open BSD", /OpenBSD/],
["Sun OS", /SunOS/],
["Chrome OS", /CrOS/],
["Linux", /(Linux)|(X11)/],
["Mac OS", /(Mac_PowerPC)|(Macintosh)/],
["QNX", /QNX/],
["BeOS", /BeOS/],
["OS/2", /OS\/2/]
];
function detect(userAgent) {
if (!!userAgent) {
return parseUserAgent(userAgent);
}
if (typeof document === "undefined" && typeof navigator !== "undefined" && navigator.product === "ReactNative") {
return new ReactNativeInfo();
}
if (typeof navigator !== "undefined") {
return parseUserAgent(navigator.userAgent);
}
return getNodeVersion();
}
function matchUserAgent(ua) {
return ua !== "" && userAgentRules.reduce(function(matched, _a2) {
var browser = _a2[0], regex = _a2[1];
if (matched) {
return matched;
}
var uaMatch = regex.exec(ua);
return !!uaMatch && [browser, uaMatch];
}, false);
}
function parseUserAgent(ua) {
var matchedRule = matchUserAgent(ua);
if (!matchedRule) {
return null;
}
var name = matchedRule[0], match2 = matchedRule[1];
if (name === "searchbot") {
return new BotInfo();
}
var versionParts = match2[1] && match2[1].split(".").join("_").split("_").slice(0, 3);
if (versionParts) {
if (versionParts.length < REQUIRED_VERSION_PARTS) {
versionParts = __spreadArray(__spreadArray([], versionParts, true), createVersionParts(REQUIRED_VERSION_PARTS - versionParts.length), true);
}
} else {
versionParts = [];
}
var version = versionParts.join(".");
var os = detectOS(ua);
var searchBotMatch = SEARCHBOT_OS_REGEX.exec(ua);
if (searchBotMatch && searchBotMatch[1]) {
return new SearchBotDeviceInfo(name, version, os, searchBotMatch[1]);
}
return new BrowserInfo(name, version, os);
}
function detectOS(ua) {
for (var ii = 0, count = operatingSystemRules.length; ii < count; ii++) {
var _a2 = operatingSystemRules[ii], os = _a2[0], regex = _a2[1];
var match2 = regex.exec(ua);
if (match2) {
return os;
}
}
return null;
}
function getNodeVersion() {
var isNode = typeof process !== "undefined" && process.version;
return isNode ? new NodeInfo(process.version.slice(1)) : null;
}
function createVersionParts(count) {
var output = [];
for (var ii = 0; ii < count; ii++) {
output.push("0");
}
return output;
}
const booleanValidator = (val) => typeof val === "boolean";
const createNumberValidator = (start, end) => (val) => typeof val === "number" && start <= val && val <= end;
const settingDefinitions = {
threadNum: {
key: "thread_num",
default: 8,
validator: createNumberValidator(1, 32),
formatter: (val) => Math.floor(val)
},
openOnNewTab: {
key: "open_on_new_tab",
default: true,
validator: booleanValidator
},
customDownloadUrl: {
key: "custom_download_url",
default: "",
validator: (val) => typeof val === "string",
formatter: (val) => val.trim()
},
compressionFileName: {
key: "cf_name",
default: "{{japanese}}.zip",
validator: (val) => typeof val === "string",
formatter: (val) => val.trim()
},
compressionLevel: {
key: "c_lv",
default: 0,
validator: createNumberValidator(0, 9),
formatter: (val) => Math.floor(val)
},
compressionStreamFiles: {
key: "c_stream_files",
default: false,
validator: booleanValidator
},
streamDownload: {
key: "stream_download",
default: false,
validator: booleanValidator
},
seriesMode: {
key: "series_mode",
default: false,
validator: booleanValidator
},
filenameLength: {
key: "filename_length",
default: 0,
validator: (val) => val === "auto" || typeof val === "number" && val >= 0,
formatter: (val) => typeof val === "number" ? Math.floor(val) : val
},
autoCancelDownloadedManga: {
key: "auto_cancel_downloaded_doujin",
default: false,
validator: booleanValidator
},
autoRetryWhenErrorOccurs: {
key: "auto_retry_when_error_occurs",
default: false,
validator: booleanValidator
},
autoShowAll: {
key: "auto_show_all",
default: false,
validator: booleanValidator
},
showIgnoreButton: {
key: "show_ignore_button",
default: false,
validator: booleanValidator
},
preventConsoleClearing: {
key: "prevent_console_clear",
default: false,
validator: booleanValidator
}
};
const browserDetect = detect();
const DISABLE_STREAM_DOWNLOAD = !!browserDetect && (browserDetect.name === "safari" || browserDetect.name === "firefox");
const readSettings = () => mapValues(
settingDefinitions,
({ key, default: defaultVal }) => h(key, defaultVal)
);
const writeableSettings = Vue.reactive(readSettings());
const settings = writeableSettings;
if (DISABLE_STREAM_DOWNLOAD && settings.streamDownload)
writeableSettings.streamDownload = false;
const startWatchSettings = functionOnce(() => {
const settingRefs = Vue.toRefs(writeableSettings);
forEach(settingRefs, (ref, key) => {
const cur = settingDefinitions[key];
Vue.watch(ref, (val) => {
if (!cur.validator(val)) {
ref.value = cur.default;
return;
}
if (cur.formatter) {
const formattedVal = cur.formatter(val);
if (ref.value !== formattedVal) {
ref.value = formattedVal;
return;
}
}
logger.log("update setting", cur.key, val);
u(cur.key, val);
});
});
});
const dlQueue = new AsyncQueue();
const zipQueue = new AsyncQueue(WORKER_THREAD_NUM);
dlQueue.canSingleStart = () => !(settings.seriesMode && zipQueue.length);
zipQueue.emitter.on("finish", () => {
if (settings.seriesMode)
dlQueue.start().catch(logger.error);
});
const _withScopeId = (n2) => (Vue.pushScopeId("data-v-5e3261cd"), n2 = n2(), Vue.popScopeId(), n2);
const _hoisted_1$2 = ["title"];
const _hoisted_2$1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ Vue.createElementVNode("i", { class: "fa fa-times" }, null, -1));
const _hoisted_3$1 = [
_hoisted_2$1
];
const _hoisted_4$1 = { class: "download-item__title" };
const _hoisted_5$1 = { class: "download-item__progress-text" };
const _sfc_main$3 = /* @__PURE__ */ Vue.defineComponent({
__name: "DownloadItem",
props: {
item: null,
index: null
},
setup(__props) {
const props = __props;
const title = Vue.computed(() => props.item.gallery.title);
const progressWidth = Vue.computed(() => {
const {
gallery: { pages: pages2 },
done,
compressing,
compressingPercent
} = props.item;
const page = pages2.length;
return compressing ? compressingPercent : page && done ? (100 * done / page).toFixed(2) : 0;
});
const canCancel = Vue.computed(() => !props.item.compressing);
const cancel = () => {
var _a2;
const { info } = props.index === 0 ? dlQueue.queue[0] : removeAt(dlQueue.queue, props.index);
(_a2 = info == null ? void 0 : info.cancel) == null ? void 0 : _a2.call(info);
};
return (_ctx, _cache) => {
return Vue.openBlock(), Vue.createElementBlock("div", {
class: Vue.normalizeClass(["download-item", {
"download-item--error": __props.item.error,
"download-item--compressing": __props.item.compressing && !__props.item.error,
"download-item--can-cancel": Vue.unref(canCancel)
}]),
title: Vue.unref(title)
}, [
Vue.unref(canCancel) ? (Vue.openBlock(), Vue.createElementBlock("div", {
key: 0,
class: "download-item__cancel",
onClick: cancel
}, _hoisted_3$1)) : Vue.createCommentVNode("", true),
Vue.createElementVNode("div", _hoisted_4$1, Vue.toDisplayString(Vue.unref(title)), 1),
Vue.createElementVNode("div", {
class: "download-item__progress",
style: Vue.normalizeStyle({ width: `${Vue.unref(progressWidth)}%` })
}, [
Vue.createElementVNode("div", _hoisted_5$1, Vue.toDisplayString(Vue.unref(progressWidth)) + "%", 1)
], 4)
], 10, _hoisted_1$2);
};
}
});
const DownloadItem_vue_vue_type_style_index_0_scoped_5e3261cd_lang = "";
const _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
target[key] = val;
}
return target;
};
const DownloadItem = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-5e3261cd"]]);
const _hoisted_1$1 = { id: "download-panel" };
const _sfc_main$2 = /* @__PURE__ */ Vue.defineComponent({
__name: "DownloadList",
props: {
zipList: null,
dlList: null
},
setup(__props) {
return (_ctx, _cache) => {
return Vue.openBlock(), Vue.createElementBlock("div", _hoisted_1$1, [
(Vue.openBlock(true), Vue.createElementBlock(Vue.Fragment, null, Vue.renderList(__props.zipList, (item, index2) => {
return Vue.openBlock(), Vue.createBlock(DownloadItem, {
key: index2,
item,
index: index2
}, null, 8, ["item", "index"]);
}), 128)),
(Vue.openBlock(true), Vue.createElementBlock(Vue.Fragment, null, Vue.renderList(__props.dlList, (item, index2) => {
return Vue.openBlock(), Vue.createBlock(DownloadItem, {
key: index2,
item,
index: index2
}, null, 8, ["item", "index"]);
}), 128))
]);
};
}
});
const DownloadList_vue_vue_type_style_index_0_scoped_658acab9_lang = "";
const DownloadList = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-658acab9"]]);
const _sfc_main$1 = /* @__PURE__ */ Vue.defineComponent({
__name: "DownloadPanel",
setup(__props) {
const { title } = document;
const zipList = Vue.computed(() => zipQueue.queue.map(({ info }) => info));
const dlList = Vue.computed(() => dlQueue.queue.map(({ info }) => info));
const infoList = Vue.computed(() => [...zipList.value, ...dlList.value]);
const error = Vue.computed(() => {
var _a2;
return !!((_a2 = dlList.value[0]) == null ? void 0 : _a2.error);
});
const titleWithStatus = Vue.computed(() => {
if (error.value)
return `[\xD7] ${title}`;
const len = infoList.value.length;
return `[${len || "\u2713"}] ${title}`;
});
Vue.watch(infoList, (val) => {
sessionStorage.setItem("downloadQueue", JSON.stringify(val.map(({ gallery: gallery2 }) => gallery2)));
});
Vue.watch(titleWithStatus, (val) => {
document.title = val;
});
return (_ctx, _cache) => {
return Vue.unref(infoList).length ? (Vue.openBlock(), Vue.createBlock(DownloadList, {
key: 0,
"zip-list": Vue.unref(zipList),
"dl-list": Vue.unref(dlList)
}, null, 8, ["zip-list", "dl-list"])) : Vue.createCommentVNode("", true);
};
}
});
/*! Element Plus Icons Vue v2.0.9 */
var export_helper_default = (sfc, props) => {
let target = sfc.__vccOpts || sfc;
for (let [key, val] of props)
target[key] = val;
return target;
};
var _sfc_main80 = {
name: "Delete"
}, _hoisted_180 = {
viewBox: "0 0 1024 1024",
xmlns: "http://www.w3.org/2000/svg"
}, _hoisted_280 = /* @__PURE__ */ Vue.createElementVNode("path", {
fill: "currentColor",
d: "M160 256H96a32 32 0 0 1 0-64h256V95.936a32 32 0 0 1 32-32h256a32 32 0 0 1 32 32V192h256a32 32 0 1 1 0 64h-64v672a32 32 0 0 1-32 32H192a32 32 0 0 1-32-32V256zm448-64v-64H416v64h192zM224 896h576V256H224v640zm192-128a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32zm192 0a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32z"
}, null, -1), _hoisted_379 = [
_hoisted_280
];
function _sfc_render80(_ctx, _cache, $props, $setup, $data, $options) {
return Vue.openBlock(), Vue.createElementBlock("svg", _hoisted_180, _hoisted_379);
}
var delete_default = /* @__PURE__ */ export_helper_default(_sfc_main80, [["render", _sfc_render80], ["__file", "delete.vue"]]);
var _sfc_main91 = {
name: "Download"
}, _hoisted_191 = {
viewBox: "0 0 1024 1024",
xmlns: "http://www.w3.org/2000/svg"
}, _hoisted_291 = /* @__PURE__ */ Vue.createElementVNode("path", {
fill: "currentColor",
d: "M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64zm384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64v450.304z"
}, null, -1), _hoisted_390 = [
_hoisted_291
];
function _sfc_render91(_ctx, _cache, $props, $setup, $data, $options) {
return Vue.openBlock(), Vue.createElementBlock("svg", _hoisted_191, _hoisted_390);
}
var download_default = /* @__PURE__ */ export_helper_default(_sfc_main91, [["render", _sfc_render91], ["__file", "download.vue"]]);
var _sfc_main275 = {
name: "Upload"
}, _hoisted_1275 = {
viewBox: "0 0 1024 1024",
xmlns: "http://www.w3.org/2000/svg"
}, _hoisted_2275 = /* @__PURE__ */ Vue.createElementVNode("path", {
fill: "currentColor",
d: "M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64zm384-578.304V704h-64V247.296L237.248 490.048 192 444.8 508.8 128l316.8 316.8-45.312 45.248L544 253.696z"
}, null, -1), _hoisted_3274 = [
_hoisted_2275
];
function _sfc_render275(_ctx, _cache, $props, $setup, $data, $options) {
return Vue.openBlock(), Vue.createElementBlock("svg", _hoisted_1275, _hoisted_3274);
}
var upload_default = /* @__PURE__ */ export_helper_default(_sfc_main275, [["render", _sfc_render275], ["__file", "upload.vue"]]);
function getSerializerPromise(localForageInstance) {
if (getSerializerPromise.result) {
return getSerializerPromise.result;
}
if (!localForageInstance || typeof localForageInstance.getSerializer !== "function") {
return Promise.reject(new Error("localforage.getSerializer() was not available! localforage v1.4+ is required!"));
}
getSerializerPromise.result = localForageInstance.getSerializer();
return getSerializerPromise.result;
}
function executeCallback(promise, callback) {
if (callback) {
promise.then(function(result) {
callback(null, result);
}, function(error) {
callback(error);
});
}
}
function forEachItem(items, keyFn, valueFn, loopFn) {
function ensurePropGetterMethod(propFn, defaultPropName) {
var propName = propFn || defaultPropName;
if ((!propFn || typeof propFn !== "function") && typeof propName === "string") {
propFn = function propFn2(item2) {
return item2[propName];
};
}
return propFn;
}
var result = [];
if (Object.prototype.toString.call(items) === "[object Array]") {
keyFn = ensurePropGetterMethod(keyFn, "key");
valueFn = ensurePropGetterMethod(valueFn, "value");
for (var i = 0, len = items.length; i < len; i++) {
var item = items[i];
result.push(loopFn(keyFn(item), valueFn(item)));
}
} else {
for (var prop in items) {
if (items.hasOwnProperty(prop)) {
result.push(loopFn(prop, items[prop]));
}
}
}
return result;
}
function setItemsIndexedDB(items, keyFn, valueFn, callback) {
var localforageInstance = this;
var promise = localforageInstance.ready().then(function() {
return new Promise(function(resolve, reject) {
var dbInfo = localforageInstance._dbInfo;
var transaction = dbInfo.db.transaction(dbInfo.storeName, "readwrite");
var store = transaction.objectStore(dbInfo.storeName);
var lastError;
transaction.oncomplete = function() {
resolve(items);
};
transaction.onabort = transaction.onerror = function(event) {
reject(lastError || event.target);
};
function requestOnError(evt) {
var request2 = evt.target || this;
lastError = request2.error || request2.transaction.error;
reject(lastError);
}
forEachItem(items, keyFn, valueFn, function(key, value) {
if (value === null) {
value = void 0;
}
var request2 = store.put(value, key);
request2.onerror = requestOnError;
});
});
});
executeCallback(promise, callback);
return promise;
}
function setItemsWebsql(items, keyFn, valueFn, callback) {
var localforageInstance = this;
var promise = new Promise(function(resolve, reject) {
localforageInstance.ready().then(function() {
return getSerializerPromise(localforageInstance);
}).then(function(serializer) {
var dbInfo = localforageInstance._dbInfo;
dbInfo.db.transaction(
function(t) {
var query = "INSERT OR REPLACE INTO " + dbInfo.storeName + " (key, value) VALUES (?, ?)";
var itemPromises = forEachItem(items, keyFn, valueFn, function(key, value) {
return new Promise(function(resolve2, reject2) {
serializer.serialize(value, function(value2, error) {
if (error) {
reject2(error);
} else {
t.executeSql(query, [key, value2], function() {
resolve2();
}, function(t2, error2) {
reject2(error2);
});
}
});
});
});
Promise.all(itemPromises).then(function() {
resolve(items);
}, reject);
},
function(sqlError) {
reject(sqlError);
}
);
}).catch(reject);
});
executeCallback(promise, callback);
return promise;
}
function setItemsGeneric(items, keyFn, valueFn, callback) {
var localforageInstance = this;
var itemPromises = forEachItem(items, keyFn, valueFn, function(key, value) {
return localforageInstance.setItem(key, value);
});
var promise = Promise.all(itemPromises);
executeCallback(promise, callback);
return promise;
}
function localforageSetItems(items, keyFn, valueFn, callback) {
var localforageInstance = this;
var currentDriver = localforageInstance.driver();
if (currentDriver === localforageInstance.INDEXEDDB) {
return setItemsIndexedDB.call(localforageInstance, items, keyFn, valueFn, callback);
} else if (currentDriver === localforageInstance.WEBSQL) {
return setItemsWebsql.call(localforageInstance, items, keyFn, valueFn, callback);
} else {
return setItemsGeneric.call(localforageInstance, items, keyFn, valueFn, callback);
}
}
function extendPrototype(localforage$$1) {
var localforagePrototype = Object.getPrototypeOf(localforage$$1);
if (localforagePrototype) {
localforagePrototype.setItems = localforageSetItems;
localforagePrototype.setItems.indexedDB = function() {
return setItemsIndexedDB.apply(this, arguments);
};
localforagePrototype.setItems.websql = function() {
return setItemsWebsql.apply(this, arguments);
};
localforagePrototype.setItems.generic = function() {
return setItemsGeneric.apply(this, arguments);
};
}
}
extendPrototype(localforage__default.default);
const dateTimeFormatter = new Intl.DateTimeFormat(void 0, {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false
});
const jszipWorkerCode = 'importScripts("https://fastly.jsdelivr.net/npm/comlink@4.3.1/dist/umd/comlink.min.js","https://fastly.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js");class DisposableJSZip{zip=new JSZip;file({name:e,data:t}){this.zip.file(e,t)}files(e){e.forEach(({name:t,data:i})=>{this.zip.file(t,i)})}async unzipFile({data:e,path:t,type:i}){return(await JSZip.loadAsync(e)).file(t)?.async(i)}async generateAsync(e,t){const i=await this.zip.generateAsync({...e,type:"uint8array"},t);return Comlink.transfer(i,[i.buffer])}generateStream(e,t,i){const s=this.zip.generateInternalStream({...e,type:"uint8array"}),r=new ReadableStream({start:n=>{s.on("error",a=>{n.error(a),i?.()}),s.on("end",()=>{setTimeout(()=>{n.close(),i?.()})}),s.on("data",(a,p)=>{n.enqueue(a),t?.(p)}),s.resume()}});return Comlink.transfer({zipStream:r},[r])}}Comlink.expose(DisposableJSZip);';
const WORKER_URL = URL.createObjectURL(new Blob([jszipWorkerCode], { type: "text/javascript" }));
const getTransferableData = (files) => files.map(({ data }) => data).filter((data) => typeof data !== "string");
class JSZipWorkerPool {
constructor() {
__publicField(this, "pool", []);
__publicField(this, "waitingQueue", []);
__publicField(this, "unzipFile", async (params) => {
const worker = await this.acquireWorker();
const zip = await new worker.JSZip();
const clean = () => {
zip[comlink.releaseProxy]();
this.releaseWorker(worker);
};
try {
return await zip.unzipFile(comlink.transfer(params, [params.data]));
} catch (error) {
clean();
throw error;
}
});
for (let id = 0; id < WORKER_THREAD_NUM; id++) {
this.pool.push({
id,
idle: true
});
}
}
createWorker() {
const worker = new Worker(WORKER_URL);
return comlink.wrap(worker);
}
waitIdleWorker() {
return new Promise((resolve) => {
this.waitingQueue.push(resolve);
});
}
async acquireWorker() {
let worker = this.pool.find(({ idle }) => idle);
if (!worker)
worker = await this.waitIdleWorker();
if (!worker.JSZip)
worker.JSZip = this.createWorker();
worker.idle = false;
return worker;
}
releaseWorker(worker) {
worker.idle = true;
if (!this.waitingQueue.length)
return;
const emit = removeAt(this.waitingQueue, 0);
emit(worker);
}
async generateAsync(files, options, onUpdate) {
const worker = await this.acquireWorker();
const zip = await new worker.JSZip();
try {
await zip.files(comlink.transfer(files, getTransferableData(files)));
return await zip.generateAsync(
options,
comlink.proxy((metaData) => {
if (metaData.currentFile)
onUpdate == null ? void 0 : onUpdate({ workerId: worker.id, ...metaData });
})
);
} finally {
zip[comlink.releaseProxy]();
this.releaseWorker(worker);
}
}
async generateStream(files, options, onUpdate) {
const worker = await this.acquireWorker();
const zip = await new worker.JSZip();
try {
await zip.files(comlink.transfer(files, getTransferableData(files)));
const { zipStream } = await zip.generateStream(
options,
comlink.proxy((metaData) => {
if (metaData.currentFile)
onUpdate == null ? void 0 : onUpdate({ workerId: worker.id, ...metaData });
})
);
return zipStream;
} finally {
zip[comlink.releaseProxy]();
this.releaseWorker(worker);
}
}
}
const jszipPool = new JSZipWorkerPool();
class JSZip {
constructor() {
__publicField(this, "files", []);
}
file(name, data) {
this.files.push({ name, data });
}
generateAsync(options, onUpdate) {
const { files } = this;
this.files = [];
return jszipPool.generateAsync(files, options, onUpdate);
}
generateStream(options, onUpdate) {
const { files } = this;
this.files = [];
return jszipPool.generateStream(files, options, onUpdate);
}
}
__publicField(JSZip, "unzipFile", (params) => jszipPool.unzipFile(params));
extendPrototype(localforage__default.default);
const dlGidStore = localforage__default.default.createInstance({
name: "nhentai_helper",
storeName: "dl_history_gid"
});
const dlGidStoreReady = dlGidStore.ready().then(() => true).catch((e) => {
logger.error(e);
return false;
});
const dlTitleStore = localforage__default.default.createInstance({
name: "nhentai_helper",
storeName: "dl_history"
});
const dlTitleStoreReady = dlTitleStore.ready().then(() => true).catch((e) => {
logger.error(e);
return false;
});
const markAsDownloaded = (gid2, title) => {
void dlGidStoreReady.then((ready) => {
if (!ready)
return;
dlGidStore.setItem(String(gid2), true).then(() => logger.log(`mark "${gid2}" as downloaded`)).catch(logger.error);
});
if (title) {
void dlTitleStoreReady.then((ready) => {
if (!ready)
return;
dlTitleStore.setItem(md5__default.default(title.replace(/\s/g, "")), true).then(() => logger.log(`mark "${title}" as downloaded`)).catch(logger.error);
});
}
};
const unmarkAsDownloaded = (gid2, title) => {
void dlGidStoreReady.then((ready) => {
if (!ready)
return;
dlGidStore.removeItem(String(gid2)).then(() => logger.log("unmark", gid2, "as downloaded")).catch(logger.error);
});
if (title) {
void dlTitleStoreReady.then((ready) => {
if (!ready)
return;
dlTitleStore.removeItem(md5__default.default(title.replace(/\s/g, ""))).then(() => logger.log("unmark", title, "as downloaded")).catch(logger.error);
});
}
};
const isDownloadedByGid = async (gid2) => {
try {
if (await dlGidStoreReady) {
return await dlGidStore.getItem(String(gid2)) === true;
}
} catch (e) {
logger.error(e);
}
return false;
};
const isDownloadedByTitle = async (title) => {
try {
if (!await dlTitleStoreReady)
return false;
const md5v2 = md5__default.default(title.replace(/\s/g, ""));
if (await dlTitleStore.getItem(md5v2) === true)
return true;
const md5v1 = md5__default.default(title);
if (await dlTitleStore.getItem(md5v1) === true) {
dlTitleStore.setItem(md5v2, true).catch(logger.error);
dlTitleStore.removeItem(md5v1).catch(logger.error);
return true;
}
} catch (e) {
logger.error(e);
}
return false;
};
const getDownloadNumber = async () => {
try {
if (!await dlGidStoreReady)
throw new Error("store cannot ready");
return await dlGidStore.length();
} catch (error) {
logger.error(error);
}
return NaN;
};
const EXPORT_HEADER_GID = "gid:";
const EXPORT_HEADER_TITLE = "title:";
const EXPORT_SEPARATOR = ",";
const EXPORT_TEXT_FILENAME = "history.txt";
const exportDownloadHistory = async () => {
try {
if (!(await dlGidStoreReady && await dlTitleStoreReady))
throw new Error("store cannot ready");
const gids = await dlGidStore.keys();
const titles = await dlTitleStore.keys();
const text = `${EXPORT_HEADER_GID}${gids.join(EXPORT_SEPARATOR)}
${EXPORT_HEADER_TITLE}${titles.join(EXPORT_SEPARATOR)}`;
const zip = new JSZip();
zip.file(EXPORT_TEXT_FILENAME, text);
const data = await zip.generateAsync({
compression: "DEFLATE",
compressionOptions: { level: 9 }
});
const timeStr = dateTimeFormatter.format(Date.now()).replace(/[^\d]/g, "");
const filename = `nhentai-helper-download-history-${timeStr}.zip`;
fileSaver.saveAs(new File([data], filename, { type: "application/zip" }));
logger.log("export download history", filename);
return true;
} catch (error) {
logger.error(error);
}
return false;
};
const importDownloadHistory = async (data) => {
try {
if (!(await dlGidStoreReady && await dlTitleStoreReady))
throw new Error("store cannot ready");
const str = await JSZip.unzipFile({ data, path: EXPORT_TEXT_FILENAME, type: "string" });
if (!str) {
logger.error("zip doesn't contain file", EXPORT_TEXT_FILENAME);
return false;
}
const lines = str.split("\n");
for (const line of lines) {
if (line.startsWith(EXPORT_HEADER_GID)) {
const gids = line.replace(EXPORT_HEADER_GID, "").split(EXPORT_SEPARATOR);
await dlGidStore.setItems(gids.map((gid2) => ({ key: gid2, value: true })));
} else if (line.startsWith(EXPORT_HEADER_TITLE)) {
const titles = line.replace(EXPORT_HEADER_TITLE, "").split(EXPORT_SEPARATOR);
await dlTitleStore.setItems(titles.map((gid2) => ({ key: gid2, value: true })));
}
}
return true;
} catch (error) {
logger.error(error);
}
return false;
};
const clearDownloadHistory = async () => {
try {
if (!(await dlGidStoreReady && await dlTitleStoreReady))
throw new Error("store cannot ready");
await dlGidStore.clear();
await dlTitleStore.clear();
return true;
} catch (error) {
logger.error(error);
}
return false;
};
const createElement = (tag, props, ...children) => {
if (typeof tag === "function")
return tag(props, ...children);
const element = document.createElement(tag);
Object.entries(props != null ? props : {}).forEach(([name, value]) => {
if (name === "html")
element.innerHTML = value;
else if (name === "class")
element.classList.add(...String(value).split(" "));
else if (name === "style" && typeof value === "object") {
const styleString = Object.entries(value).map(([k, v]) => `${camelCase$1(k)}:${String(v)}`).join(";");
element.setAttribute("style", styleString);
} else if (name.startsWith("on")) {
element.addEventListener(kebabCase$1(name.replace("on", "")), value);
} else
element.setAttribute(name, String(value));
});
children.flat().forEach((child) => {
appendChild(element, child);
});
return element;
};
const appendChild = (parent, child) => {
if (!child)
return;
parent.appendChild(typeof child === "string" ? document.createTextNode(child) : child);
};
const Fragment = (props, ...children) => {
return children;
};
const readFile = (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onabort = reject;
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
const pickFile = (accept) => new Promise((resolve) => {
const input = /* @__PURE__ */ createElement("input", {
type: "file",
accept,
onChange: () => {
var _a2;
return resolve((_a2 = input.files) == null ? void 0 : _a2[0]);
}
});
input.click();
});
const pickAndReadFile = async (accept) => {
const file = await pickFile(accept);
if (file)
return readFile(file);
};
const elementPlusJs = rawLoader("elementPlusJs");
const elementPlusCss = rawLoader("elementPlusCss");
const elementPlus = functionOnce(() => {
const win = window;
if (!win.Vue)
win.Vue = Vue__namespace;
eval(elementPlusJs);
l(elementPlusCss);
return win.ElementPlus;
});
const showMessage = (params) => elementPlus().ElMessage({ ...params, appendTo: r.document.body });
const _hoisted_1 = { class: "nhentai-helper-setting-help-buttons no-sl" };
const _hoisted_2 = /* @__PURE__ */ Vue.createTextVNode("Help");
const _hoisted_3 = /* @__PURE__ */ Vue.createTextVNode("\u8BF4\u660E");
const _hoisted_4 = ["id"];
const _hoisted_5 = { id: "nhentai-helper-setting-dialog" };
const _hoisted_6 = /* @__PURE__ */ Vue.createElementVNode("div", {
class: "asterisk-left no-sl",
style: { "margin-bottom": "18px" }
}, " means refresh is required to take effect ", -1);
const _hoisted_7 = /* @__PURE__ */ Vue.createTextVNode("Advance Settings");
const _hoisted_8 = /* @__PURE__ */ Vue.createTextVNode("Download History");
const _hoisted_9 = { class: "no-sl" };
const _hoisted_10 = /* @__PURE__ */ Vue.createTextVNode("Export");
const _hoisted_11 = /* @__PURE__ */ Vue.createTextVNode("Import");
const _hoisted_12 = /* @__PURE__ */ Vue.createTextVNode("Clear");
const _hoisted_13 = /* @__PURE__ */ Vue.createElementVNode("p", { class: "no-sl" }, "Notice: Import will not clear the existing history, but merges with it.", -1);
const _sfc_main = /* @__PURE__ */ Vue.defineComponent({
__name: "SettingsDialog",
setup(__props, { expose }) {
startWatchSettings();
const threadNumMarks = {
1: "1",
4: "4",
8: "8",
16: "16",
32: {
label: "32",
style: { whiteSpace: "nowrap" }
}
};
const compressionLevelMarks = {
0: "0",
1: "1",
9: "9"
};
const show = Vue.ref(false);
const downloadNum = Vue.ref(NaN);
const filenameLengthNumber = Vue.computed({
get: () => typeof writeableSettings.filenameLength === "number" ? writeableSettings.filenameLength : 0,
set: (val) => {
writeableSettings.filenameLength = val;
}
});
const filenameLengthAuto = Vue.computed({
get: () => writeableSettings.filenameLength === "auto",
set: (val) => {
writeableSettings.filenameLength = val ? "auto" : 0;
}
});
const refreshDownloadNum = async () => {
downloadNum.value = await getDownloadNumber();
};
const open = () => {
show.value = true;
refreshDownloadNum();
};
const openHelp = () => {
r.open(
"https://github.com/Tsuk1ko/nhentai-helper/blob/master/README.md#settings",
"_blank"
);
};
const openHelpCn = () => {
r.open(
"https://github.com/Tsuk1ko/nhentai-helper/blob/master/README-ZH.md#%E8%AE%BE%E7%BD%AE",
"_blank"
);
};
const exporting = Vue.ref(false);
const importing = Vue.ref(false);
const clearing = Vue.ref(false);
const showMessageBySucceed = (succeed) => {
showMessage({
type: succeed ? "success" : "error",
message: succeed ? "Succeed" : "Failed, please check console for error message"
});
};
const exportHistory = async () => {
exporting.value = true;
const succeed = await exportDownloadHistory();
exporting.value = false;
showMessageBySucceed(succeed);
};
const importHistory = async () => {
const data = await pickAndReadFile("application/zip");
if (!data)
return;
importing.value = true;
const succeed = await importDownloadHistory(data);
importing.value = false;
refreshDownloadNum();
showMessageBySucceed(succeed);
};
const clearHistory = async () => {
clearing.value = true;
const succeed = await clearDownloadHistory();
clearing.value = false;
refreshDownloadNum();
showMessageBySucceed(succeed);
};
expose({ open });
return (_ctx, _cache) => {
const _component_el_button = Vue.resolveComponent("el-button");
const _component_el_slider = Vue.resolveComponent("el-slider");
const _component_el_form_item = Vue.resolveComponent("el-form-item");
const _component_el_switch = Vue.resolveComponent("el-switch");
const _component_el_input = Vue.resolveComponent("el-input");
const _component_el_input_number = Vue.resolveComponent("el-input-number");
const _component_el_checkbox = Vue.resolveComponent("el-checkbox");
const _component_el_divider = Vue.resolveComponent("el-divider");
const _component_el_form = Vue.resolveComponent("el-form");
const _component_el_popconfirm = Vue.resolveComponent("el-popconfirm");
const _component_el_dialog = Vue.resolveComponent("el-dialog");
return Vue.openBlock(), Vue.createBlock(_component_el_dialog, {
modelValue: show.value,
"onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => show.value = $event),
center: true,
top: "50px"
}, {
header: Vue.withCtx(({ titleId, titleClass }) => [
Vue.createElementVNode("div", _hoisted_1, [
Vue.createVNode(_component_el_button, {
size: "small",
onClick: openHelp
}, {
default: Vue.withCtx(() => [
_hoisted_2
]),
_: 1
}),
Vue.createVNode(_component_el_button, {
size: "small",
onClick: openHelpCn
}, {
default: Vue.withCtx(() => [
_hoisted_3
]),
_: 1
})
]),
Vue.createElementVNode("span", {
id: titleId,
class: Vue.normalizeClass([titleClass, "no-sl"])
}, "Settings", 10, _hoisted_4)
]),
default: Vue.withCtx(() => [
Vue.createElementVNode("div", _hoisted_5, [
_hoisted_6,
Vue.createVNode(_component_el_form, {
"label-width": "auto",
"label-position": "left"
}, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_form_item, {
class: "m-b-32",
label: "Download thread"
}, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_slider, {
modelValue: Vue.unref(writeableSettings).threadNum,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => Vue.unref(writeableSettings).threadNum = $event),
min: 1,
max: 32,
marks: threadNumMarks
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, {
class: "refresh-required",
label: "Open on new tab"
}, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).openOnNewTab,
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => Vue.unref(writeableSettings).openOnNewTab = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Compression filename" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_input, {
modelValue: Vue.unref(writeableSettings).compressionFileName,
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => Vue.unref(writeableSettings).compressionFileName = $event),
placeholder: Vue.unref(settingDefinitions).compressionFileName.default,
onBlur: _cache[3] || (_cache[3] = ($event) => {
if (!Vue.unref(writeableSettings).compressionFileName) {
Vue.unref(writeableSettings).compressionFileName = Vue.unref(settingDefinitions).compressionFileName.default;
}
})
}, null, 8, ["modelValue", "placeholder"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, {
class: "m-b-32",
label: "Compression level"
}, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_slider, {
modelValue: Vue.unref(writeableSettings).compressionLevel,
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => Vue.unref(writeableSettings).compressionLevel = $event),
min: 0,
max: 9,
marks: compressionLevelMarks
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Filename length" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_input_number, {
modelValue: Vue.unref(filenameLengthNumber),
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => Vue.isRef(filenameLengthNumber) ? filenameLengthNumber.value = $event : null),
min: 0,
"value-on-clear": Vue.unref(settingDefinitions).filenameLength.default,
"step-strictly": true,
disabled: Vue.unref(writeableSettings).filenameLength === "auto"
}, null, 8, ["modelValue", "value-on-clear", "disabled"]),
Vue.createVNode(_component_el_checkbox, {
modelValue: Vue.unref(filenameLengthAuto),
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => Vue.isRef(filenameLengthAuto) ? filenameLengthAuto.value = $event : null),
class: "m-l-16",
label: "Auto"
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Auto cancel downloaded manga" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).autoCancelDownloadedManga,
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => Vue.unref(writeableSettings).autoCancelDownloadedManga = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Auto retry when error occurs" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).autoRetryWhenErrorOccurs,
"onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => Vue.unref(writeableSettings).autoRetryWhenErrorOccurs = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Auto show all" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).autoShowAll,
"onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => Vue.unref(writeableSettings).autoShowAll = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, {
class: "refresh-required",
label: "Show ignore button"
}, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).showIgnoreButton,
"onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => Vue.unref(writeableSettings).showIgnoreButton = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_divider, null, {
default: Vue.withCtx(() => [
_hoisted_7
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Custom download URL" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_input, {
modelValue: Vue.unref(writeableSettings).customDownloadUrl,
"onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => Vue.unref(writeableSettings).customDownloadUrl = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: 'Compression "streamFiles"' }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).compressionStreamFiles,
"onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => Vue.unref(writeableSettings).compressionStreamFiles = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Series mode" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).seriesMode,
"onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => Vue.unref(writeableSettings).seriesMode = $event)
}, null, 8, ["modelValue"])
]),
_: 1
}),
Vue.createVNode(_component_el_form_item, { label: "Stream download" }, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).streamDownload,
"onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => Vue.unref(writeableSettings).streamDownload = $event),
disabled: Vue.unref(DISABLE_STREAM_DOWNLOAD)
}, null, 8, ["modelValue", "disabled"])
]),
_: 1
}),
Vue.unref(IS_NHENTAI) ? (Vue.openBlock(), Vue.createBlock(_component_el_form_item, {
key: 0,
class: "refresh-required",
label: "Prevent console clearing"
}, {
default: Vue.withCtx(() => [
Vue.createVNode(_component_el_switch, {
modelValue: Vue.unref(writeableSettings).preventConsoleClearing,
"onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => Vue.unref(writeableSettings).preventConsoleClearing = $event)
}, null, 8, ["modelValue"])
]),
_: 1
})) : Vue.createCommentVNode("", true)
]),
_: 1
}),
Vue.createVNode(_component_el_divider, null, {
default: Vue.withCtx(() => [
_hoisted_8
]),
_: 1
}),
Vue.createElementVNode("p", _hoisted_9, " You have downloaded " + Vue.toDisplayString(downloadNum.value) + " manga on this site using nHentai Helper. ", 1),
Vue.createVNode(_component_el_button, {
type: "primary",
icon: Vue.unref(download_default),
disabled: !downloadNum.value,
loading: exporting.value,
onClick: exportHistory
}, {
default: Vue.withCtx(() => [
_hoisted_10
]),
_: 1
}, 8, ["icon", "disabled", "loading"]),
Vue.createVNode(_component_el_button, {
type: "primary",
icon: Vue.unref(upload_default),
loading: importing.value,
onClick: importHistory
}, {
default: Vue.withCtx(() => [
_hoisted_11
]),
_: 1
}, 8, ["icon", "loading"]),
Vue.createVNode(_component_el_popconfirm, {
title: "Are you sure?",
placement: "top",
onConfirm: clearHistory
}, {
reference: Vue.withCtx(() => [
Vue.createVNode(_component_el_button, {
type: "danger",
icon: Vue.unref(delete_default),
loading: clearing.value
}, {
default: Vue.withCtx(() => [
_hoisted_12
]),
_: 1
}, 8, ["icon", "loading"])
]),
_: 1
}),
_hoisted_13
])
]),
_: 1
}, 8, ["modelValue"]);
};
}
});
const SettingsDialog_vue_vue_type_style_index_0_lang = "";
const compileTemplate = (tpl) => template(tpl, { interpolate: /{{([\s\S]+?)}}/g });
const getDownloadExt = () => {
const ext = last(settings.compressionFileName.split("."));
if (ext)
return ext.toLowerCase();
return "zip";
};
const getCompressionOptions = () => {
return {
streamFiles: settings.compressionStreamFiles,
compression: settings.compressionLevel > 0 ? "DEFLATE" : "STORE",
compressionOptions: { level: settings.compressionLevel }
};
};
const getShowAllBtn = () => new Promise((resolve, reject) => {
const $btn = $__default.default("#show-all-images-button");
if ($btn.length > 0) {
resolve($btn);
return;
}
const container = document.getElementById("thumbnail-container");
if (!container) {
reject(new Error("Show all button not found"));
return;
}
new MutationObserver((mutations, self2) => {
mutations.forEach(({ addedNodes }) => {
const btnContainer = addedNodes[0];
if ((btnContainer == null ? void 0 : btnContainer.id) === "show-all-images-container") {
self2.disconnect();
resolve($__default.default("#show-all-images-button"));
}
});
}).observe(container, { childList: true });
});
const createMangaDownloadInfo = (gallery2) => ({
gallery: gallery2,
done: 0,
compressing: false,
compressingPercent: "0",
error: false
});
const notyConfirmOption = {
type: "error",
layout: "bottomRight",
theme: "nest",
timeout: false,
closeWith: []
};
const downloadAgainConfirm = async (title, hasQueue = false) => {
if (hasQueue && settings.autoCancelDownloadedManga) {
downloadedTip(title);
return false;
}
return new Promise((resolve) => {
const n2 = new Noty__default.default({
...notyConfirmOption,
text: `"${title}" is already downloaded${hasQueue ? " or in queue" : ""}.<br>Do you want to download again?`,
buttons: [
Noty__default.default.button("YES", "btn btn-noty-blue btn-noty", () => {
n2.close();
resolve(true);
}),
Noty__default.default.button("NO", "btn btn-noty-green btn-noty", () => {
n2.close();
resolve(false);
})
]
});
n2.show();
});
};
const errorRetryConfirm = (action, noCb, yesCb) => {
if (settings.autoRetryWhenErrorOccurs) {
errorRetryTip(action);
yesCb == null ? void 0 : yesCb();
return;
}
const n2 = new Noty__default.default({
...notyConfirmOption,
text: `Error occurred while ${action}, retry?`,
buttons: [
Noty__default.default.button("NO", "btn btn-noty-blue btn-noty", () => {
n2.close();
noCb == null ? void 0 : noCb();
}),
Noty__default.default.button("YES", "btn btn-noty-green btn-noty", () => {
n2.close();
yesCb == null ? void 0 : yesCb();
})
]
});
n2.show();
};
const downloadedTip = (title) => {
new Noty__default.default({
type: "info",
layout: "bottomRight",
theme: "nest",
closeWith: [],
timeout: 4e3,
text: `"${title}" is already downloaded or in queue.`
}).show();
};
const errorRetryTip = (action) => {
new Noty__default.default({
type: "warning",
layout: "bottomRight",
theme: "nest",
closeWith: [],
timeout: 3e3,
text: `Error occurred while ${action}, retrying...`
}).show();
};
class MultiThread {
constructor(tasks, taskFunc, params) {
__publicField(this, "threads", []);
__publicField(this, "taskIndex", 0);
__publicField(this, "started", false);
__publicField(this, "aborted", false);
this.tasks = tasks;
this.taskFunc = taskFunc;
this.params = params;
}
startThread(threadId) {
let abortFunc;
const threadPromise = (async () => {
while (true) {
if (this.aborted)
break;
const i = this.taskIndex++;
if (i >= this.tasks.length)
break;
const { abort, promise } = this.taskFunc(this.tasks[i], threadId, this.params);
abortFunc = abort;
await promise;
}
})();
return {
abort: () => abortFunc == null ? void 0 : abortFunc(),
promise: threadPromise
};
}
start() {
if (this.started)
throw new Error("Multi-thread started.");
this.started = true;
for (let threadId = 0; threadId < settings.threadNum; threadId++) {
this.threads.push(this.startThread(threadId));
}
return {
abort: () => {
this.aborted = true;
this.threads.forEach(({ abort }) => abort());
},
promise: Promise.all(this.threads.map(({ promise }) => promise)).then()
};
}
}
class RequestAbortError extends Error {
constructor(url) {
super(`Request abort ${url}`);
}
}
const isAbortError = (e) => e instanceof RequestAbortError;
const request = (url, responseType, retry = 3) => {
let abortFunc;
const dataPromise = new Promise((resolve, reject) => {
try {
const req = b({
method: "GET",
url,
responseType,
onerror: (e) => {
if (retry === 0) {
logger.error("Network error", url);
reject(e);
} else {
logger.warn("Network error, retry", url);
setTimeout(() => {
const { abort, dataPromise: dataPromise2 } = request(url, responseType, retry - 1);
abortFunc = abort;
resolve(dataPromise2);
}, 1e3);
}
},
onload: ({ status, response }) => {
if (status === 200)
resolve(response);
else if (retry === 0)
reject(new Error(`${status} ${url}`));
else {
logger.warn(status, url);
setTimeout(() => {
const { abort, dataPromise: dataPromise2 } = request(url, responseType, retry - 1);
abortFunc = abort;
resolve(dataPromise2);
}, 1e3);
}
}
});
abortFunc = () => {
req.abort();
logger.log("Request abort", url);
reject(new RequestAbortError(url));
};
} catch (error) {
reject(error);
}
});
return {
abort: () => abortFunc == null ? void 0 : abortFunc(),
dataPromise
};
};
const getJSON = (url) => request(url, "json").dataPromise;
const getText = (url) => request(url).dataPromise;
var NHentaiImgExt = /* @__PURE__ */ ((NHentaiImgExt2) => {
NHentaiImgExt2["j"] = "jpg";
NHentaiImgExt2["p"] = "png";
NHentaiImgExt2["g"] = "gif";
return NHentaiImgExt2;
})(NHentaiImgExt || {});
const nHentaiImgExtReversed = invert$1(NHentaiImgExt);
const getTypeFromExt = (ext) => nHentaiImgExtReversed[ext.toLowerCase()];
const getMediaDownloadUrl = IS_NHENTAI ? (mid, filename) => `https://i.nhentai.net/galleries/${mid}/${filename}` : IS_NHENTAI_TO ? (mid, filename) => `https://cdn.nload.xyz/galleries/${mid}/${filename}` : (mid, filename) => `https://cdn.nhentai.xxx/g/${mid}/${filename}`;
const getGalleryFromApi = (gid2) => {
const url = `https://nhentai.net/api/gallery/${gid2}`;
return getJSON(url);
};
const getGalleryFromWebpage = async (gid) => {
var _a2;
let doc = document;
if (!IS_PAGE_MANGA_DETAIL) {
const html = await getText(`/g/${gid}`);
const match = (_a2 = /gallery(\(\{[\s\S]+\}\));/.exec(html)) == null ? void 0 : _a2[1];
if (match) {
try {
const gallery = eval(match);
gallery.id = Number(gid);
} catch {
logger.warn("get gallery by eval failed");
}
}
const parser = new DOMParser();
doc = parser.parseFromString(html, "text/html");
}
const $doc = $__default.default(doc.body);
const english = $doc.find("#info h1").text();
const japanese = $doc.find("#info h2").text();
const pages = [];
let mediaId = "";
$doc.find("#thumbnail-container img").each((i, img) => {
var _a3;
const src = (_a3 = img.dataset.src) != null ? _a3 : img.src;
const match2 = /\/(\d+)\/(\d+)t?\.(\w+)/.exec(src);
if (!match2)
return;
const [, mid, index2, ext] = match2;
if (!mediaId)
mediaId = mid;
const t = getTypeFromExt(ext);
if (!t)
return;
pages[Number(index2) - 1] = { t };
});
if (!english && !japanese || !mediaId || !pages.length) {
throw new Error("Get gallery info error.");
}
return {
id: Number(gid),
media_id: mediaId,
title: {
english: english || japanese,
japanese: japanese || english,
pretty: english || japanese
},
images: {
pages
}
};
};
const getGallery = async (gid2) => {
const gallery2 = IS_NHENTAI ? await getGalleryFromApi(gid2) : await getGalleryFromWebpage(gid2);
logger.log("gallery", gallery2);
return gallery2;
};
const getGalleryInfo = async (gid2) => {
const {
id,
media_id,
title: { english: english2, japanese: japanese2, pretty },
images: { pages: pages2 },
num_pages
} = await (async () => {
var _a2, _b2;
if (gid2)
return getGallery(gid2);
const gidFromUrl = (_a2 = /^\/g\/(\d+)/.exec(location.pathname)) == null ? void 0 : _a2[1];
const localGallery = (_b2 = n._gallery) != null ? _b2 : n.gallery;
if (localGallery) {
if (gidFromUrl)
localGallery.id = Number(gidFromUrl);
return localGallery;
}
if (gidFromUrl)
return getGallery(gidFromUrl);
throw new Error("Cannot get gallery info.");
})();
const infoPages = (Array.isArray(pages2) ? pages2 : Object.values(pages2)).map(
(img, i) => ({ i: i + 1, t: NHentaiImgExt[img.t] })
);
const info = {
gid: id,
mid: media_id,
title: japanese2 || english2,
pages: infoPages,
cfName: compileTemplate(settings.compressionFileName)({
english: english2,
japanese: japanese2 || english2,
pretty,
id,
pages: num_pages
})
};
logger.log("info", info);
return info;
};
const downloadGalleryByInfo = async (info, { progressDisplayController, rangeCheckers } = {}) => {
info.done = 0;
let { mid, pages: pages2, cfName } = info.gallery;
if (rangeCheckers == null ? void 0 : rangeCheckers.length) {
pages2 = pages2.filter(({ i }) => rangeCheckers.some((check) => check(i)));
}
let aborted = false;
info.cancel = () => {
aborted = true;
progressDisplayController == null ? void 0 : progressDisplayController.reset();
};
progressDisplayController == null ? void 0 : progressDisplayController.bindInfo(info);
progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
const zip = await new JSZip();
const downloadTask = (page, threadID, { filenameLength, customDownloadUrl }) => {
if (info.error)
return { abort: () => {
}, promise: Promise.resolve() };
const url = customDownloadUrl ? compileTemplate(customDownloadUrl)({ mid, index: page.i, ext: page.t }) : getMediaDownloadUrl(mid, `${page.i}.${page.t}`);
logger.log(`[${threadID}] ${url}`);
const { abort: abort2, dataPromise } = request(url, "arraybuffer");
return {
abort: () => {
logger.log(`[${threadID}] abort`);
abort2();
},
promise: dataPromise.then(async (data) => {
if (data) {
zip.file(`${String(page.i).padStart(filenameLength || 0, "0")}.${page.t}`, data);
}
info.done++;
progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
}).catch((e) => {
if (isAbortError(e))
return;
info.error = true;
throw e;
})
};
};
const multiThread = new MultiThread(pages2, downloadTask, {
filenameLength: settings.filenameLength === "auto" ? Math.ceil(Math.log10(Math.max(...pages2.map(({ i }) => Number(i))))) : settings.filenameLength,
customDownloadUrl: settings.customDownloadUrl
});
const { abort, promise } = multiThread.start();
info.cancel = () => {
aborted = true;
abort();
progressDisplayController == null ? void 0 : progressDisplayController.reset();
};
if (!aborted)
await promise;
if (aborted)
return;
return async () => {
info.compressing = true;
progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
logger.log("start compressing", cfName);
let lastZipFile = "";
const onCompressionUpdate = ({ workerId, percent, currentFile }) => {
if (lastZipFile !== currentFile && currentFile) {
lastZipFile = currentFile;
logger.log(`[${workerId}] compressing ${percent.toFixed(2)}%`, currentFile);
}
info.compressingPercent = percent.toFixed(2);
progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
};
if (settings.streamDownload) {
logger.log("stream mode on");
const fileStream = streamsaver.createWriteStream(cfName);
const zipStream = await zip.generateStream(getCompressionOptions(), onCompressionUpdate);
await zipStream.pipeTo(fileStream);
} else {
const data = await zip.generateAsync(getCompressionOptions(), onCompressionUpdate);
fileSaver.saveAs(new File([data], cfName, { type: "application/zip" }));
}
logger.log("completed", cfName);
progressDisplayController == null ? void 0 : progressDisplayController.complete();
progressDisplayController == null ? void 0 : progressDisplayController.unbindInfo();
};
};
const addDownloadGalleryTask = (gallery2, { progressDisplayController, markGalleryDownloaded } = {}) => {
const info = Vue.reactive(createMangaDownloadInfo(gallery2));
info.cancel = () => {
progressDisplayController == null ? void 0 : progressDisplayController.reset();
};
dlQueue.push(async () => {
const zipFunc = await downloadGalleryByInfo(info, { progressDisplayController }).catch((e) => {
progressDisplayController == null ? void 0 : progressDisplayController.error();
errorRetryConfirm(
"downloading",
() => {
dlQueue.skipFromError().catch(logger.error);
},
() => {
info.error = false;
dlQueue.restartFromError().catch(logger.error);
}
);
throw e;
});
if (zipFunc) {
zipQueue.push(async () => {
try {
await zipFunc();
markAsDownloaded(gallery2.gid, gallery2.title);
markGalleryDownloaded == null ? void 0 : markGalleryDownloaded();
} catch (error) {
if (!error)
logger.warn("user abort stream download");
logger.error(error);
progressDisplayController == null ? void 0 : progressDisplayController.error();
}
}, info);
zipQueue.start().catch(logger.error);
}
}, info);
dlQueue.start().catch(logger.error);
};
class ProgressDisplayController {
constructor(enableHeadTxt = false, docTitle) {
__publicField(this, "downloadBtn");
__publicField(this, "btnTxt");
__publicField(this, "info");
this.enableHeadTxt = enableHeadTxt;
this.docTitle = docTitle;
this.btnTxt = /* @__PURE__ */ createElement("span", {
class: "download-zip-txt"
}, this.defaultBtnText());
this.downloadBtn = /* @__PURE__ */ createElement("button", {
class: "btn btn-secondary nhentai-helper-btn download-zip-btn"
}, /* @__PURE__ */ createElement("i", {
class: "fa fa-download"
}), " ", this.btnTxt);
}
get compressingHeadText() {
return this.enableHeadTxt ? `Compressing ${getDownloadExt()} ` : "";
}
get downloadingHeadText() {
return this.enableHeadTxt ? `Downloading ${getDownloadExt()} ` : "";
}
defaultBtnText(suffix) {
if (!this.enableHeadTxt)
return suffix != null ? suffix : "";
return `Download ${getDownloadExt()}${suffix ? ` ${suffix}` : ""}`;
}
bindInfo(info) {
this.info = info;
}
unbindInfo() {
this.info = void 0;
}
lockBtn(text) {
this.downloadBtn.setAttribute("disabled", "disabled");
if (text)
this.btnTxt.innerText = text;
}
releaseBtn() {
this.downloadBtn.removeAttribute("disabled");
}
complete() {
this.setDocTitle("\u2713");
this.btnTxt.innerText = this.defaultBtnText("\u2713");
this.releaseBtn();
}
reset() {
this.setDocTitle();
this.btnTxt.innerText = this.defaultBtnText();
this.releaseBtn();
}
error() {
this.releaseBtn();
this.btnTxt.innerText = "Error";
this.setDocTitle("\xD7");
}
updateProgress() {
if (!this.info)
return;
const { done, compressing, compressingPercent } = this.info;
if (compressing) {
this.setDocTitle(`${compressingPercent}%`);
this.btnTxt.innerText = `${this.compressingHeadText}${compressingPercent}%`;
} else {
const total = this.info.gallery.pages.length;
this.setDocTitle(`${done}/${total}`);
this.btnTxt.innerText = `${this.downloadingHeadText}${done}/${total}`;
}
}
setDocTitle(prefix) {
if (!this.docTitle)
return;
document.title = prefix ? `[${prefix}] ${this.docTitle}` : this.docTitle;
}
}
class IgnoreController {
constructor(text = true, status = false) {
__publicField(this, "ignoreBtn");
__publicField(this, "icon");
__publicField(this, "text");
this.status = status;
this.icon = /* @__PURE__ */ createElement("i", {
class: this.iconClass
});
if (text)
this.text = /* @__PURE__ */ createElement("span", null, this.btnText);
this.ignoreBtn = /* @__PURE__ */ createElement("button", {
class: "btn btn-secondary nhentai-helper-btn ignore-btn"
}, this.icon, " ", this.text);
}
setStatus(status) {
this.status = status;
this.updateBtn();
}
getStatus() {
return this.status;
}
get iconClass() {
return this.status ? "fa fa-eye-slash" : "fa fa-eye";
}
get btnText() {
return this.status ? "Unignore this" : "Ignore this";
}
updateBtn() {
this.icon.className = this.iconClass;
if (this.text)
this.text.innerText = this.btnText;
}
}
const initDetailPage = async () => {
const progressDisplayController = new ProgressDisplayController(true, document.title);
const { downloadBtn } = progressDisplayController;
const pagesInput = /* @__PURE__ */ createElement("input", {
class: "pages-input",
placeholder: "Download pages (e.g. 1-10,12,14,18-)"
});
$__default.default("#info > .buttons").append(downloadBtn).after(pagesInput);
const gallery2 = await getGalleryInfo();
let ignoreController;
if (settings.showIgnoreButton) {
const isDownloaded = await isDownloadedByGid(gallery2.gid);
ignoreController = new IgnoreController(true, isDownloaded);
const { ignoreBtn } = ignoreController;
ignoreBtn.addEventListener("click", () => {
const ignore = ignoreController.getStatus();
if (ignore)
unmarkAsDownloaded(gallery2.gid, gallery2.title);
else
markAsDownloaded(gallery2.gid, gallery2.title);
ignoreController.setStatus(!ignore);
});
$__default.default("#info > .buttons").append(ignoreBtn);
}
downloadBtn.addEventListener("click", async () => {
var _a2;
const rangeCheckers = pagesInput.value.split(",").filter((range) => !Number.isNaN(parseInt(range))).map((range) => {
const [start, end] = range.split("-").map((num) => parseInt(num));
if (typeof end === "undefined")
return (page) => page === start;
else if (Number.isNaN(end))
return (page) => page >= start;
else
return (page) => start <= page && page <= end;
});
progressDisplayController.lockBtn();
try {
const downloaded = await isDownloadedByGid(gallery2.gid) || await isDownloadedByTitle(gallery2.title);
if (downloaded && !await downloadAgainConfirm(gallery2.title)) {
progressDisplayController.reset();
markAsDownloaded(gallery2.gid, gallery2.title);
ignoreController == null ? void 0 : ignoreController.setStatus(true);
return;
}
await ((_a2 = await downloadGalleryByInfo(createMangaDownloadInfo(gallery2), {
progressDisplayController,
rangeCheckers
})) == null ? void 0 : _a2());
markAsDownloaded(gallery2.gid, gallery2.title);
ignoreController == null ? void 0 : ignoreController.setStatus(true);
} catch (error) {
progressDisplayController.error();
logger.error(error);
}
});
applyAutoShowAll();
};
const applyAutoShowAll = () => {
if (settings.autoShowAll) {
getShowAllBtn().then(($btn) => $btn.trigger("click")).catch(logger.error);
}
};
const createLangFilter = () => {
const langFilter = /* @__PURE__ */ createElement("select", {
id: "lang-filter",
onChange: () => {
filterLang(langFilter.value);
sessionStorage.setItem("lang-filter", langFilter.value);
}
}, IS_NHENTAI_TO ? /* @__PURE__ */ createElement(Fragment, null, /* @__PURE__ */ createElement("option", {
value: "0"
}, "None"), /* @__PURE__ */ createElement("option", {
value: "10197"
}, "Chinese"), /* @__PURE__ */ createElement("option", {
value: "2"
}, "Japanese"), /* @__PURE__ */ createElement("option", {
value: "19"
}, "English")) : /* @__PURE__ */ createElement(Fragment, null, /* @__PURE__ */ createElement("option", {
value: "0"
}, "None"), /* @__PURE__ */ createElement("option", {
value: "29963"
}, "Chinese"), /* @__PURE__ */ createElement("option", {
value: "6346"
}, "Japanese"), /* @__PURE__ */ createElement("option", {
value: "12227"
}, "English")));
$__default.default("ul.menu.left").append(
/* @__PURE__ */ createElement("li", {
style: { padding: "0 10px", userSelect: "none" }
}, "Filter: ", langFilter)
);
return langFilter;
};
const filterLang = (lang, $node) => {
const getNode = $node ? (selector) => $node.find(selector) : (selector) => $__default.default(selector);
if (lang === "0")
getNode(".gallery").removeClass("hidden");
else {
getNode(`.gallery[data-tags~=${lang}]`).removeClass("hidden");
getNode(`.gallery:not([data-tags~=${lang}])`).addClass("hidden");
}
};
const initListPage = () => {
$__default.default(".gallery").each(initGallery);
const langFilter = initLangFilter();
initShortcut();
restoreDownloadQueue();
const contentEl = $__default.default("#content")[0];
if (contentEl) {
new MutationObserver((mutations) => {
mutations.forEach(({ addedNodes }) => {
addedNodes.forEach((node) => {
const $el = $__default.default(node);
$el.find(".gallery").each(initGallery);
const lang = langFilter.value;
if (lang)
filterLang(lang, $el);
});
});
}).observe(contentEl, { childList: true });
}
};
const initLangFilter = () => {
const langFilter = createLangFilter();
const storedLangFilterVal = sessionStorage.getItem("lang-filter");
if (storedLangFilterVal) {
langFilter.value = storedLangFilterVal;
filterLang(storedLangFilterVal);
}
return langFilter;
};
const initShortcut = () => {
$__default.default(document).on("keydown", (event) => {
switch (event.key) {
case "ArrowLeft":
$__default.default(".pagination .previous").trigger("click");
break;
case "ArrowRight":
$__default.default(".pagination .next").trigger("click");
break;
}
});
};
const restoreDownloadQueue = () => {
const galleriesJson = sessionStorage.getItem("downloadQueue");
if (!galleriesJson)
return;
try {
const galleries = JSON.parse(galleriesJson);
for (const gallery2 of galleries) {
addDownloadGalleryTask(gallery2);
}
} catch (error) {
logger.error(error);
}
};
const initGallery = function() {
var _a2;
const $gallery = $__default.default(this);
if ($gallery.attr("init"))
return;
$gallery.attr("init", "true");
const $a = $gallery.find("a.cover");
if (settings.openOnNewTab)
$a.attr("target", "_blank");
const gid2 = (_a2 = /\/g\/([0-9]+)/.exec($a.attr("href"))) == null ? void 0 : _a2[1];
if (!gid2)
return;
const progressDisplayController = new ProgressDisplayController();
const { downloadBtn } = progressDisplayController;
$gallery.append(downloadBtn);
let ignoreController;
let galleryTitle;
const markGalleryDownloaded = () => {
$gallery.addClass("downloaded");
ignoreController == null ? void 0 : ignoreController.setStatus(true);
};
const unmarkGalleryDownloaded = () => {
$gallery.removeClass("downloaded");
ignoreController == null ? void 0 : ignoreController.setStatus(false);
};
void isDownloadedByGid(gid2).then((downloaded) => {
if (downloaded)
markGalleryDownloaded();
if (settings.showIgnoreButton) {
ignoreController = new IgnoreController(false, downloaded);
const { ignoreBtn } = ignoreController;
ignoreBtn.addEventListener("click", () => {
const ignore = ignoreController.getStatus();
if (ignore) {
unmarkGalleryDownloaded();
unmarkAsDownloaded(gid2, galleryTitle);
} else {
markGalleryDownloaded();
markAsDownloaded(gid2, galleryTitle);
}
});
$gallery.append(ignoreBtn);
}
});
let gallery2;
let skipDownloadedCheck = false;
const startDownload = async () => {
if (!settings.autoCancelDownloadedManga) {
progressDisplayController.lockBtn("Wait");
}
if (!skipDownloadedCheck && await isDownloadedByGid(gid2)) {
const title = $gallery.find(".caption").text();
if (!await downloadAgainConfirm(title, true)) {
progressDisplayController.reset();
markGalleryDownloaded();
return;
}
skipDownloadedCheck = true;
}
if (settings.autoCancelDownloadedManga) {
progressDisplayController.lockBtn("Wait");
}
if (!gallery2) {
try {
gallery2 = await getGalleryInfo(gid2);
galleryTitle = gallery2.title;
} catch (error) {
logger.error(error);
progressDisplayController.error();
errorRetryConfirm("getting information", void 0, startDownload);
return;
}
}
if (!skipDownloadedCheck && (await isDownloadedByTitle(gallery2.title) || dlQueue.queue.some(
({
info: {
gallery: { title }
}
}) => title === gallery2.title
)) && !await downloadAgainConfirm(gallery2.title, true)) {
progressDisplayController.reset();
markAsDownloaded(gid2, gallery2.title);
markGalleryDownloaded();
return;
}
addDownloadGalleryTask(gallery2, { progressDisplayController, markGalleryDownloaded });
};
downloadBtn.addEventListener("click", startDownload);
};
class StyleInjector {
constructor(style) {
__publicField(this, "styleNode");
this.styleNode = /* @__PURE__ */ createElement("style", null, style);
}
inject() {
document.head.append(this.styleNode);
}
remove() {
this.styleNode.remove();
}
}
const initOnlineViewPage = () => {
if (!IS_NHENTAI)
initViewMode();
};
const initViewMode = () => {
const style = new StyleInjector(
"#image-container img{width:auto;max-width:calc(100vw - 20px);max-height:100vh}"
);
const viewModeText = ["[off]", "[on]"];
let viewMode = h("online_view_mode", 0);
applyOnlineViewStyle(!!viewMode, style);
const btnText = /* @__PURE__ */ createElement("span", null, viewModeText[viewMode]);
const btn = /* @__PURE__ */ createElement("button", {
id: "online-view-mode-btn",
class: "btn btn-secondary"
}, "100% view height ", btnText);
btn.addEventListener("click", () => {
viewMode = 1 - viewMode;
u("online_view_mode", viewMode);
btnText.innerText = viewModeText[viewMode];
applyOnlineViewStyle(!!viewMode, style);
});
$__default.default("#page-container").prepend(btn);
};
const applyOnlineViewStyle = (enable, style) => {
if (enable)
style.inject();
else
style.remove();
};
const initPage = () => {
if (IS_PAGE_MANGA_LIST) {
initListPage();
applyPjax();
} else if (IS_PAGE_MANGA_DETAIL)
initDetailPage().catch(logger.error);
else if (IS_PAGE_ONLINE_VIEW)
initOnlineViewPage();
};
const applyPjax = () => {
$__default.default(document).pjax(".pagination a, .sort a", {
container: "#content",
fragment: "#content",
timeout: 1e4
});
$__default.default(document).on("pjax:end", () => {
$__default.default(".pagination a").each(function() {
const $this = $__default.default(this);
const href = $this.attr("href");
const isPathname = href.startsWith("/");
const url = isPathname ? new URL(href, location.origin) : new URL(href);
url.searchParams.delete("_pjax");
$this.attr("href", isPathname ? `${url.pathname}${url.search}` : url.href);
});
applyLazyLoad();
});
};
const applyLazyLoad = () => {
const { _n_app } = n;
if (_n_app) {
_n_app.install_lazy_loader();
_n_app.install_blacklisting();
}
};
const createAppAndMount = (component, appInitFunc) => {
const el = document.createElement("div");
document.body.append(el);
const app = Vue.createApp(component);
appInitFunc == null ? void 0 : appInitFunc(app);
return app.mount(el);
};
const initSettingsDialogApp = functionOnce(
() => createAppAndMount(_sfc_main, (app) => {
app.use(elementPlus());
})
);
const openSettingsDialog = () => {
const dialog = initSettingsDialogApp();
dialog.open();
};
createAppAndMount(_sfc_main$1);
initPage();
m("Settings", openSettingsDialog);
})($, null, Vue, EventEmitter3, saveAs, localforage, MD5, Comlink, Noty, streamSaver);