efront 4.13.2 → 4.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,36 @@
1
+ - zh-CN: 未知错误!
2
+ en: Unknown error!
3
+
4
+ - zh-CN: 文件系统
5
+ en: file system
6
+
7
+ - zh-CN: 网络
8
+ en: network
9
+
10
+ - zh-CN: 无法访问$1
11
+ en: Unable to access $1
12
+
13
+ - zh-CN: Cookie解析异常!
14
+ en: Cookie parsing exception!
15
+
16
+ - zh-CN: 数据无法解析!
17
+ en: Data cannot be parsed!
18
+
19
+ - zh-CN: 无法连接可加密的服务器!
20
+ en: Unable to connect to an encrypted server!
21
+
22
+ - zh-CN: 无可用的数据源
23
+ en: No available data source
24
+
25
+ - zh-CN: 通道不存在!
26
+ en: The channel does not exist!
27
+
28
+ - zh-CN: 服务器忙!
29
+ en: The server is busy!
30
+
31
+ - zh-CN: $1不是有效的色彩信息
32
+ en: $1 is not a valid color
33
+
1
34
  - zh-CN: 加载失败
2
35
  en: Loading failed
3
36
 
@@ -316,8 +349,8 @@
316
349
  - zh-CN: 检查到两个菜单项使用了相同的快捷键
317
350
  en: Checked that two menu items used the same shortcut key
318
351
 
319
- - zh-CN: 如您需要使用参数--SCITER或--QUICKJS或--QJS,请购买炸毛授权
320
- en: "If you need to use the parameters --SCITER or --QUICKJS or --QJS, please purchase the authorization for explosion"
352
+ - zh-CN: 如您需要使用参数--SCITER或--QUICKJS或--QJS,请联系作者购买授权(暂定50元人民币)
353
+ en: "If you need to use the parameters --SCITER or --QUICKJS or --QJS, please concat the author and purchase the authorization, it costs 50 CNY now."
321
354
 
322
355
  - zh-CN: 检测到错误,无法建立代码关联:$1
323
356
  en: "Error detected, unable to establish code association: $1"
@@ -35,7 +35,7 @@ function main(params, from) {
35
35
  resultMap: null,
36
36
  addResult(info) {
37
37
  var resultMap = this.resultMap;
38
- var singerName = sortname(String(info.singername || '').split(/[\&\,,、]/)).join('、');
38
+ var singerName = sortname(String(info.singername || '').split(/[\&\,,、]/)).join('、');
39
39
  var songName = info.songname;
40
40
  var id = `${singerName}:${info.songname}`;
41
41
  if (!resultMap[id]) resultMap[id] = Object.assign([], { singer: singerName, song: songName });
@@ -0,0 +1,6 @@
1
+ <script serverside>
2
+ var fs = require("fs").promises;
3
+ var names = await fs.readdir(__dirname);
4
+ names = names.filter(a => /\.(jpe?g|png|gif)$/i.test(names));
5
+ return JSON.stringify(names);
6
+ </script>
@@ -1 +1 @@
1
- buildList('songs-list');
1
+ buildList(['song/list.jsp', 'songs-list']);
@@ -0,0 +1,6 @@
1
+ <script serverside>
2
+ var fs = require("fs").promises;
3
+ var names = await fs.readdir(__dirname);
4
+ names = names.filter(a => /\.(flac|mp3|wav)$/i.test(a));
5
+ return JSON.stringify(names);
6
+ </script>
@@ -143,16 +143,22 @@ function cross_(jsonp, digest = noop, method, url, headers) {
143
143
  var onerror1 = function (e) {
144
144
  if (!~requests.indexOf(_xhr)) return;
145
145
  removeFromList(requests, _xhr);
146
- errored = e || "未知错误!";
146
+ errored = e || i18n`未知错误!`;
147
147
  if (typeof errored === 'string') {
148
148
  errored = createResponse(e, xhr.status);
149
149
  }
150
150
  flush();
151
151
  digest();
152
152
  };
153
+ var getErrorSystem = function () {
154
+ if (!/^(\w+\:|\/\/)/.test(url) && /^file\:/i.test(location.href) || /^file\:/i.test(url)) return i18n`文件系统`;
155
+ if (navigator.onLine) return i18n`网络`;
156
+ return i18n`服务器`;
157
+ };
158
+
153
159
  var onerror = async function (e) {
154
160
  if (e.type === 'error') {
155
- e = createResponse("无法访问服务器!");
161
+ e = createResponse(i18n`无法访问${getErrorSystem()}`);
156
162
  }
157
163
  headers = extend({}, _headers);
158
164
  for (var r of reforms) {
@@ -212,7 +218,7 @@ function cross_(jsonp, digest = noop, method, url, headers) {
212
218
  if (isencrypt) cookie = encode62.safedecode(cookie, xhr.encrypt);
213
219
  }
214
220
  catch (e) {
215
- onerror({ status: xhr.status, response: "Cookie解析异常!", toString: toResponse });
221
+ onerror({ status: xhr.status, response: i18n`Cookie解析异常!`, toString: toResponse });
216
222
  return;
217
223
  }
218
224
  cookie_.addCookie(cookie, originDomain);
@@ -233,13 +239,13 @@ function cross_(jsonp, digest = noop, method, url, headers) {
233
239
  xhr.responseText = xhr.response;
234
240
  }
235
241
  catch (e) {
236
- return onerror("数据无法解析!")
242
+ return onerror(i18n`数据无法解析!`);
237
243
  }
238
244
  };
239
245
  switch (xhr.status) {
240
246
  case 0:
241
247
  if (!xhr.response) {
242
- onerror("无法访问服务器");
248
+ onerror(i18n`无法访问${getErrorSystem()}`);
243
249
  break;
244
250
  }
245
251
  case 200:
@@ -493,7 +499,7 @@ function addReform(r) {
493
499
  function getCode() {
494
500
  return new Promise((ok, oh) => {
495
501
  this('get', base + "!").then((xhr) => { return ok(encode62.timedecode(xhr.response || xhr.responseText)) }, () => {
496
- return oh('无法连接可加密的服务器!');
502
+ return oh(i18n`无法连接可加密的服务器!`);
497
503
  });
498
504
  });
499
505
  }
@@ -815,12 +815,22 @@ var data = {
815
815
  return createApiMap(o);
816
816
  }
817
817
  },
818
+ fromAll(refs, params, parse) {
819
+ return this.createResponse(Promise.all(refs.map(r => this.from(r, params, parse).loading_promise.catch(e => []))).then(datas => {
820
+ datas = datas.filter(a => !!a);
821
+ if (!datas.length) throw new Error(i18n`无可用的数据源`);
822
+ return datas.concat.apply([], datas);
823
+ }));
824
+ },
818
825
  from(ref, params, parse) {
819
826
  if (params instanceof Function) {
820
827
  parse = params;
821
828
  params = {};
822
829
  }
823
- if (isObject(ref)) {
830
+ if (isArray(ref)) {
831
+ return this.fromAll(ref, params, parse);
832
+ }
833
+ else if (isObject(ref)) {
824
834
  return this.fromApi(ref, params, parse);
825
835
  }
826
836
  else if (/^\.*\/|\.\w+$/.test(ref)) {
@@ -488,14 +488,28 @@ var Method = function () {
488
488
  return body;
489
489
  }
490
490
  var vlist = [], mlist = [macros], clist = [], base = '';
491
+ var killneg = function (v, n) {
492
+ if (n === "-") {
493
+ if (/^\-/.test(v)) {
494
+ v = v.slice(1);
495
+ }
496
+ else {
497
+ v = n + v;
498
+ }
499
+ }
500
+ return v;
501
+ };
491
502
  var calcvars = function (v) {
492
503
  var decode = /^['"`]/.test(v) ? strings.decode : a => a;
493
- return v.replace(/@[^\s\{\}\(\)\[\]\:\+\*\/,;\!\>\$\=\&\%\#\@'"`\?\.\/\|~#]+|@\{[^\}@]*\}/g, function (m) {
504
+ return v.replace(/(^\-)?(@[^\s\{\}\(\)\[\]\:\+\*\/,;\!\>\$\=\&\%\#\@'"`\?\.\/\|~#]+|@\{[^\}@]*\})/g, function (_, n, m) {
494
505
  var value = getFromScopeList(m, vlist, m);
495
506
  value = decode(value);
507
+ value = killneg(value, n);
496
508
  return value;
497
- }).replace(/(^|\s|[\]\)\(\[\-\+\*\/,;])(?:var\s*\(([\s\S]*?)\)|(--\S+))/g, function (m, q, a, b) {
498
- return q + getFromScopeList(b || a.trim(), vlist, m.slice(q.length));
509
+ }).replace(/(^|\s|[\]\)\(\[\+\*\/,;]|^\-)(?:var\s*\(([\s\S]*?)\)|(--\S+))/g, function (m, q, a, b) {
510
+ var v = getFromScopeList(b || a.trim(), vlist, m.slice(q.length));
511
+ v = killneg(v, q);
512
+ return v;
499
513
  });
500
514
  };
501
515
  var initvars = function (vars) {
@@ -86,6 +86,7 @@ assert(素馨(`a{a:extract(2,3,2)}`), `a{a:3;}`);
86
86
  assert(素馨(`a{a:extract(2 3,2)}`), `a{a:3;}`);
87
87
  assert(素馨(`value: range(10px, 30px, 10);`, '', true), `value:10px 20px 30px;`);
88
88
  assert(素馨(`value: range(4);`, '', true), `value:1 2 3 4;`);
89
+ assert(素馨(`@a:-1;b{a:-@a}`, '', true), `b{a:1;}`);
89
90
  assert(scanner2(`-0.2em .3em -0.2em 0`, new 素馨.素心)[0].text, '-0.2em');
90
91
  assert(scanner2(`-0.2em .3em -0.2em 0`, new 素馨.素心)[0].isdigit, true);
91
92
  assert(scanner2(`-0.2em .3em -0.2em 0`, new 素馨.素心)[2].text, ".3em");
@@ -6,7 +6,7 @@ function main(dataid, datapath) {
6
6
  padding,
7
7
  song,
8
8
  loading,
9
- musicList:kugou$musicList,
9
+ musicList: kugou$musicList,
10
10
  async run(s) {
11
11
  if (!s.hash && s.hashid) {
12
12
  await data.from("song-mix", s, function (a) {
@@ -14,7 +14,7 @@ function main(dataid, datapath) {
14
14
  if (m) s.hash = m[3];
15
15
  });
16
16
  }
17
- if (s.hash) {
17
+ if (s.hash || s.url) {
18
18
  kugou$player.play(s);
19
19
  } else {
20
20
  go(datapath, s);
@@ -1,4 +1,5 @@
1
1
  var activeDevice, ratio = 1;
2
+ var strokeColor = '#096';
2
3
  function line(buffer, style, lineWidth = window.devicePixelRatio || 1) {
3
4
  var canvas = this;
4
5
  var context = canvas.getContext("2d");
@@ -27,7 +28,7 @@ function line(buffer, style, lineWidth = window.devicePixelRatio || 1) {
27
28
  var [x, y] = buffer[cx];
28
29
  context.lineTo(x * width, y * height);
29
30
  }
30
- context.strokeStyle = style || "#00bd7bd4";
31
+ context.strokeStyle = style || strokeColor;
31
32
  context.lineWidth = lineWidth;
32
33
  context.stroke();
33
34
  }
@@ -69,7 +70,7 @@ function draw(buffer) {
69
70
  if (canvas.height !== canvas.offsetHeight * devicePixelRatio) canvas.height = canvas.offsetHeight * devicePixelRatio;
70
71
  context.clearRect(0, 0, canvas.width, canvas.height);
71
72
  context.beginPath();
72
- context.strokeStyle = "#00bd7bd4";
73
+ context.strokeStyle = strokeColor;
73
74
  context.lineWidth = window.devicePixelRatio || 1;
74
75
  var max = 2;
75
76
  var v = (this.volume >= 0 ? this.volume : 1) * buffer.length - .5;
@@ -91,7 +92,7 @@ function draw(buffer) {
91
92
  }
92
93
  });
93
94
  context.lineWidth = 1;
94
- context.strokeStyle = "#00bd7bd4";
95
+ context.strokeStyle = strokeColor;
95
96
  context.stroke();
96
97
  if (this === activeDevice) {
97
98
  context.beginPath();
@@ -0,0 +1 @@
1
+ a => a.split(/[\&\,,、]/).join('、');
@@ -9,7 +9,8 @@ var isSameSong = function (m1, m2) {
9
9
  m1.hash && m1.hash === m2.hash || // 酷狗
10
10
  m1.id && m1.id === m2.id || // 网易云 千千静听
11
11
  m1.rid && m1.rid === m2.rid || // 酷我
12
- m1.mid && m1.mid === m2.mid; // 酷我
12
+ m1.mid && m1.mid === m2.mid ||// 酷我
13
+ m1.url && m1.url === m2.url;
13
14
  };
14
15
 
15
16
  function addMethod(name, func) {
@@ -1,4 +1,11 @@
1
- a => {
1
+ var singerPhotosMap = Object.create(null);
2
+ data.from("singer/list.jsp", function (a) {
3
+ a.forEach(a => {
4
+ var b = a.replace(/\.\w+$/, '');
5
+ singerPhotosMap[b] = a;
6
+ })
7
+ })
8
+ return a => {
2
9
  if (isElement(a)) {
3
10
  var m = /songsdata\s*=\s*(\[[\s\S]*\])/.exec(a.innerText);
4
11
  if (!m) throw new Error(i18n`无法加载数据!`);
@@ -7,16 +14,31 @@ a => {
7
14
  }
8
15
  if (a) return a.map(b => {
9
16
  var data = {};
17
+
10
18
  if (b.data) extend(data, {
11
19
  name: b.data.filename.replace(/^[\s\S]*?\s*\-\s*/, ''),
12
20
  singer: b.data.filename.replace(/\s*\-\s*[\s\S]*?$/, '')
13
21
  }, b.data);
14
- else extend(data, b);
15
- if (!data.singer) {
22
+ else if (isObject(b)) extend(data, b);
23
+ if (typeof b === 'string') {
24
+ var [name, singer] = b.replace(/\.\w+$/, '').split(/\s*-\s*/);
25
+ data.name = name;
26
+ data.singer = singer;
27
+ data.url = "song/" + b;
28
+
29
+ } if (!data.singer) {
16
30
  data.singer = data.author_name;
17
31
  }
18
32
  if (!data.name) data.name = data.audio_name;
19
33
  if (data.hash) data.hash = data.hash.replace(/^songs\_/i, '');
34
+ if (data.singer) data.singer = formatSingerNames(data.singer);
35
+ if (!data.avatar && data.singer) {
36
+ var singer0 = data.singer.split("、")[0];
37
+ console.log(singer0)
38
+ if (singer0 in singerPhotosMap) data.avatar = `singer/` + singerPhotosMap[singer0];
39
+ }
40
+ if (!data.singerName) data.singerName = data.singer;
41
+ if (!data.songName) data.songName = data.name;
20
42
  return data;
21
43
  });
22
44
 
@@ -6,8 +6,6 @@
6
6
  right: 0;
7
7
  max-width: 460px;
8
8
  box-shadow: 0 0 20px -6px rgba(0, 0, 0, .6);
9
- margin-bottom: 10px;
10
- overflow: visible;
11
9
  background: #131416;
12
10
  margin-top: 0;
13
11
  transition: margin .2s ease-out;
@@ -5,21 +5,18 @@
5
5
  </div>
6
6
  <div class="track"></div>
7
7
  <div class="avatar" ng-style="{'background-image': info.avatarUrl,transform:currentRotate}"></div>
8
- <div class="info">
9
- <div class="time">
10
- <span ng-bind="currentTime"></span>&nbsp;/&nbsp;
11
- <span ng-bind="totalTime"></span>
12
- </div>
13
- <div class="song">
14
- <span class="name" ng-bind=getSongName()></span>
15
- <span class="spliter" ng-if="getSongName()&&getSingerName()">&nbsp;-&nbsp;</span>
16
- <span class="singer" ng-bind=getSingerName()></span>
17
- </div>
8
+ <btn class="play"></btn>
9
+ <div class="time">
10
+ <span ng-bind="currentTime"></span>
18
11
  </div>
12
+ <div class="total">
13
+ <span ng-bind="totalTime"></span>
14
+ </div>
15
+ <div class="song" ng-bind=getSongName()></div>
16
+ <div class="singer" ng-bind=getSingerName()></div>
19
17
  <btn class="prev" ng-click=play(index-1)></btn>
20
- <btn class="play" ng-click="playing?pause():play()"></btn>
21
18
  <btn class="next" ng-click=play(index+1)></btn>
22
- <sbtn class="list"></sbtn>
19
+ <!-- <sbtn class="list"></sbtn> -->
23
20
  <krc elementid=krcpad></krc>
24
21
  <canvas elementid="dance"></canvas>
25
- <div class="avatar" ng-click="effectPage()"></div>
22
+ <div class="avatar" ng-click="playing?pause():play()" ng-click="effectPage()"></div>
@@ -38,13 +38,15 @@ var patchMusicInfo = async function (info) {
38
38
  break;
39
39
  case "kugo":
40
40
  default:
41
- res = await data.from("song-info", info);
42
- krc = await data.from("search-krc", res);
43
- krc = await data.from("download-krc", krc);
44
- info.krc = fromBase64(krc);
45
- if (res.fail_process === 12) res.priced = true;
46
- if (res.imgUrl) {
47
- res.avatar = res.imgUrl.replace(/\{size\}/ig, 200);
41
+ if (info.hash) {
42
+ res = await data.from("song-info", info);
43
+ krc = await data.from("search-krc", res);
44
+ krc = await data.from("download-krc", krc);
45
+ info.krc = fromBase64(krc);
46
+ if (res.fail_process === 12) res.priced = true;
47
+ if (res.imgUrl) {
48
+ res.avatar = res.imgUrl.replace(/\{size\}/ig, 200);
49
+ }
48
50
  }
49
51
  break;
50
52
  }
@@ -140,10 +142,10 @@ var $scope = {
140
142
  activeList: playList,
141
143
  index: 0,
142
144
  getSongName() {
143
- return this.info.singername || this.info.singerName;
145
+ return this.info.songname || this.info.songName;
144
146
  },
145
147
  getSingerName() {
146
- return this.info.songname || this.info.songName;
148
+ return this.info.singername || this.info.singerName;
147
149
  },
148
150
  update() {
149
151
  if (touching) return;
@@ -207,8 +209,12 @@ var $scope = {
207
209
  var { sin, cos } = Math;
208
210
  var { currentTheta } = $scope;
209
211
  if (player.offsetHeight <= calcPixel(80)) {
210
- var centerx = 44 / width, centery = .5;
211
- var start = 11 * ratio | 0, end = 77 * ratio | 0;
212
+ var avatar = player.querySelector(".avatar");
213
+ var { clientTop, clientWidth, offsetLeft } = avatar;
214
+ var offsetWidth = clientWidth;
215
+ offsetLeft += clientTop;
216
+ var centerx = (offsetWidth / 2 + offsetLeft) / width, centery = .5;
217
+ var start = offsetLeft * ratio | 0, end = (offsetLeft + offsetWidth) * ratio | 0;
212
218
  var cost = cos(currentTheta);
213
219
  var sint = sin(currentTheta);
214
220
  for (var cx = start, dx = end; cx < dx; cx++) {
@@ -430,6 +436,13 @@ var createControls = function () {
430
436
  };
431
437
 
432
438
  var player = function (player) {
439
+ var savatar = player.querySelector('canvas');
440
+ var switchPlayList = function () {
441
+ if (onclick.preventClick) return;
442
+ onclick.preventClick = true;
443
+ if (playList.parentNode) remove(playList);
444
+ else popup(playList, savatar);
445
+ }
433
446
  render(player, $scope);
434
447
  player.play = function (hash) {
435
448
  $scope.play(hash);
@@ -438,5 +451,17 @@ var player = function (player) {
438
451
  $scope.pause();
439
452
  };
440
453
  appendChild.before(document.body, player);
454
+ on("contextmenu")(player, e => e.preventDefault());
455
+ on("click.self")(player, function (a) {
456
+ if ($scope.playing) $scope.pause();
457
+ else $scope.play();
458
+ });
459
+ var timeout = 0;
460
+ on("pointerdown")(player, function () {
461
+ timeout = setTimeout(switchPlayList, 600);
462
+ });
463
+ on("pointerup")(player, function () {
464
+ clearTimeout(timeout);
465
+ })
441
466
  return player;
442
467
  }(createControls());