hexo-theme-shokax 0.3.14 → 0.3.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/scripts/filters/locals.js +52 -0
  3. package/scripts/filters/post.js +5 -0
  4. package/scripts/generaters/archive.js +133 -0
  5. package/scripts/generaters/config.js +48 -0
  6. package/scripts/generaters/images.js +23 -0
  7. package/scripts/generaters/index.js +107 -0
  8. package/scripts/generaters/pages.js +15 -0
  9. package/scripts/generaters/script.js +118 -0
  10. package/scripts/helpers/asset.js +147 -0
  11. package/scripts/helpers/engine.js +153 -0
  12. package/scripts/helpers/list_categories.js +84 -0
  13. package/scripts/helpers/summary_ai.js +107 -0
  14. package/scripts/helpers/symbols_count_time.js +69 -0
  15. package/scripts/plugin/check.js +32 -0
  16. package/scripts/plugin/index.js +78 -0
  17. package/scripts/plugin/lib/injects-point.js +20 -0
  18. package/scripts/plugin/lib/injects.js +89 -0
  19. package/scripts/tags/links.js +44 -0
  20. package/scripts/tags/media.js +19 -0
  21. package/scripts/utils.js +14 -0
  22. package/source/js/_app/components/sidebar.js +209 -0
  23. package/source/js/_app/fireworks.js +10 -0
  24. package/source/js/_app/globals/globalVars.js +80 -0
  25. package/source/js/_app/globals/handles.js +98 -0
  26. package/source/js/_app/globals/themeColor.js +62 -0
  27. package/source/js/_app/globals/thirdparty.js +62 -0
  28. package/source/js/_app/globals/tools.js +66 -0
  29. package/source/js/_app/library/anime.js +106 -0
  30. package/source/js/_app/library/dom.js +34 -0
  31. package/source/js/_app/library/loadFile.js +36 -0
  32. package/source/js/_app/library/proto.js +163 -0
  33. package/source/js/_app/library/scriptPjax.js +70 -0
  34. package/source/js/_app/library/storage.js +12 -0
  35. package/source/js/_app/library/vue.js +53 -0
  36. package/source/js/_app/page/comment.js +23 -0
  37. package/source/js/_app/page/common.js +41 -0
  38. package/source/js/_app/page/fancybox.js +65 -0
  39. package/source/js/_app/page/post.js +244 -0
  40. package/source/js/_app/page/search.js +118 -0
  41. package/source/js/_app/page/tab.js +53 -0
  42. package/source/js/_app/pjax/domInit.js +76 -0
  43. package/source/js/_app/pjax/refresh.js +52 -0
  44. package/source/js/_app/pjax/siteInit.js +51 -0
  45. package/source/js/_app/player.js +771 -0
@@ -0,0 +1,771 @@
1
+ import { originTitle } from './globals/globalVars';
2
+ import { showtip } from './globals/tools';
3
+ import { pageScroll } from './library/anime';
4
+ import { $dom } from './library/dom';
5
+ import { $storage } from './library/storage';
6
+ import { tabFormat } from './page/tab';
7
+ let NOWPLAYING = null;
8
+ const isMobile = /mobile/i.test(window.navigator.userAgent);
9
+ export const mediaPlayer = /* @__PURE__ */ (t, config) => {
10
+ const buttons = {
11
+ el: {},
12
+ create() {
13
+ if (!t.player.options.btns) {
14
+ return;
15
+ }
16
+ t.player.options.btns.forEach((item) => {
17
+ if (buttons.el[item]) {
18
+ return;
19
+ }
20
+ buttons.el[item] = t.createChild('div', {
21
+ className: item + ' btn',
22
+ onclick(event) {
23
+ t.player.fetch().then(() => {
24
+ t.player.options.events[item](event);
25
+ });
26
+ }
27
+ });
28
+ });
29
+ }
30
+ };
31
+ const controller = {
32
+ el: null,
33
+ btns: {
34
+ mode: undefined,
35
+ volume: undefined
36
+ },
37
+ step: 'next',
38
+ create: () => {
39
+ if (!t.player.options.controls) {
40
+ return;
41
+ }
42
+ const that = controller;
43
+ t.player.options.controls.forEach((item) => {
44
+ if (that.btns[item]) {
45
+ return;
46
+ }
47
+ const opt = {
48
+ onclick(event) {
49
+ that.events[item] ? that.events[item](event) : t.player.options.events[item](event);
50
+ }
51
+ };
52
+ switch (item) {
53
+ case 'volume':
54
+ opt.className = ' ' + (source.muted ? 'off' : 'on');
55
+ opt.innerHTML = '<div class="bar"></div>';
56
+ opt['on' + utils.nameMap.dragStart] = that.events.volume;
57
+ opt.onclick = null;
58
+ break;
59
+ case 'mode':
60
+ opt.className = ' ' + t.player.options.mode;
61
+ break;
62
+ default:
63
+ opt.className = '';
64
+ break;
65
+ }
66
+ opt.className = item + opt.className + ' btn';
67
+ that.btns[item] = that.el.createChild('div', opt);
68
+ });
69
+ that.btns.volume.bar = that.btns.volume.child('.bar');
70
+ },
71
+ events: {
72
+ mode(e) {
73
+ switch (t.player.options.mode) {
74
+ case 'loop':
75
+ t.player.options.mode = 'random';
76
+ break;
77
+ case 'random':
78
+ t.player.options.mode = 'order';
79
+ break;
80
+ default:
81
+ t.player.options.mode = 'loop';
82
+ }
83
+ controller.btns.mode.className = 'mode ' + t.player.options.mode + ' btn';
84
+ $storage.set('_PlayerMode', t.player.options.mode);
85
+ },
86
+ volume(e) {
87
+ e.preventDefault();
88
+ const current = e.currentTarget;
89
+ let drag = false;
90
+ const thumbMove = (e) => {
91
+ e.preventDefault();
92
+ t.player.volume(controller.percent(e, current));
93
+ drag = true;
94
+ };
95
+ const thumbUp = (e) => {
96
+ e.preventDefault();
97
+ current.removeEventListener(utils.nameMap.dragEnd, thumbUp);
98
+ current.removeEventListener(utils.nameMap.dragMove, thumbMove);
99
+ if (drag) {
100
+ t.player.muted();
101
+ t.player.volume(controller.percent(e, current));
102
+ }
103
+ else {
104
+ if (source.muted) {
105
+ t.player.muted();
106
+ t.player.volume(source.volume);
107
+ }
108
+ else {
109
+ t.player.muted('muted');
110
+ controller.update(0);
111
+ }
112
+ }
113
+ };
114
+ current.addEventListener(utils.nameMap.dragMove, thumbMove);
115
+ current.addEventListener(utils.nameMap.dragEnd, thumbUp);
116
+ },
117
+ backward(e) {
118
+ controller.step = 'prev';
119
+ t.player.mode();
120
+ },
121
+ forward(e) {
122
+ controller.step = 'next';
123
+ t.player.mode();
124
+ }
125
+ },
126
+ update(percent) {
127
+ controller.btns.volume.className = 'volume ' + (!source.muted && percent > 0 ? 'on' : 'off') + ' btn';
128
+ controller.btns.volume.bar.changeOrGetWidth(Math.floor(percent * 100) + '%');
129
+ },
130
+ percent(e, el) {
131
+ let percentage = ((e.clientX || e.changedTouches[0].clientX) - el.left()) / el.changeOrGetWidth();
132
+ percentage = Math.max(percentage, 0);
133
+ return Math.min(percentage, 1);
134
+ }
135
+ };
136
+ const progress = {
137
+ el: null,
138
+ bar: null,
139
+ create() {
140
+ const current = playlist.current().el;
141
+ if (current) {
142
+ if (progress.el) {
143
+ progress.el.parentNode.removeClass('current')
144
+ .removeEventListener(utils.nameMap.dragStart, progress.drag);
145
+ progress.el.remove();
146
+ }
147
+ progress.el = current.createChild('div', {
148
+ className: 'progress'
149
+ });
150
+ progress.el.attr('data-dtime', utils.secondToTime(0));
151
+ progress.bar = progress.el.createChild('div', {
152
+ className: 'bar'
153
+ });
154
+ current.addClass('current');
155
+ current.addEventListener(utils.nameMap.dragStart, progress.drag);
156
+ playlist.scroll();
157
+ }
158
+ },
159
+ update(percent) {
160
+ progress.bar.changeOrGetWidth(Math.floor(percent * 100) + '%');
161
+ progress.el.attr('data-ptime', utils.secondToTime(percent * source.duration));
162
+ },
163
+ seeking(type) {
164
+ if (type) {
165
+ progress.el.addClass('seeking');
166
+ }
167
+ else {
168
+ progress.el.removeClass('seeking');
169
+ }
170
+ },
171
+ percent(e, el) {
172
+ let percentage = ((e.clientX || e.changedTouches[0].clientX) - el.left()) / el.changeOrGetWidth();
173
+ percentage = Math.max(percentage, 0);
174
+ return Math.min(percentage, 1);
175
+ },
176
+ drag(e) {
177
+ e.preventDefault();
178
+ const current = playlist.current().el;
179
+ const thumbMove = (e) => {
180
+ e.preventDefault();
181
+ const percentage = progress.percent(e, current);
182
+ progress.update(percentage);
183
+ lyrics.update(percentage * source.duration);
184
+ };
185
+ const thumbUp = (e) => {
186
+ e.preventDefault();
187
+ current.removeEventListener(utils.nameMap.dragEnd, thumbUp);
188
+ current.removeEventListener(utils.nameMap.dragMove, thumbMove);
189
+ const percentage = progress.percent(e, current);
190
+ progress.update(percentage);
191
+ t.player.seek(percentage * source.duration);
192
+ source.disableTimeupdate = false;
193
+ progress.seeking(false);
194
+ };
195
+ source.disableTimeupdate = true;
196
+ progress.seeking(true);
197
+ current.addEventListener(utils.nameMap.dragMove, thumbMove);
198
+ current.addEventListener(utils.nameMap.dragEnd, thumbUp);
199
+ }
200
+ };
201
+ const preview = {
202
+ el: null,
203
+ create() {
204
+ const current = playlist.current();
205
+ preview.el.innerHTML = '<div class="cover"><div class="disc"><img src="' + (current.cover) + '" class="blur" alt="music cover"/></div></div>' +
206
+ '<div class="info"><h4 class="title">' + current.name + '</h4><span>' + current.artist + '</span>' +
207
+ '<div class="lrc"></div></div>';
208
+ preview.el.child('.cover').addEventListener('click', t.player.options.events['play-pause']);
209
+ lyrics.create(preview.el.child('.lrc'));
210
+ }
211
+ };
212
+ let source;
213
+ const playlist = {
214
+ el: null,
215
+ data: [],
216
+ index: -1,
217
+ errnum: 0,
218
+ add: (group, list) => {
219
+ list.forEach((item) => {
220
+ item.group = group;
221
+ item.name = item.name || item.title || 'Meida name';
222
+ item.artist = item.artist || item.author || 'Anonymous';
223
+ item.cover = item.cover || item.pic;
224
+ item.type = item.type || 'normal';
225
+ playlist.data.push(item);
226
+ });
227
+ },
228
+ clear() {
229
+ playlist.data = [];
230
+ playlist.el.innerHTML = '';
231
+ if (playlist.index !== -1) {
232
+ playlist.index = -1;
233
+ t.player.fetch();
234
+ }
235
+ },
236
+ create() {
237
+ const el = playlist.el;
238
+ playlist.data.map((item, index) => {
239
+ if (item.el) {
240
+ return null;
241
+ }
242
+ const id = 'list-' + t.player._id + '-' + item.group;
243
+ let tab = $dom('#' + id);
244
+ if (!tab) {
245
+ tab = el.createChild('div', {
246
+ id,
247
+ className: t.player.group ? 'tab' : '',
248
+ innerHTML: '<ol></ol>'
249
+ });
250
+ if (t.player.group) {
251
+ tab.attr('data-title', t.player.options.rawList[item.group].title)
252
+ // @ts-ignore
253
+ .attr('data-id', t.player._id);
254
+ }
255
+ }
256
+ item.el = tab.child('ol').createChild('li', {
257
+ title: item.name + ' - ' + item.artist,
258
+ innerHTML: '<span class="info"><span>' + item.name + '</span><span>' + item.artist + '</span></span>',
259
+ onclick(event) {
260
+ const current = event.currentTarget;
261
+ if (playlist.index === index && progress.el) {
262
+ if (source.paused) {
263
+ t.player.play();
264
+ }
265
+ else {
266
+ t.player.seek(source.duration * progress.percent(event, current));
267
+ }
268
+ return;
269
+ }
270
+ t.player.switch(index);
271
+ t.player.play();
272
+ }
273
+ });
274
+ return item;
275
+ });
276
+ tabFormat();
277
+ },
278
+ current() {
279
+ return this.data[this.index];
280
+ },
281
+ scroll() {
282
+ const item = this.current();
283
+ let li = this.el.child('li.active');
284
+ li && li.removeClass('active');
285
+ let tab = this.el.child('.tab.active');
286
+ tab && tab.removeClass('active');
287
+ li = this.el.find('.nav li')[item.group];
288
+ li && li.addClass('active');
289
+ tab = this.el.find('.tab')[item.group];
290
+ tab && tab.addClass('active');
291
+ pageScroll(item.el, item.el.offsetTop);
292
+ return this;
293
+ },
294
+ title() {
295
+ if (source.paused) {
296
+ return;
297
+ }
298
+ const current = this.current();
299
+ document.title = 'Now Playing...' + current.name + ' - ' + current.artist + ' | ' + originTitle;
300
+ },
301
+ error() {
302
+ const current = this.current();
303
+ current.el.removeClass('current').addClass('error');
304
+ current.error = true;
305
+ this.errnum++;
306
+ }
307
+ };
308
+ const info = {
309
+ el: null,
310
+ create() {
311
+ if (this.el) {
312
+ return;
313
+ }
314
+ this.el = t.createChild('div', {
315
+ className: 'player-info',
316
+ innerHTML: (t.player.options.type === 'audio' ? '<div class="preview"></div>' : '') + '<div class="controller"></div><div class="playlist"></div>'
317
+ }, 'after');
318
+ preview.el = this.el.child('.preview');
319
+ playlist.el = this.el.child('.playlist');
320
+ controller.el = this.el.child('.controller');
321
+ },
322
+ hide() {
323
+ const el = this.el;
324
+ el.addClass('hide');
325
+ window.setTimeout(() => {
326
+ el.removeClass('show hide');
327
+ }, 300);
328
+ }
329
+ };
330
+ const option = {
331
+ type: 'audio',
332
+ mode: 'random',
333
+ btns: ['play-pause', 'music'],
334
+ controls: ['mode', 'backward', 'play-pause', 'forward', 'volume'],
335
+ events: {
336
+ 'play-pause'(event) {
337
+ if (source.paused) {
338
+ t.player.play();
339
+ }
340
+ else {
341
+ t.player.pause();
342
+ }
343
+ },
344
+ music(event) {
345
+ if (info.el.hasClass('show')) {
346
+ info.hide();
347
+ }
348
+ else {
349
+ info.el.addClass('show');
350
+ playlist.scroll().title();
351
+ }
352
+ }
353
+ }
354
+ };
355
+ const utils = {
356
+ random(len) {
357
+ return Math.floor((Math.random() * len));
358
+ },
359
+ parse(link) {
360
+ let result = [];
361
+ [
362
+ ['music.163.com.*song.*id=(\\d+)', 'netease', 'song'],
363
+ ['music.163.com.*album.*id=(\\d+)', 'netease', 'album'],
364
+ ['music.163.com.*artist.*id=(\\d+)', 'netease', 'artist'],
365
+ ['music.163.com.*playlist.*id=(\\d+)', 'netease', 'playlist'],
366
+ ['music.163.com.*discover/toplist.*id=(\\d+)', 'netease', 'playlist'],
367
+ ['y.qq.com.*song/(\\w+)(.html)?', 'tencent', 'song'],
368
+ ['y.qq.com.*album/(\\w+)(.html)?', 'tencent', 'album'],
369
+ ['y.qq.com.*singer/(\\w+)(.html)?', 'tencent', 'artist'],
370
+ ['y.qq.com.*playsquare/(\\w+)(.html)?', 'tencent', 'playlist'],
371
+ ['y.qq.com.*playlist/(\\w+)(.html)?', 'tencent', 'playlist'],
372
+ ['xiami.com.*song/(\\w+)', 'xiami', 'song'],
373
+ ['xiami.com.*album/(\\w+)', 'xiami', 'album'],
374
+ ['xiami.com.*artist/(\\w+)', 'xiami', 'artist'],
375
+ ['xiami.com.*collect/(\\w+)', 'xiami', 'playlist']
376
+ ].forEach((rule) => {
377
+ const patt = new RegExp(rule[0]);
378
+ const res = patt.exec(link);
379
+ if (res !== null) {
380
+ result = [rule[1], rule[2], res[1]];
381
+ }
382
+ });
383
+ return result;
384
+ },
385
+ fetch(source) {
386
+ const list = [];
387
+ return new Promise((resolve, reject) => {
388
+ source.forEach((raw) => {
389
+ const meta = utils.parse(raw);
390
+ if (meta[0]) {
391
+ const skey = JSON.stringify(meta);
392
+ const playlist = $storage.get(skey);
393
+ if (playlist) {
394
+ // list.push.apply(list, JSON.parse(playlist))
395
+ list.push(...JSON.parse(playlist));
396
+ resolve(list);
397
+ }
398
+ else {
399
+ fetch(`${CONFIG.playerAPI}/meting/?server=` + meta[0] + '&type=' + meta[1] + '&id=' + meta[2] + '&r=' + Math.random())
400
+ .then((response) => {
401
+ return response.json();
402
+ }).then((json) => {
403
+ $storage.set(skey, JSON.stringify(json));
404
+ // list.push.apply(list, json)
405
+ list.push(...json);
406
+ resolve(list);
407
+ }).catch((ex) => {
408
+ // (不)处理catch的异常
409
+ });
410
+ }
411
+ }
412
+ else {
413
+ list.push(raw);
414
+ resolve(list);
415
+ }
416
+ });
417
+ });
418
+ },
419
+ secondToTime(second) {
420
+ const add0 = (num) => {
421
+ return isNaN(num) ? '00' : (num < 10 ? '0' + num : '' + num);
422
+ };
423
+ const hour = Math.floor(second / 3600);
424
+ const min = Math.floor((second - hour * 3600) / 60);
425
+ const sec = Math.floor(second - hour * 3600 - min * 60);
426
+ return (hour > 0 ? [hour, min, sec] : [min, sec]).map(add0).join(':');
427
+ },
428
+ nameMap: {
429
+ dragStart: isMobile ? 'touchstart' : 'mousedown',
430
+ dragMove: isMobile ? 'touchmove' : 'mousemove',
431
+ dragEnd: isMobile ? 'touchend' : 'mouseup'
432
+ }
433
+ };
434
+ source = null;
435
+ t.player = {
436
+ _id: utils.random(999999),
437
+ group: true,
438
+ // 加载播放列表
439
+ load(newList) {
440
+ let d = '';
441
+ if (newList && newList.length > 0) {
442
+ if (this.options.rawList !== newList) {
443
+ this.options.rawList = newList;
444
+ playlist.clear();
445
+ // 获取新列表
446
+ this.fetch();
447
+ }
448
+ }
449
+ else {
450
+ // 没有列表时,隐藏按钮
451
+ d = 'none';
452
+ this.pause();
453
+ }
454
+ for (const el in buttons.el) {
455
+ buttons.el[el].display(d);
456
+ }
457
+ return this;
458
+ },
459
+ fetch() {
460
+ return new Promise((resolve, reject) => {
461
+ if (playlist.data.length > 0) {
462
+ resolve(true);
463
+ }
464
+ else {
465
+ if (this.options.rawList) {
466
+ const promises = [];
467
+ this.options.rawList.forEach((raw, index) => {
468
+ promises.push(new Promise((resolve, reject) => {
469
+ let group = index;
470
+ let source;
471
+ if (!raw.list) {
472
+ group = 0;
473
+ this.group = false;
474
+ source = [raw];
475
+ }
476
+ else {
477
+ this.group = true;
478
+ source = raw.list;
479
+ }
480
+ utils.fetch(source).then((list) => {
481
+ playlist.add(group, list);
482
+ resolve(0);
483
+ });
484
+ }));
485
+ });
486
+ Promise.all(promises).then(() => {
487
+ resolve(true);
488
+ });
489
+ }
490
+ }
491
+ }).then((c) => {
492
+ if (c) {
493
+ playlist.create();
494
+ controller.create();
495
+ this.mode();
496
+ }
497
+ });
498
+ },
499
+ // 根据模式切换当前曲目index
500
+ mode() {
501
+ const total = playlist.data.length;
502
+ if (!total || playlist.errnum === total) {
503
+ return;
504
+ }
505
+ const step = controller.step === 'next' ? 1 : -1;
506
+ const next = () => {
507
+ let index = playlist.index + step;
508
+ if (index > total || index < 0) {
509
+ index = controller.step === 'next' ? 0 : total - 1;
510
+ }
511
+ playlist.index = index;
512
+ };
513
+ const random = () => {
514
+ const p = utils.random(total);
515
+ if (playlist.index !== p) {
516
+ playlist.index = p;
517
+ }
518
+ else {
519
+ next();
520
+ }
521
+ };
522
+ switch (this.options.mode) {
523
+ case 'random':
524
+ random();
525
+ break;
526
+ case 'order':
527
+ next();
528
+ break;
529
+ case 'loop':
530
+ if (controller.step) {
531
+ next();
532
+ }
533
+ if (playlist.index === -1) {
534
+ random();
535
+ }
536
+ break;
537
+ }
538
+ this.init();
539
+ },
540
+ // 直接设置当前曲目index
541
+ switch(index) {
542
+ if (typeof index === 'number' &&
543
+ index !== playlist.index &&
544
+ playlist.current() &&
545
+ !playlist.current().error) {
546
+ playlist.index = index;
547
+ this.init();
548
+ }
549
+ },
550
+ // 更新source为当前曲目index
551
+ init() {
552
+ const item = playlist.current();
553
+ if (!item || item.error) {
554
+ this.mode();
555
+ return;
556
+ }
557
+ let playing = false;
558
+ if (!source.paused) {
559
+ playing = true;
560
+ this.stop();
561
+ }
562
+ source.attr('src', item.url);
563
+ source.attr('title', item.name + ' - ' + item.artist);
564
+ this.volume($storage.get('_PlayerVolume') || '0.7');
565
+ this.muted($storage.get('_PlayerMuted'));
566
+ progress.create();
567
+ if (this.options.type === 'audio') {
568
+ preview.create();
569
+ }
570
+ if (playing === true) {
571
+ this.play();
572
+ }
573
+ },
574
+ play() {
575
+ NOWPLAYING && NOWPLAYING.player.pause();
576
+ if (playlist.current().error) {
577
+ this.mode();
578
+ return;
579
+ }
580
+ source.play().then(() => {
581
+ playlist.scroll();
582
+ }).catch((e) => {
583
+ // 不处理错误
584
+ });
585
+ },
586
+ pause() {
587
+ source.pause();
588
+ document.title = originTitle;
589
+ },
590
+ stop() {
591
+ source.pause();
592
+ source.currentTime = 0;
593
+ document.title = originTitle;
594
+ },
595
+ seek(time) {
596
+ time = Math.max(time, 0);
597
+ time = Math.min(time, source.duration);
598
+ source.currentTime = time;
599
+ progress.update(time / source.duration);
600
+ },
601
+ muted(status) {
602
+ if (status === 'muted') {
603
+ source.muted = status;
604
+ $storage.set('_PlayerMuted', status);
605
+ controller.update(0);
606
+ }
607
+ else {
608
+ $storage.del('_PlayerMuted');
609
+ source.muted = false;
610
+ controller.update(source.volume);
611
+ }
612
+ },
613
+ volume(percentage) {
614
+ if (!isNaN(percentage)) {
615
+ controller.update(percentage);
616
+ $storage.set('_PlayerVolume', percentage);
617
+ source.volume = percentage;
618
+ }
619
+ },
620
+ mini() {
621
+ info.hide();
622
+ }
623
+ };
624
+ const lyrics = {
625
+ el: null,
626
+ data: null,
627
+ index: 0,
628
+ create(box) {
629
+ const current = playlist.index;
630
+ // const that = this
631
+ const raw = playlist.current().lrc;
632
+ const callback = (body) => {
633
+ if (current !== playlist.index) {
634
+ return;
635
+ }
636
+ this.data = this.parse(body);
637
+ let lrc = '';
638
+ this.data.forEach((line, index) => {
639
+ lrc += '<p' + (index === 0 ? ' class="current"' : '') + '>' + line[1] + '</p>';
640
+ });
641
+ this.el = box.createChild('div', {
642
+ className: 'inner',
643
+ innerHTML: lrc
644
+ }, 'replace');
645
+ this.index = 0;
646
+ };
647
+ if (raw.startsWith('http')) {
648
+ this.fetch(raw, callback);
649
+ }
650
+ else {
651
+ callback(raw);
652
+ }
653
+ },
654
+ update(currentTime) {
655
+ if (!this.data) {
656
+ return;
657
+ }
658
+ if (this.index > this.data.length - 1 || currentTime < this.data[this.index][0] || (!this.data[this.index + 1] || currentTime >= this.data[this.index + 1][0])) {
659
+ for (let i = 0; i < this.data.length; i++) {
660
+ if (currentTime >= this.data[i][0] && (!this.data[i + 1] || currentTime < this.data[i + 1][0])) {
661
+ this.index = i;
662
+ const y = -(this.index - 1);
663
+ this.el.style.transform = 'translateY(' + y + 'rem)';
664
+ // this.el.style.webkitTransform = 'translateY(' + y + 'rem)';
665
+ this.el.getElementsByClassName('current')[0].removeClass('current');
666
+ this.el.getElementsByTagName('p')[i].addClass('current');
667
+ }
668
+ }
669
+ }
670
+ },
671
+ parse(lrc_s) {
672
+ if (lrc_s) {
673
+ lrc_s = lrc_s.replace(/([^\]^\n])\[/g, (match, p1) => {
674
+ return p1 + '\n[';
675
+ });
676
+ const lyric = lrc_s.split('\n');
677
+ let lrc = [];
678
+ const lyricLen = lyric.length;
679
+ for (let i = 0; i < lyricLen; i++) {
680
+ // match lrc time
681
+ const lrcTimes = lyric[i].match(/\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g);
682
+ // match lrc text
683
+ const lrcText = lyric[i]
684
+ .replace(/.*\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g, '')
685
+ .replace(/<(\d{2}):(\d{2})(\.(\d{2,3}))?>/g, '')
686
+ .trim();
687
+ if (lrcTimes) {
688
+ // handle multiple time tag
689
+ const timeLen = lrcTimes.length;
690
+ for (let j = 0; j < timeLen; j++) {
691
+ const oneTime = /\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/.exec(lrcTimes[j]);
692
+ const min2sec = oneTime[1] * 60;
693
+ const sec2sec = parseInt(oneTime[2]);
694
+ const msec2sec = oneTime[4] ? parseInt(oneTime[4]) / ((oneTime[4] + '').length === 2 ? 100 : 1000) : 0;
695
+ const lrcTime = min2sec + sec2sec + msec2sec;
696
+ lrc.push([lrcTime, lrcText]);
697
+ }
698
+ }
699
+ }
700
+ // sort by time
701
+ lrc = lrc.filter((item) => item[1]);
702
+ lrc.sort((a, b) => a[0] - b[0]);
703
+ return lrc;
704
+ }
705
+ else {
706
+ return [];
707
+ }
708
+ },
709
+ fetch(url, callback) {
710
+ fetch(url)
711
+ .then((response) => {
712
+ return response.text();
713
+ }).then((body) => {
714
+ callback(body);
715
+ }).catch((ex) => {
716
+ // 不处理错误
717
+ });
718
+ }
719
+ };
720
+ const events = {
721
+ onerror() {
722
+ playlist.error();
723
+ t.player.mode();
724
+ },
725
+ ondurationchange() {
726
+ if (source.duration !== 1) {
727
+ progress.el.attr('data-dtime', utils.secondToTime(source.duration));
728
+ }
729
+ },
730
+ onloadedmetadata() {
731
+ t.player.seek(0);
732
+ progress.el.attr('data-dtime', utils.secondToTime(source.duration));
733
+ },
734
+ onplay() {
735
+ t.parentNode.addClass('playing');
736
+ showtip(this.attr('title'));
737
+ NOWPLAYING = t;
738
+ },
739
+ onpause() {
740
+ t.parentNode.removeClass('playing');
741
+ NOWPLAYING = null;
742
+ },
743
+ ontimeupdate() {
744
+ if (!this.disableTimeupdate) {
745
+ progress.update(this.currentTime / this.duration);
746
+ lyrics.update(this.currentTime);
747
+ }
748
+ },
749
+ onended(argument) {
750
+ t.player.mode();
751
+ t.player.play();
752
+ }
753
+ };
754
+ const init = (config) => {
755
+ if (t.player.created) {
756
+ return;
757
+ }
758
+ t.player.options = Object.assign(option, config);
759
+ t.player.options.mode = $storage.get('_PlayerMode') || t.player.options.mode;
760
+ // 初始化button、controls以及click事件
761
+ buttons.create();
762
+ // 初始化audio or video
763
+ source = t.createChild(t.player.options.type, events);
764
+ // 初始化播放列表、预览、控件按钮等
765
+ info.create();
766
+ t.parentNode.addClass(t.player.options.type);
767
+ t.player.created = true;
768
+ };
769
+ init(config);
770
+ return t;
771
+ };