🏠 Home 

Baidu Translate

Baidu translate api support for userscripts. No need for baidu's token.

สคริปต์นี้ไม่ควรถูกติดตั้งโดยตรง มันเป็นคลังสำหรับสคริปต์อื่น ๆ เพื่อบรรจุด้วยคำสั่งเมทา // @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//###////////////+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(r###lt) {console.log(r###lt);}.
Argument `r###lt` will be <string> translate r###lt.
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 r###lt
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 r###lt = [];
AM.onfinish = function() {
callback(r###lt.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] : '');
r###lt[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_r###lt = json.trans_r###lt.data.reduce(function(pre, cur) {
return (pre.push('\n'.repeat(cur.prefixWrap) + cur.dst), pre);
}, []).join('\n');
r###lt[i].dst = temp_r###lt;
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;
}
}) ();