hexo-theme-shokax 0.5.0-dev-f96faf9 → 0.5.0-dev-d82f54b

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.
package/README.md CHANGED
@@ -10,9 +10,8 @@
10
10
  - [ ] 引入新的工作流程
11
11
  - [ ] 重构 player (暂时移除)
12
12
  - [ ] 重构并修改代码块
13
- - [ ] 优化 menu 配置格式
14
- - [ ] 优化和异步化 Smart Bundle 技术
15
- - [ ] 优化 CSS 结构和加载
13
+ - [x] 优化和异步化 Smart Bundle 技术
14
+ - [x] 优化 CSS 结构和加载
16
15
  - [x] 修复/重置 fancybox
17
16
  - [ ] 修复模板长期遗留问题
18
17
  - [ ] 修复 images 遗留问题
package/_config.yml CHANGED
@@ -331,10 +331,9 @@ creative_commons:
331
331
  # bgm
332
332
  # 不使用请打开noplayer功能
333
333
  audio:
334
- # - title: 列表1
335
- # list:
336
- # - https://music.163.com/#/playlist?id=2943811283
337
- # - https://music.163.com/#/playlist?id=2297706586
334
+ - title: 列表1
335
+ list:
336
+ - https://music.163.com/#/playlist?id=2943811283
338
337
  # - title: 列表2
339
338
  # list:
340
339
  # - https://music.163.com/#/playlist?id=2031842656
@@ -1,9 +1,8 @@
1
1
  mixin CardRender(item)
2
- - cover = url_for(theme.statics + item.slug + this.getCoverExt(item.slug))
3
2
  - itemname = item.name
4
3
 
5
4
  section(class="item")
6
- div(class="cover" data-background-image!=cover ? cover:"")
5
+ div(class="cover" data-background-image=`${theme.statics}${item.slug}/cover.${getCoverExt(item.slug)}`)
7
6
  h2(class="title")
8
7
  != itemname
9
8
  - var temp = item?.top?.name
@@ -1,5 +1,4 @@
1
1
  mixin CommentRender()
2
- != shokax_inject('comment')
3
2
  if page.comment !== false
4
3
  div(class="wrap" id="comments")
5
4
 
@@ -37,7 +37,4 @@ div(class="status")
37
37
  a(target="_blank" href=`https://beian.mps.gov.cn/#/query/webSearch?code=${RC}`)
38
38
  img(loading="lazy" decoding="async" data-src=theme.statics + theme.assets + '/' + theme.footer.icp.icon style="max-width: 2em;display:inline;" width="20" height="20" alt="备案")
39
39
  != beianN
40
- != shokax_inject('status')
41
-
42
- != shokax_inject('footer')
43
40
 
@@ -14,5 +14,4 @@ nav(id="nav")
14
14
  i(class="ic i-sun")
15
15
  li(class="item search")
16
16
  i(class="ic i-search")
17
- != shokax_inject('rightNav')
18
17
 
@@ -21,7 +21,6 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f
21
21
  link(rel="preload" href!=covers as="image" fetchpriority="high")
22
22
 
23
23
  != partial('_partials/head/head_com.pug')
24
- != shokax_inject('head')
25
24
  block head
26
25
  title
27
26
  block title
@@ -75,6 +74,8 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f
75
74
  block sidebar
76
75
  +sidebarRender
77
76
  div(class="dimmer")
77
+ div(id="player")
78
+ button(id="showBtn") 11111
78
79
  footer(id="footer")
79
80
  div(class="inner")
80
81
  div(class="widgets")
@@ -140,6 +141,4 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f
140
141
 
141
142
  != _js('siteInit.js')
142
143
 
143
- != shokax_inject('bodyEnd')
144
-
145
144
 
@@ -16,5 +16,3 @@ div(class="meta")
16
16
  != __('post.edited') + __('symbol.space')
17
17
  time(title=__('post.modified') + __('symbol.colon') + full_date(post.updated) itemprop="dateModified" datetime=moment(post.updated).format())
18
18
  != date(post.updated)
19
-
20
- != shokax_inject('postMeta')
@@ -38,4 +38,3 @@ article(itemscope itemtype="http://schema.org/Article" class="post block" lang=t
38
38
  != partial('_partials/post/reward.pug', {}, {cache: true})
39
39
  if theme.creative_commons.license
40
40
  != partial('_partials/post/copyright.pug')
41
- != shokax_inject('postBodyEnd')
@@ -36,7 +36,5 @@ div(class="social")
36
36
  - var sidebarIcon = '<i class="ic i-' + link.split('||')[1].trim() + '"></i>'
37
37
  != _url(sidebarURL, sidebarIcon, {title: sidebarURL, class: 'item ' + name})
38
38
 
39
- != shokax_inject('sidebar')
40
-
41
39
  div(class="menu")
42
40
  != partial('_partials/sidebar/menu.pug')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-shokax",
3
- "version": "0.5.0-dev-f96faf9",
3
+ "version": "0.5.0-dev-d82f54b",
4
4
  "description": "a hexo theme based on shoka",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/theme-shoka-x/hexo-theme-shokaX",
@@ -45,6 +45,7 @@
45
45
  "js-yaml": "^4.1.0",
46
46
  "katex": "^0.16.21",
47
47
  "mouse-firework": "^0.1.1",
48
+ "nyx-player": "^0.0.1",
48
49
  "quicklink": "^2.3.0",
49
50
  "theme-shokax-anime": "^0.0.8",
50
51
  "theme-shokax-pjax": "^0.0.3",
@@ -33,6 +33,7 @@ hexo.config.index_generator = Object.assign({
33
33
  order_by: "-date"
34
34
  }, hexo.config.index_generator);
35
35
  hexo.extend.helper.register("getCoverExt", function(path) {
36
+ const theme = hexo.theme.config;
36
37
  if (theme.homeConfig.cateCards.length > 0) {
37
38
  const cardMap = /* @__PURE__ */ new Map();
38
39
  theme.homeConfig.cateCards.forEach((card) => {
@@ -44,7 +45,7 @@ hexo.extend.helper.register("getCoverExt", function(path) {
44
45
  }
45
46
  }
46
47
  });
47
- hexo.extend.generator.register("index", function(locals) {
48
+ hexo.extend.generator.register("index", async function(locals) {
48
49
  const covers = [];
49
50
  const catlist = [];
50
51
  let pages;
@@ -54,7 +55,7 @@ hexo.extend.generator.register("index", function(locals) {
54
55
  const paginationDir = config.pagination_dir || "page";
55
56
  const path = config.index_generator.path || "";
56
57
  const categories = locals.categories;
57
- const theme2 = hexo.theme.config;
58
+ const theme = hexo.theme.config;
58
59
  const getTopcat = function(cat) {
59
60
  if (cat.parent) {
60
61
  const pCat = categories.findOne({ _id: cat.parent });
@@ -64,42 +65,44 @@ hexo.extend.generator.register("index", function(locals) {
64
65
  }
65
66
  };
66
67
  if (categories && categories.length) {
67
- categories.forEach(async (cat) => {
68
- const cover = `source/_posts/${cat.slug}`;
69
- if (theme2.homeConfig.cateCards.length > 0) {
70
- const cardMap = /* @__PURE__ */ new Map();
71
- theme2.homeConfig.cateCards.forEach((card) => {
72
- cardMap.set(card.slug, card.cover);
73
- });
74
- if (cardMap.has(cat.slug)) {
75
- const cover2 = cardMap.get(cat.slug);
76
- const coverData = await (0, import_promises.readFile)(`source/_posts/${cover2}`);
77
- covers.push({
78
- path: `${cat.slug}/cover.${getFileExtension(cover2)}`,
79
- data: coverData
68
+ await Promise.all(
69
+ categories.map(async (cat) => {
70
+ const cover = `source/_posts/${cat.slug}`;
71
+ if (theme.homeConfig.cateCards.length > 0) {
72
+ const cardMap = /* @__PURE__ */ new Map();
73
+ theme.homeConfig.cateCards.forEach((card) => {
74
+ cardMap.set(card.slug, card.cover);
80
75
  });
81
- const topcat = getTopcat(cat);
82
- if (topcat._id !== cat._id) {
83
- cat.top = topcat;
84
- }
85
- const child = categories.find({ parent: cat._id });
86
- let pl = 6;
87
- if (child.length !== 0) {
88
- cat.child = child.length;
89
- cat.subs = child.sort({ name: 1 }).limit(6).toArray();
90
- pl = Math.max(0, pl - child.length);
91
- if (pl > 0) {
92
- cat.subs.push(...cat.posts.sort({ title: 1 }).filter(function(item, i) {
93
- return item.categories.last()._id === cat._id;
94
- }).limit(pl).toArray());
76
+ if (cardMap.has(cat.slug)) {
77
+ const cover2 = cardMap.get(cat.slug);
78
+ const coverData = await (0, import_promises.readFile)(`source/_posts/${cover2}`);
79
+ covers.push({
80
+ path: `${cat.slug}/cover.${getFileExtension(cover2)}`,
81
+ data: coverData
82
+ });
83
+ const topcat = getTopcat(cat);
84
+ if (topcat._id !== cat._id) {
85
+ cat.top = topcat;
86
+ }
87
+ const child = categories.find({ parent: cat._id });
88
+ let pl = 6;
89
+ if (child.length !== 0) {
90
+ cat.child = child.length;
91
+ cat.subs = child.sort({ name: 1 }).limit(6).toArray();
92
+ pl = Math.max(0, pl - child.length);
93
+ if (pl > 0) {
94
+ cat.subs.push(...cat.posts.sort({ title: 1 }).filter(function(item, i) {
95
+ return item.categories.last()._id === cat._id;
96
+ }).limit(pl).toArray());
97
+ }
98
+ } else {
99
+ cat.subs = cat.posts.sort({ title: 1 }).limit(6).toArray();
95
100
  }
96
- } else {
97
- cat.subs = cat.posts.sort({ title: 1 }).limit(6).toArray();
101
+ catlist.push(cat);
98
102
  }
99
- catlist.push(cat);
100
103
  }
101
- }
102
- });
104
+ })
105
+ );
103
106
  }
104
107
  if (posts.length > 0) {
105
108
  pages = (0, import_hexo_pagination.default)(path, posts, {
@@ -156,6 +156,3 @@ hexo.extend.helper.register("random_color", function() {
156
156
  const [r, g, b] = arr;
157
157
  return `#${r.toString(16).length > 1 ? r.toString(16) : "0" + r.toString(16)}${g.toString(16).length > 1 ? g.toString(16) : "0" + g.toString(16)}${b.toString(16).length > 1 ? b.toString(16) : "0" + b.toString(16)}`;
158
158
  });
159
- hexo.extend.helper.register("shokax_inject", function(point) {
160
- return hexo.theme.config.injects[point].map((item) => this.partial(item.layout, item.locals, item.options)).join("");
161
- });
@@ -59,7 +59,8 @@ export const sideBarTab = () => {
59
59
  const text = document.createTextNode(element.getAttribute('data-title'))
60
60
  span.appendChild(text)
61
61
  tab.appendChild(span)
62
- tab.classList.add(item + ' item')
62
+ tab.classList.add(item)
63
+ tab.classList.add('item')
63
64
 
64
65
  if (active) {
65
66
  element.classList.add(active)
@@ -1,799 +1,12 @@
1
- // 临时性弃用,等待重构
2
-
3
- import { CONFIG, originTitle } from './globals/globalVars'
4
- import { showtip } from './globals/tools'
5
- import { pageScroll } from './library/anime'
6
- import { tabFormat } from './page/tab'
7
- import { createChild, getLeft, getWidth, setDisplay, setWidth } from './library/proto'
8
-
9
- let NOWPLAYING = null
10
-
11
- const isMobile = /mobile/i.test(window.navigator.userAgent)
12
- export const mediaPlayer = (t, config?) => {
13
- const buttons = {
14
- el: {},
15
- create () {
16
- if (!t.player.options.btns) { return }
17
- t.player.options.btns.forEach((item) => {
18
- if (buttons.el[item]) { return }
19
-
20
- buttons.el[item] = createChild(t, '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) { return }
40
-
41
- const that = controller
42
- t.player.options.controls.forEach((item) => {
43
- if (that.btns[item]) { return }
44
-
45
- const opt = <HTMLElement> {
46
- onclick (event) {
47
- that.events[item] ? that.events[item](event) : t.player.options.events[item](event)
48
- }
49
- }
50
-
51
- switch (item) {
52
- case 'volume':
53
- opt.className = ' ' + (source.muted ? 'off' : 'on')
54
- opt.innerHTML = '<div class="bar"></div>'
55
- opt['on' + utils.nameMap.dragStart] = that.events.volume
56
- opt.onclick = null
57
- break
58
- case 'mode':
59
- opt.className = ' ' + t.player.options.mode
60
- break
61
- default:
62
- opt.className = ''
63
- break
64
- }
65
-
66
- opt.className = item + opt.className + ' btn'
67
-
68
- that.btns[item] = createChild(that.el, 'div', opt)
69
- })
70
-
71
- that.btns.volume.bar = that.btns.volume.querySelector('.bar')
72
- },
73
- events: {
74
- mode (e) {
75
- switch (t.player.options.mode) {
76
- case 'loop':
77
- t.player.options.mode = 'random'
78
- break
79
- case 'random':
80
- t.player.options.mode = 'order'
81
- break
82
- default:
83
- t.player.options.mode = 'loop'
84
- }
85
-
86
- controller.btns.mode.className = 'mode ' + t.player.options.mode + ' btn'
87
- localStorage.setItem('_PlayerMode', t.player.options.mode)
88
- },
89
- volume (e) {
90
- e.preventDefault()
91
-
92
- const current = e.currentTarget
93
-
94
- let drag = false
95
-
96
- const thumbMove = (e) => {
97
- e.preventDefault()
98
- t.player.volume(controller.percent(e, current))
99
- drag = true
100
- }
101
-
102
- const thumbUp = (e) => {
103
- e.preventDefault()
104
- current.removeEventListener(utils.nameMap.dragEnd, thumbUp)
105
- current.removeEventListener(utils.nameMap.dragMove, thumbMove)
106
- if (drag) {
107
- t.player.muted()
108
- t.player.volume(controller.percent(e, current))
109
- } else {
110
- if (source.muted) {
111
- t.player.muted()
112
- t.player.volume(source.volume)
113
- } else {
114
- t.player.muted('muted')
115
- controller.update(0)
116
- }
117
- }
118
- }
119
-
120
- current.addEventListener(utils.nameMap.dragMove, thumbMove)
121
- current.addEventListener(utils.nameMap.dragEnd, thumbUp)
122
- },
123
- backward (e) {
124
- controller.step = 'prev'
125
- t.player.mode()
126
- },
127
- forward (e) {
128
- controller.step = 'next'
129
- t.player.mode()
130
- }
131
- },
132
- update (percent) {
133
- controller.btns.volume.className = 'volume ' + (!source.muted && percent > 0 ? 'on' : 'off') + ' btn'
134
- setWidth(controller.btns.volume.bar, Math.floor(percent * 100) + '%')
135
- },
136
- percent (e, el) {
137
- let percentage = ((e.clientX || e.changedTouches[0].clientX) - getLeft(el)) / getWidth(el)
138
- percentage = Math.max(percentage, 0)
139
- return Math.min(percentage, 1)
140
- }
141
- }
142
- const progress = {
143
- el: null,
144
- bar: null,
145
- create () {
146
- const current = playlist.current().el
147
-
148
- if (current) {
149
- if (progress.el) {
150
- progress.el.parentNode.classList.remove('current')
151
- .removeEventListener(utils.nameMap.dragStart, progress.drag)
152
- progress.el.remove()
153
- }
154
-
155
- progress.el = createChild(current, 'div', {
156
- className: 'progress'
157
- });
158
-
159
- (progress.el as HTMLElement).setAttribute('data-dtime', utils.secondToTime(0))
160
-
161
- progress.bar = createChild(progress.el, 'div', {
162
- className: 'bar'
163
- })
164
-
165
- current.classList.add('current')
166
-
167
- current.addEventListener(utils.nameMap.dragStart, progress.drag)
168
-
169
- playlist.scroll()
170
- }
171
- },
172
- update (percent) {
173
- setWidth(progress.bar, Math.floor(percent * 100) + '%');
174
- (progress.el as HTMLElement).setAttribute('data-ptime', utils.secondToTime(percent * source.duration))
175
- },
176
- seeking (type) {
177
- if (type) { progress.el.classList.add('seeking') } else { progress.el.classList.remove('seeking') }
178
- },
179
- percent (e, el) {
180
- let percentage = ((e.clientX || e.changedTouches[0].clientX) - getLeft(el)) / getWidth(el)
181
- percentage = Math.max(percentage, 0)
182
- return Math.min(percentage, 1)
183
- },
184
- drag (e) {
185
- e.preventDefault()
186
-
187
- const current = playlist.current().el
188
-
189
- const thumbMove = (e) => {
190
- e.preventDefault()
191
- const percentage = progress.percent(e, current)
192
- progress.update(percentage)
193
- lyrics.update(percentage * source.duration)
194
- }
195
-
196
- const thumbUp = (e) => {
197
- e.preventDefault()
198
- current.removeEventListener(utils.nameMap.dragEnd, thumbUp)
199
- current.removeEventListener(utils.nameMap.dragMove, thumbMove)
200
- const percentage = progress.percent(e, current)
201
- progress.update(percentage)
202
- t.player.seek(percentage * source.duration)
203
- source.disableTimeupdate = false
204
- progress.seeking(false)
205
- }
206
-
207
- source.disableTimeupdate = true
208
- progress.seeking(true)
209
- current.addEventListener(utils.nameMap.dragMove, thumbMove)
210
- current.addEventListener(utils.nameMap.dragEnd, thumbUp)
211
- }
212
- }
213
- const preview = {
214
- el: null,
215
- create () {
216
- const current = playlist.current()
217
-
218
- preview.el.innerHTML = '<div class="cover"><div class="disc"><img src="' + (current.cover) + '" class="blur" alt="music cover"/></div></div>' +
219
- '<div class="info"><h4 class="title">' + current.name + '</h4><span>' + current.artist + '</span>' +
220
- '<div class="lrc"></div></div>';
221
-
222
- (preview.el as HTMLElement).querySelector('.cover').addEventListener('click', t.player.options.events['play-pause'])
223
-
224
- lyrics.create((preview.el as HTMLElement).querySelector('.lrc'))
225
- }
226
- }
227
- let source
228
- const playlist = {
229
- el: null,
230
- data: [],
231
- index: -1,
232
- errnum: 0,
233
- add: (group, list) => {
234
- list.forEach((item) => {
235
- item.group = group
236
- item.name = item.name || item.title || 'Meida name'
237
- item.artist = item.artist || item.author || 'Anonymous'
238
- item.cover = item.cover || item.pic
239
- item.type = item.type || 'normal'
240
-
241
- playlist.data.push(item)
242
- })
243
- },
244
- clear () {
245
- playlist.data = []
246
- playlist.el.innerHTML = ''
247
-
248
- if (playlist.index !== -1) {
249
- playlist.index = -1
250
- t.player.fetch()
251
- }
252
- },
253
- create () {
254
- const el = playlist.el
255
-
256
- playlist.data.map((item, index) => {
257
- if (item.el) { return null }
258
-
259
- const id = 'list-' + t.player._id + '-' + item.group
260
- let tab = document.getElementById(id)
261
- if (!tab) {
262
- tab = createChild(el, 'div', {
263
- id,
264
- className: t.player.group ? 'tab' : '',
265
- innerHTML: '<ol></ol>'
266
- })
267
- if (t.player.group) {
268
- tab.setAttribute('data-title', t.player.options.rawList[item.group].title)
269
- tab.setAttribute('data-id', t.player._id)
270
- }
271
- }
272
-
273
- item.el = createChild(tab.querySelector('ol'), 'li', {
274
- title: item.name + ' - ' + item.artist,
275
- innerHTML: '<span class="info"><span>' + item.name + '</span><span>' + item.artist + '</span></span>',
276
- onclick (event) {
277
- const current = event.currentTarget
278
- if (playlist.index === index && progress.el) {
279
- if (source.paused) {
280
- t.player.play()
281
- } else {
282
- t.player.seek(source.duration * progress.percent(event, current))
283
- }
284
- return
285
- }
286
- t.player.switch(index)
287
- t.player.play()
288
- }
289
- })
290
-
291
- return item
292
- })
293
- if (__shokax_tabs__) {
294
- tabFormat()
295
- }
296
- },
297
- current () {
298
- return this.data[this.index]
299
- },
300
- scroll () {
301
- const item = this.current()
302
- let li = this.el.querySelector('li.active')
303
- li && li.classList.remove('active')
304
- let tab = this.el.querySelector('.tab.active')
305
- tab && tab.classList.remove('active')
306
- li = this.el.querySelectorAll('.nav li')[item.group]
307
- li && li.classList.add('active')
308
- tab = this.el.querySelectorAll('.tab')[item.group]
309
- tab && tab.classList.add('active')
310
-
311
- pageScroll(item.el, item.el.offsetTop)
312
-
313
- return this
314
- },
315
- title () {
316
- if (source.paused) { return }
317
-
318
- const current = this.current()
319
- document.title = 'Now Playing...' + current.name + ' - ' + current.artist + ' | ' + originTitle
320
- },
321
- error () {
322
- const current = this.current()
323
- current.el.classList.remove('current').classList.add('error')
324
- current.error = true
325
- this.errnum++
326
- }
327
- }
328
- const info = {
329
- el: null,
330
- create () {
331
- if (this.el) { return }
332
-
333
- this.el = createChild(t, 'div', {
334
- className: 'player-info',
335
- innerHTML: (t.player.options.type === 'audio' ? '<div class="preview"></div>' : '') + '<div class="controller"></div><div class="playlist"></div>'
336
- }, 'after')
337
-
338
- preview.el = this.el.querySelector('.preview')
339
- playlist.el = this.el.querySelector('.playlist')
340
- controller.el = this.el.querySelector('.controller')
341
- },
342
- hide () {
343
- const el = this.el
344
- el.classList.add('hide')
345
- window.setTimeout(() => {
346
- el.classList.remove('show hide')
347
- }, 300)
348
- }
349
- }
350
- const option = {
351
- type: 'audio',
352
- mode: 'random',
353
- btns: ['play-pause', 'music'],
354
- controls: ['mode', 'backward', 'play-pause', 'forward', 'volume'],
355
- events: {
356
- 'play-pause' (event) {
357
- if (source.paused) {
358
- t.player.play()
359
- } else {
360
- t.player.pause()
361
- }
362
- },
363
- music (event) {
364
- if (info.el.classList.contains('show')) {
365
- info.hide()
366
- } else {
367
- info.el.classList.add('show')
368
- playlist.scroll().title()
369
- }
370
- }
371
- }
372
- }
373
- const utils = {
374
- random (len) {
375
- return Math.floor((Math.random() * len))
376
- },
377
- parse (link) {
378
- let result = [];
379
- [
380
- ['music.163.com.*song.*id=(\\d+)', 'netease', 'song'],
381
- ['music.163.com.*album.*id=(\\d+)', 'netease', 'album'],
382
- ['music.163.com.*artist.*id=(\\d+)', 'netease', 'artist'],
383
- ['music.163.com.*playlist.*id=(\\d+)', 'netease', 'playlist'],
384
- ['music.163.com.*discover/toplist.*id=(\\d+)', 'netease', 'playlist'],
385
- ['y.qq.com.*song/(\\w+)(.html)?', 'tencent', 'song'],
386
- ['y.qq.com.*album/(\\w+)(.html)?', 'tencent', 'album'],
387
- ['y.qq.com.*singer/(\\w+)(.html)?', 'tencent', 'artist'],
388
- ['y.qq.com.*playsquare/(\\w+)(.html)?', 'tencent', 'playlist'],
389
- ['y.qq.com.*playlist/(\\w+)(.html)?', 'tencent', 'playlist'],
390
- ['xiami.com.*song/(\\w+)', 'xiami', 'song'],
391
- ['xiami.com.*album/(\\w+)', 'xiami', 'album'],
392
- ['xiami.com.*artist/(\\w+)', 'xiami', 'artist'],
393
- ['xiami.com.*collect/(\\w+)', 'xiami', 'playlist']
394
- ].forEach((rule) => {
395
- const patt = new RegExp(rule[0])
396
- const res = patt.exec(link)
397
- if (res !== null) {
398
- result = [rule[1], rule[2], res[1]]
399
- }
400
- })
401
- return result
402
- },
403
- fetch (source) {
404
- const list = []
405
-
406
- return new Promise((resolve, reject) => {
407
- source.forEach((raw) => {
408
- const meta = utils.parse(raw)
409
- if (meta[0]) {
410
- const skey = JSON.stringify(meta)
411
- const playlist = localStorage.getItem(skey)
412
- if (playlist) {
413
- // list.push.apply(list, JSON.parse(playlist))
414
- list.push(...JSON.parse(playlist))
415
- resolve(list)
416
- } else {
417
- fetch(`${CONFIG.playerAPI}/meting/?server=` + meta[0] + '&type=' + meta[1] + '&id=' + meta[2] + '&r=' + Math.random())
418
- .then((response) => {
419
- return response.json()
420
- }).then((json) => {
421
- localStorage.setItem(skey, JSON.stringify(json))
422
- // list.push.apply(list, json)
423
- list.push(...json)
424
- resolve(list)
425
- }).catch((ex) => {
426
- // (不)处理catch的异常
427
- })
428
- }
429
- } else {
430
- list.push(raw)
431
- resolve(list)
432
- }
433
- })
434
- })
435
- },
436
- secondToTime (second) {
437
- const add0 = (num) => {
438
- return isNaN(num) ? '00' : (num < 10 ? '0' + num : '' + num)
439
- }
440
- const hour = Math.floor(second / 3600)
441
- const min = Math.floor((second - hour * 3600) / 60)
442
- const sec = Math.floor(second - hour * 3600 - min * 60)
443
- return (hour > 0 ? [hour, min, sec] : [min, sec]).map(add0).join(':')
444
- },
445
- nameMap: {
446
- dragStart: isMobile ? 'touchstart' : 'mousedown',
447
- dragMove: isMobile ? 'touchmove' : 'mousemove',
448
- dragEnd: isMobile ? 'touchend' : 'mouseup'
449
- }
450
- }
451
- source = null
452
-
453
- t.player = {
454
- _id: utils.random(999999),
455
- group: true,
456
- // 加载播放列表
457
- load (newList) {
458
- let d = ''
459
-
460
- if (newList && newList.length > 0) {
461
- if (this.options.rawList !== newList) {
462
- this.options.rawList = newList
463
- playlist.clear()
464
- // 获取新列表
465
- this.fetch()
466
- }
467
- } else {
468
- // 没有列表时,隐藏按钮
469
- d = 'none'
470
- this.pause()
471
- }
472
- for (const el in buttons.el) {
473
- setDisplay(buttons.el[el], d)
474
- }
475
- return this
476
- },
477
- fetch () {
478
- return new Promise<boolean>((resolve, reject) => {
479
- if (playlist.data.length > 0) {
480
- resolve(false)
481
- } else {
482
- if (this.options.rawList) {
483
- const promises = []
484
-
485
- this.options.rawList.forEach((raw, index) => {
486
- promises.push(new Promise((resolve, reject) => {
487
- let group = index
488
- let source
489
- if (!raw.list) {
490
- group = 0
491
- this.group = false
492
- source = [raw]
493
- } else {
494
- this.group = true
495
- source = raw.list
496
- }
497
- utils.fetch(source).then((list) => {
498
- playlist.add(group, list)
499
- resolve(0)
500
- })
501
- }))
502
- })
503
-
504
- Promise.all(promises).then(() => {
505
- resolve(true)
506
- })
507
- }
508
- }
509
- }).then((c) => {
510
- if (c) {
511
- playlist.create()
512
- controller.create()
513
- this.mode()
514
- }
515
- })
516
- },
517
- // 根据模式切换当前曲目index
518
- mode () {
519
- const total = playlist.data.length
520
-
521
- if (!total || playlist.errnum === total) { return }
522
-
523
- const step = controller.step === 'next' ? 1 : -1
524
-
525
- const next = () => {
526
- let index = playlist.index + step
527
- if (index > total || index < 0) {
528
- index = controller.step === 'next' ? 0 : total - 1
529
- }
530
- playlist.index = index
531
- }
532
-
533
- const random = () => {
534
- const p = utils.random(total)
535
- if (playlist.index !== p) {
536
- playlist.index = p
537
- } else {
538
- next()
539
- }
540
- }
541
-
542
- switch (this.options.mode) {
543
- case 'random':
544
- random()
545
- break
546
- case 'order':
547
- next()
548
- break
549
- case 'loop':
550
- if (controller.step) { next() }
551
-
552
- if (playlist.index === -1) { random() }
553
- break
554
- }
555
-
556
- this.init()
557
- },
558
- // 直接设置当前曲目index
559
- switch (index) {
560
- if (typeof index === 'number' &&
561
- index !== playlist.index &&
562
- playlist.current() &&
563
- !playlist.current().error) {
564
- playlist.index = index
565
- this.init()
566
- }
567
- },
568
- // 更新source为当前曲目index
569
- init () {
570
- const item = playlist.current()
571
-
572
- if (!item || item.error) {
573
- this.mode()
574
- return
575
- }
576
-
577
- let playing = false
578
- if (!source.paused) {
579
- playing = true
580
- this.stop()
581
- }
582
-
583
- source.setAttribute('src', item.url)
584
- source.setAttribute('title', item.name + ' - ' + item.artist)
585
- this.volume(localStorage.getItem('_PlayerVolume') || '0.7')
586
- this.muted(localStorage.getItem('_PlayerMuted'))
587
-
588
- progress.create()
589
-
590
- if (this.options.type === 'audio') { preview.create() }
591
-
592
- if (playing === true) {
593
- this.play()
594
- }
595
- },
596
- play () {
597
- NOWPLAYING && NOWPLAYING.player.pause()
598
-
599
- if (playlist.current().error) {
600
- this.mode()
601
- return
602
- }
603
- source.play().then(() => {
604
- playlist.scroll()
605
- }).catch((e) => {
606
- // 不处理错误
607
- })
608
- },
609
- pause () {
610
- source.pause()
611
- document.title = originTitle
612
- },
613
- stop () {
614
- source.pause()
615
- source.currentTime = 0
616
- document.title = originTitle
617
- },
618
- seek (time) {
619
- time = Math.max(time, 0)
620
- time = Math.min(time, source.duration)
621
- source.currentTime = time
622
- progress.update(time / source.duration)
623
- },
624
- muted (status?) {
625
- if (status === 'muted') {
626
- source.muted = status
627
- localStorage.setItem('_PlayerMuted', status)
628
- controller.update(0)
629
- } else {
630
- localStorage.removeItem('_PlayerMuted')
631
- source.muted = false
632
- controller.update(source.volume)
633
- }
634
- },
635
- volume (percentage) {
636
- if (!isNaN(percentage)) {
637
- controller.update(percentage)
638
- localStorage.setItem('_PlayerVolume', percentage)
639
- source.volume = percentage
640
- }
641
- },
642
- mini () {
643
- info.hide()
644
- }
645
- }
646
-
647
- const lyrics = {
648
- el: null,
649
- data: null,
650
- index: 0,
651
- create (box) {
652
- const current = playlist.index
653
- // const that = this
654
- const raw = playlist.current().lrc
655
-
656
- const callback = (body) => {
657
- if (current !== playlist.index) { return }
658
-
659
- this.data = this.parse(body)
660
-
661
- let lrc = ''
662
- this.data.forEach((line, index) => {
663
- lrc += '<p' + (index === 0 ? ' class="current"' : '') + '>' + line[1] + '</p>'
664
- })
665
-
666
- this.el = createChild(box, 'div', {
667
- className: 'inner',
668
- innerHTML: lrc
669
- }, 'replace')
670
-
671
- this.index = 0
672
- }
673
-
674
- if (raw.startsWith('http')) { this.fetch(raw, callback) } else { callback(raw) }
675
- },
676
- update (currentTime) {
677
- if (!this.data) { return }
678
-
679
- 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])) {
680
- for (let i = 0; i < this.data.length; i++) {
681
- if (currentTime >= this.data[i][0] && (!this.data[i + 1] || currentTime < this.data[i + 1][0])) {
682
- this.index = i
683
- const y = -(this.index - 1)
684
- this.el.style.transform = 'translateY(' + y + 'rem)'
685
- // this.el.style.webkitTransform = 'translateY(' + y + 'rem)';
686
- this.el.getElementsByClassName('current')[0].classList.remove('current')
687
- this.el.getElementsByTagName('p')[i].classList.add('current')
688
- }
689
- }
690
- }
691
- },
692
- parse (lrc_s) {
693
- if (lrc_s) {
694
- lrc_s = lrc_s.replace(/([^\]^\n])\[/g, (match, p1) => {
695
- return p1 + '\n['
696
- })
697
- const lyric = lrc_s.split('\n')
698
- let lrc = []
699
- const lyricLen = lyric.length
700
- for (let i = 0; i < lyricLen; i++) {
701
- // match lrc time
702
- const lrcTimes = lyric[i].match(/\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g)
703
- // match lrc text
704
- const lrcText = lyric[i]
705
- .replace(/.*\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/g, '')
706
- .replace(/<(\d{2}):(\d{2})(\.(\d{2,3}))?>/g, '')
707
- .trim()
708
-
709
- if (lrcTimes) {
710
- // handle multiple time tag
711
- const timeLen = lrcTimes.length
712
- for (let j = 0; j < timeLen; j++) {
713
- const oneTime = /\[(\d{2}):(\d{2})(\.(\d{2,3}))?]/.exec(lrcTimes[j])
714
- const min2sec = <number><unknown> oneTime[1] * 60
715
- const sec2sec = parseInt(oneTime[2])
716
- const msec2sec = oneTime[4] ? parseInt(oneTime[4]) / ((oneTime[4] + '').length === 2 ? 100 : 1000) : 0
717
- const lrcTime = min2sec + sec2sec + msec2sec
718
- lrc.push([lrcTime, lrcText])
719
- }
720
- }
721
- }
722
- // sort by time
723
- lrc = lrc.filter((item) => item[1])
724
- lrc.sort((a, b) => a[0] - b[0])
725
- return lrc
726
- } else {
727
- return []
728
- }
729
- },
730
- fetch (url, callback) {
731
- fetch(url)
732
- .then((response) => {
733
- return response.text()
734
- }).then((body) => {
735
- callback(body)
736
- }).catch((ex) => {
737
- // 不处理错误
738
- })
739
- }
740
- }
741
-
742
- const events = {
743
- onerror () {
744
- playlist.error()
745
- t.player.mode()
746
- },
747
- ondurationchange () {
748
- if (source.duration !== 1) {
749
- progress.el.setAttribute('data-dtime', utils.secondToTime(source.duration))
750
- }
751
- },
752
- onloadedmetadata () {
753
- t.player.seek(0)
754
- progress.el.setAttribute('data-dtime', utils.secondToTime(source.duration))
755
- },
756
- onplay () {
757
- t.parentNode.classList.add('playing')
758
- showtip(this.getAttribute('title'))
759
- NOWPLAYING = t
760
- },
761
- onpause () {
762
- t.parentNode.classList.remove('playing')
763
- NOWPLAYING = null
764
- },
765
- ontimeupdate () {
766
- if (!this.disableTimeupdate) {
767
- progress.update(this.currentTime / this.duration)
768
- lyrics.update(this.currentTime)
769
- }
770
- },
771
- onended (argument) {
772
- t.player.mode()
773
- t.player.play()
774
- }
775
- }
776
-
777
- const init = (config) => {
778
- if (t.player.created) { return }
779
-
780
- t.player.options = Object.assign(option, config)
781
- t.player.options.mode = localStorage.getItem('_PlayerMode') || t.player.options.mode
782
-
783
- // 初始化button、controls以及click事件
784
- buttons.create()
785
-
786
- // 初始化audio or video
787
- source = createChild(t, t.player.options.type, events)
788
- // 初始化播放列表、预览、控件按钮等
789
- info.create()
790
-
791
- t.parentNode.classList.add(t.player.options.type)
792
-
793
- t.player.created = true
794
- }
795
-
796
- init(config)
797
-
798
- return t
799
- }
1
+ import { initPlayer } from 'nyx-player'
2
+ import { CONFIG } from './globals/globalVars'
3
+
4
+ const urls = []
5
+ CONFIG.audio.forEach((item) => {
6
+ urls.push({
7
+ name: item.title,
8
+ url: item.list[0]
9
+ })
10
+ })
11
+
12
+ initPlayer("#player","#showBtn", [])