Dit script moet niet direct worden geïnstalleerd - het is een bibliotheek voor andere scripts om op te nemen met de meta-richtlijn // @require https://update.greasyfork.org/scripts/452362/1281581/Baidu%20Translate.js
/* eslint-disable no-multi-spaces */
/* eslint-disable no-return-assign */
/* eslint-disable curly */
/* eslint-disable no-sequences */
// ==UserScript==
// @name Baidu Translate
// @name:zh-CN 百度翻译
// @name:en Baidu Translate
// @namespace PY-DNG APIS
// @version 0.2.7
// @description Baidu translate api support for userscripts. No need for baidu's token.
// @description:zh-CN 用户脚本版的百度翻译API支持,无需申请token,@require即用
// @description:en Baidu translate api support for userscripts. No need for baidu's token.
// @author PY-DNG
// @license MIT
// @icon data:image/vnd.microsoft.icon;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPzbt074plC+9Y0e9PWIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1jR70+KZQvvzbuEwAAAAAAAAAAAAAAAD6wYWE9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//rBhYQAAAAA/Nu4TPWIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//zbuEz4plC+9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/+KZQvvaOIPL1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1jh/y9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/2kyr//vDh//vRpP/3okf/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//aRJv////////////7w4f/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/3oET//u/g//7v4P/2lCz/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9o8i/////////////vDh//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//ekS/////////////aWMP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/2jyL////////////96tb/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/96RL////////////9pYw//WIFP/1iBT/96NJ//ecO//2mDP/9pIn//WNHv////////////3q1v/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/3pEv////////////2ljD/9YgU//m5df////////////////////////////////////////v3//3n0P/948j//N/A//zdvf/817H//Nex//ixZP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//ekS/////////////aWMP/1iBT/9o8i//aYM//3n0L/96BD//elTf/4qFT////////////+8ub/+bt4//rAhP/7zJr//Ny5//3r2P/94sb/9Y0d//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/96RL////////////9pYw//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP////////////3s2f/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/3pEv////////////2ljD/9YgU//WIFP/2kCX/+saO//m9ff/5tWz/+Kxc/////////////vLl//aOIP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//ekS/////////////aWMP/1iBT/9YgU//rGjv/+7+D//vfu//748P////////////////////////////////////////////rHkP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/96RL////////////9pYw//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFf////////////727f/3okf/+KtZ//mzav/5tGv/9YgV//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/3pEv////////////2ljD/9po3//rGjv/4qlb/9Y4f//WIFP/1iBT/9YgU/////////////vjx//WIFP/1iBT/9pg0//m3cP/6x5D/9Y0d//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//ekS/////////////aWMP/1iBT/+KdS//3kyv///Pn//N6+//m1bf/2jyP//eXM//rEiv/2mjf/+bl0//3o0v/////////////////82rb/9Y0d//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/817H//Nex//zXsf/817H//OHD////////////9pYw//WIFP/1iBT/9YgU//irWv/969j///////758//6xYz/+bJn//7x5P/////////////////////////////////+7dz/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU///////////////////////////////////////2ljD/9YgU//WIFP/1iBT/9YgU//WKGP/5vHv///r1////////////////////////+fT//N28//rCh//4rFz/9po3//WLGv/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9pgz//aYM//2mDP/9pgz//aYM//2mDP/9pgz//WKGP/1iBT/9YgU//WIFP/1iBT/9YgU//WJF//83r7//////////////////eLF//WMHP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/+8uY///////+7t7//efP////////////+9Km//WJF//1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//irWv//////+9Wr//aOIP/2jiD//eXM////////////+86e//WIFf/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//rDiP/+9+///vfv//m2bv/1iBT/9YgU//WIFP/1jh///vLm//rJlf/1iBX/9YgU//WIFP/2kyn//vPn////////////+sWN//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/+seQ////////////+bl1//WIFP/2kCX//vLm//758////fv//efQ//zhxP/82bP/+9Gk//rJlP/82bT///////////////7//eLF//aXMv/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/6x5D////////////5uXX/9YgU//aYM//4sGL/+LBj//m4cv/5vHr/+sOJ//vLmP/70qb//Nm0//zfwP/+9Or////////////6xo//9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WMHP/2kCT/9pAk//WLGv/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WNHv/837//+r+B//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/2jiDy9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9o4g8vimUL71iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/4plC+/Ny5TPWIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//zbuEwAAAAA+sGFhPWIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/6wYWEAAAAAAAAAAAAAAAA/Nu4TPimUL71jh/y9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WIFP/1iBT/9YgU//WOH/L4plC+/Ny5TAAAAAAAAAAA4AAAB4AAAAGAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAeAAAAc=
// @grant GM_xmlhttpRequest
// @connect fanyi.baidu.com
// ==/UserScript==
/* Usage:
** baidu_translate(details): details = {
text: <string> Text you want to translate.
Required argument, no default value.
callback: <function> Callback function when translation succeed,
e.g. function(result) {console.log(result);}.
Argument `result` will be <string> translate result.
Required argument, no default value.
[src]: <string> Source language; e.g. 'zh' for Chinese, 'en' for English, 'ja' for Japanese, ....
Default: Auto detect.
[dst]: <string> Destination language,
Default: 'zh'.
[split]: <number> Text spliting max length, just leave blank if you don't know what this means.
What it is: Baidu has limited that up to 5000 letters can be translated each single API
request, so the translate function will split text by about every ${split} letters, and
translates each of them with a single API request then concatenate the translate result
together again. Don't worry if any sentence to be splited, actually the translate
function splits text with '\n' first, then concatenate the '\n'-splited strings as long
as possible while keeping its length <= ${split}.
Default: 5000
[onerror]: <function> Callback function when translation failed,
e.g. function(reason) {console.log(reason);}.
Argument: `reason` may be anything that causes its failure, just for debugging and do
not use it in production.
Default: function() {}.
[retry]: <number> Times to retry before onerror function being called or an error being thrown,
Default: 3.
}
** Or:
** baidu_translate(text, src, dst, callback, onerror, split, retry)
**
** Overloads:
** baidu_translate(text, src, dst, callback, onerror, split)
** baidu_translate(text, dst, callback, onerror, split)
** baidu_translate(text, callback, onerror, split)
** baidu_translate(text, callback, onerror)
** baidu_translate(text, callback)
*/
let baidu_translate, bdTransReady;
[baidu_translate, bdTransReady] = (function() {
const BDT = new BaiduTranslateAPI();
return [baidu_translate, bdTransReady];
function baidu_translate() {
// Check BDT ready
if (!BDT.gtk || !BDT.token) {
//throw new Error('BaiduTranslateAPI not ready');
return false;
}
// Get argument
const [text, src, dst, callback, onerror, split, retry] = parseArgs([...arguments], [
function(args, defaultValues) {
const details = args[0];
const parsed = [...defaultValues];
details.hasOwnProperty('text') && (parsed[0] = details.text);
details.hasOwnProperty('src') && (parsed[1] = details.src);
details.hasOwnProperty('dst') && (parsed[2] = details.dst);
details.hasOwnProperty('callback') && (parsed[3] = details.callback);
details.hasOwnProperty('onerror') && (parsed[4] = details.onerror);
details.hasOwnProperty('split') && (parsed[5] = details.split);
details.hasOwnProperty('retry') && (parsed[6] = details.retry);
return parsed;
},
[1,4],
[1,4,5],
[1,4,5,6],
[1,3,4,5,6],
[1,2,3,4,5,6],
[1,2,3,4,5,6,7]
], ['', undefined, undefined, function() {}, function() {}, 5000, 3]);
// Split lines
const textarr = text.replaceAll('\r\n', '\n').replaceAll('\n\r', '\n').replaceAll('\r', '\n').split('\n');
if (textarr.some((t) => (t.length > split))) {
throw new Error('Some paragraph is longer than given split length (' + split + ')');
}
// Prepare
const AM = new AsyncManager();
const result = [];
AM.onfinish = function() {
callback(result.map(re => '\n'.repeat(re.newline_begin) + re.dst + '\n'.repeat(re.newline_end)).join('\n'));
}
// Send requests
let index = 0;
while (textarr.length > 0) {
// Join translate api paragraph
let para = '';
while (textarr.length > 0 && para.length + textarr[0].length < split) {
para += '\n' + textarr.shift();
}
para = para.substr(1);
// Whether this paragraph contains \n at beginning
const countNewLine = str => str.split('').filter(t => t === '\n').length;
const newline_begin = countNewLine(para.match(/^\s*/) ? para.match(/^\s*/)[0] : '');
const newline_end = countNewLine(para.match(/^\s*/) ? para.match(/\s*$/)[0] : '');
result[index] = {src: para, dst: null, newline_begin, newline_end};
// API request
AM.add();
BDT.translate({
text: para,
args: [index],
src: src,
dst: dst,
onerror: onerror,
retry: retry,
callback: function(json, i) {
const temp_result = json.trans_result.data.reduce(function(pre, cur) {
return (pre.push('\n'.repeat(cur.prefixWrap) + cur.dst), pre);
}, []).join('\n');
result[i].dst = temp_result;
AM.finish();
}
});
index++;
}
AM.finishEvent = true;
return true;
}
function bdTransReady(callback) {
bdTransReady.callbacks = bdTransReady.callbacks || [];
bdTransReady.callbacks.push(callback);
BDT.oninit = dispatchCallback;
function dispatchCallback() {
bdTransReady.callbacks.forEach(cb => cb());
bdTransReady.callbacks.splice(0, Infinity);
}
}
function BaiduTranslateAPI() {
const BT = this;
BT.gtk = BT.token = null;
BT.inited = false;
let oninit=function() {};
Object.defineProperty(BT, 'oninit', {
enumerable: true,
set: (f) => (typeof f === 'function' && (oninit = f) && BT.inited && oninit()),
get: () => (oninit)
});
init();
BT.calcSign = calcSign;
BT.translate = translate;
async function translate(details) {
const callback = details.callback;
const text = details.text;
const src = details.src || await langDetect(text);
const dst = details.dst || 'zh';
const onerror = details.onerror || function() {};
const retry = details.retry || 0;
const args = details.args || [];
GM_xmlhttpRequest({
method: 'POST',
url: 'https://fanyi.baidu.com/v2transapi',
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded'
},
data: toQueryString({
'from': src,
'to': dst,
'query': text,
'simple_means_flag': 3,
'sign': calcSign(text),
'token': BT.token
}),
onload: function(response) {
response.status !== 200 && Err(response);
const json = JSON.parse(response.responseText);
json.error && Err(json);
callback.apply(null, [json].concat(args));
function Err(e) {
!_onerror(e) && console.log('Retrying...\nleft: ' + (retry-1).toString());
console.log(e);
throw new Error('Server returned with an error (logged above)');
}
},
onerror: _onerror,
ontimeout: _onerror,
onabort: _onerror,
});
// Returns true for error, false for retry
function _onerror(e) {
console.log('sign = ' + calcSign(text));
if (retry > 0) {
setTimeout(retryRequest.bind(null, e), 500);
return false;
}
onerror(e);
return true;
}
function retryRequest(e) {
translate({
callback: callback,
text: text,
src: src,
dst: dst,
onerror: onerror,
retry: retry - 1,
args: args
});
}
}
function langDetect(text) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'POST',
url: 'https://fanyi.baidu.com/langdetect',
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded'
},
data: toQueryString({'query': text}),
onload: function(response) {
const json = JSON.parse(response.responseText);
resolve(json.lan);
},
onerror: function(e) {reject(e)},
ontimeout: function(e) {reject(e)},
onabort: function(e) {reject(e)},
});
});
}
// Calc sign based on query-text and gtk
function calcSign(query) {
function e(t, e) {
(null == e || e > t.length) && (e = t.length);
for (var n = 0, r = new Array(e); n < e; n++)
r[n] = t[n];
return r
}
function n(t, e) {
for (var n = 0; n < e.length - 2; n += 3) {
var r = e.charAt(n + 2);
r = "a" <= r ? r.charCodeAt(0) - 87 : Number(r),
r = "+" === e.charAt(n + 1) ? t >>> r : t << r,
t = "+" === e.charAt(n) ? t + r & 4294967295 : t ^ r
}
return t
}
var r = null;
var token = function(t, _gtk) {
var o, i = t.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
if (null === i) {
var a = t.length;
a > 30 && (t = "".concat(t.substr(0, 10)).concat(t.substr(Math.floor(a / 2) - 5, 10)).concat(t.substr(-10, 10)))
} else {
for (var s = t.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), c = 0, u = s.length, l = []; c < u; c++)
"" !== s[c] && l.push.apply(l, function(t) {
if (Array.isArray(t))
return e(t)
}(o = s[c].split("")) || function(t) {
if ("undefined" != typeof Symbol && null != t[Symbol.iterator] || null != t["@@iterator"])
return Array.from(t)
}(o) || function(t, n) {
if (t) {
if ("string" == typeof t)
return e(t, n);
var r = Object.prototype.toString.call(t).slice(8, -1);
return "Object" === r && t.constructor && (r = t.constructor.name),
"Map" === r || "Set" === r ? Array.from(t) : "Arguments" === r || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r) ? e(t, n) : void 0
}
}(o) || function() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")
}()),
c !== u - 1 && l.push(i[c]);
var p = l.length;
p > 30 && (t = l.slice(0, 10).join("") + l.slice(Math.floor(p / 2) - 5, Math.floor(p / 2) + 5).join("") + l.slice(-10).join(""))
}
for (var h = (_gtk || "").split("."), f = Number(h[0]) || 0, m = Number(h[1]) || 0, g = [], y = 0, v = 0; v < t.length; v++) {
var _ = t.charCodeAt(v);
_ < 128 ? g[y++] = _ : (_ < 2048 ? g[y++] = _ >> 6 | 192 : (55296 == (64512 & _) && v + 1 < t.length && 56320 == (64512 & t.charCodeAt(v + 1)) ? (_ = 65536 + ((1023 & _) << 10) + (1023 & t.charCodeAt(++v)),
g[y++] = _ >> 18 | 240,
g[y++] = _ >> 12 & 63 | 128) : g[y++] = _ >> 12 | 224,
g[y++] = _ >> 6 & 63 | 128),
g[y++] = 63 & _ | 128)
}
for (var b = f, w = '+-a^+6', k = '+-3^+b+-f', x = 0; x < g.length; x++)
b = n(b += g[x], w);
return b = n(b, k),
(b ^= m) < 0 && (b = 2147483648 + (2147483647 & b)),
"".concat((b %= 1e6).toString(), ".").concat(b ^ f)
}
return token(query, BT.gtk);
}
function toQueryString(obj) {
const USP = new URLSearchParams();
for (const [key, value] of Object.entries(obj)) {
USP.append(key, value);
}
return USP.toString();
}
// Request token and gtk
function init() {
// Request twice, make sure gtk is latest,
// or may get 998 error while requesting translate API
requestIndex(requestIndex.bind(null, function(html) {
BT.token = html.match(/token: ["'](.*?)["'],/)[1];
BT.gtk = html.match(/window.gtk = ["'](.*?)["'];/)[1];
BT.inited = true;
oninit();
}));
function requestIndex(callback) {
const url = 'https://fanyi.baidu.com';
GM_xmlhttpRequest({
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
},
url: url,
onload: function(response) {
callback(response.responseText);
}
});
}
}
}
function AsyncManager() {
const AM = this;
// Ongoing xhr count
this.taskCount = 0;
// Whether generate finish events
let finishEvent = false;
Object.defineProperty(this, 'finishEvent', {
configurable: true,
enumerable: true,
get: () => (finishEvent),
set: (b) => {
finishEvent = b;
b && AM.taskCount === 0 && AM.onfinish && AM.onfinish();
}
});
// Add one task
this.add = () => (++AM.taskCount);
// Finish one task
this.finish = () => ((--AM.taskCount === 0 && AM.finishEvent && AM.onfinish && AM.onfinish(), AM.taskCount));
}
function parseArgs(args, rules, defaultValues=[]) {
// args and rules should be array, but not just iterable (string is also iterable)
if (!Array.isArray(args) || !Array.isArray(rules)) {
throw new TypeError('parseArgs: args and rules should be array')
}
// fill rules[0]
(!Array.isArray(rules[0]) || rules[0].length === 1) && rules.splice(0, 0, []);
// max arguments length
const count = rules.length - 1;
// args.length must <= count
if (args.length > count) {
throw new TypeError(`parseArgs: args has more elements(${args.length}) longer than ruless'(${count})`);
}
// rules[i].length should be === i if rules[i] is an array, otherwise it should be a function
for (let i = 1; i <= count; i++) {
const rule = rules[i];
if (Array.isArray(rule)) {
if (rule.length !== i) {
throw new TypeError(`parseArgs: rules[${i}](${rule}) should have ${i} numbers, but given ${rules[i].length}`);
}
if (!rule.every((num) => (typeof num === 'number' && num <= count))) {
throw new TypeError(`parseArgs: rules[${i}](${rule}) should contain numbers smaller than count(${count}) only`);
}
} else if (typeof rule !== 'function') {
throw new TypeError(`parseArgs: rules[${i}](${rule}) should be an array or a function.`)
}
}
// Parse
const rule = rules[args.length];
let parsed;
if (Array.isArray(rule)) {
parsed = [...defaultValues];
for (let i = 0; i < rule.length; i++) {
parsed[rule[i]-1] = args[i];
}
} else {
parsed = rule(args, defaultValues);
}
return parsed;
}
}) ();