hexo-theme-stellar 1.29.0 → 1.30.0

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.
Files changed (48) hide show
  1. package/_config.yml +29 -9
  2. package/_data/chat_users.yml +0 -0
  3. package/_data/widgets.yml +7 -0
  4. package/languages/zh-TW.yml +2 -2
  5. package/layout/_partial/head.ejs +2 -1
  6. package/layout/_partial/main/navbar/nav_tabs_blog.ejs +10 -10
  7. package/layout/_partial/scripts/defines.ejs +3 -0
  8. package/layout/_partial/scripts/services.ejs +91 -0
  9. package/layout/_partial/scripts/theme.ejs +5 -0
  10. package/layout/_partial/scripts/utils.ejs +67 -7
  11. package/layout/_partial/scripts.ejs +1 -1
  12. package/layout/_plugins/mermaid.ejs +1 -1
  13. package/layout/_plugins/scrollreveal.ejs +1 -0
  14. package/layout/_plugins/search/algolia_search.ejs +11 -12
  15. package/layout/layout.ejs +1 -1
  16. package/package.json +1 -1
  17. package/scripts/events/lib/config.js +3 -0
  18. package/scripts/events/lib/doc_tree.js +1 -6
  19. package/scripts/filters/index.js +26 -0
  20. package/scripts/generators/notebooks.js +1 -1
  21. package/scripts/generators/search.js +21 -2
  22. package/scripts/helpers/dynamic_color.js +138 -0
  23. package/scripts/tags/index.js +1 -0
  24. package/scripts/tags/lib/box.js +1 -1
  25. package/scripts/tags/lib/chat.js +515 -0
  26. package/scripts/tags/lib/folders.js +1 -1
  27. package/scripts/tags/lib/folding.js +2 -2
  28. package/scripts/tags/lib/sites.js +1 -1
  29. package/scripts/tags/lib/video.js +7 -2
  30. package/source/css/_components/tag-plugins/chat.styl +621 -0
  31. package/source/css/_components/tag-plugins/friends.styl +10 -0
  32. package/source/css/_components/tag-plugins/sites.styl +12 -0
  33. package/source/css/_components/tag-plugins/tabs.styl +5 -2
  34. package/source/css/_custom.styl +1 -0
  35. package/source/css/_defines/func.styl +7 -6
  36. package/source/css/_defines/theme.styl +38 -0
  37. package/source/css/_plugins/katex.styl +0 -1
  38. package/source/js/plugins/download-file.js +198 -0
  39. package/source/js/plugins/video.js +65 -0
  40. package/source/js/plugins/voice.js +438 -0
  41. package/source/js/search/algolia-search.js +63 -61
  42. package/source/js/services/artalk_latest_comment.js +33 -0
  43. package/source/js/services/friends.js +4 -0
  44. package/source/js/services/giscus_latest_comment.js +36 -0
  45. package/source/js/services/memos.js +91 -69
  46. package/source/js/services/sites.js +4 -0
  47. package/source/js/services/twikoo_latest_comment.js +47 -0
  48. package/source/js/services/waline_latest_comment.js +32 -0
@@ -0,0 +1,438 @@
1
+ /**该方法用来绘制一个有填充色的圆角矩形
2
+ *@param cxt:canvas的上下文环境
3
+ *@param x:左上角x轴坐标
4
+ *@param y:左上角y轴坐标
5
+ *@param width:矩形的宽度
6
+ *@param height:矩形的高度
7
+ *@param radius:圆的半径
8
+ *@param fillColor:填充颜色
9
+ **/
10
+ function fillRoundRect(cxt, x, y, width, height, radius, /*optional*/ fillColor) {
11
+ //圆的直径必然要小于矩形的宽高
12
+ if (2 * radius > width || 2 * radius > height) { return false; }
13
+
14
+ cxt.save();
15
+ cxt.translate(x, y);
16
+ //绘制圆角矩形的各个边
17
+ drawRoundRectPath(cxt, width, height, radius);
18
+ cxt.fillStyle = fillColor || "#000"; //若是给定了值就用给定的值否则给予默认值
19
+ cxt.fill();
20
+ cxt.restore();
21
+ }
22
+
23
+
24
+ /**该方法用来绘制圆角矩形
25
+ *@param cxt:canvas的上下文环境
26
+ *@param x:左上角x轴坐标
27
+ *@param y:左上角y轴坐标
28
+ *@param width:矩形的宽度
29
+ *@param height:矩形的高度
30
+ *@param radius:圆的半径
31
+ *@param lineWidth:线条粗细
32
+ *@param strokeColor:线条颜色
33
+ **/
34
+ function strokeRoundRect(cxt, x, y, width, height, radius, /*optional*/ lineWidth, /*optional*/ strokeColor) {
35
+ //圆的直径必然要小于矩形的宽高
36
+ if (2 * radius > width || 2 * radius > height) { return false; }
37
+
38
+ cxt.save();
39
+ cxt.translate(x, y);
40
+ //绘制圆角矩形的各个边
41
+ drawRoundRectPath(cxt, width, height, radius);
42
+ cxt.lineWidth = lineWidth || 2; //若是给定了值就用给定的值否则给予默认值2
43
+ cxt.strokeStyle = strokeColor || "#000";
44
+ cxt.stroke();
45
+ cxt.restore();
46
+ }
47
+
48
+ function drawRoundRectPath(cxt, width, height, radius) {
49
+ cxt.beginPath(0);
50
+ //从右下角顺时针绘制,弧度从0到1/2PI
51
+ cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
52
+
53
+ //矩形下边线
54
+ cxt.lineTo(radius, height);
55
+
56
+ //左下角圆弧,弧度从1/2PI到PI
57
+ cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
58
+
59
+ //矩形左边线
60
+ cxt.lineTo(0, radius);
61
+
62
+ //左上角圆弧,弧度从PI到3/2PI
63
+ cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
64
+
65
+ //上边线
66
+ cxt.lineTo(width - radius, 0);
67
+
68
+ //右上角圆弧
69
+ cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
70
+
71
+ //右边线
72
+ cxt.lineTo(width, height - radius);
73
+ cxt.closePath();
74
+ }
75
+
76
+ function fillRoundRectPro(cxt, x, y, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius, /*optional*/ fillColor) {
77
+ //圆的直径必然要小于矩形的宽高
78
+ if (topLeftRadius + topRightRadius > width ||
79
+ bottomLeftRadius + bottomRightRadius > width ||
80
+ topLeftRadius + bottomLeftRadius > height ||
81
+ topRightRadius + bottomRightRadius > height) {
82
+ return false;
83
+ }
84
+
85
+ cxt.save();
86
+ cxt.translate(x, y);
87
+ //绘制圆角矩形的各个边
88
+ drawRoundRectPathPro(cxt, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius);
89
+ cxt.fillStyle = fillColor || "#000"; //若是给定了值就用给定的值否则给予默认值
90
+ cxt.fill();
91
+ cxt.restore();
92
+ }
93
+
94
+ function drawRoundRectPathPro(cxt, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius) {
95
+ cxt.beginPath(0);
96
+ //从右下角顺时针绘制,弧度从0到1/2PI
97
+ cxt.arc(width - bottomRightRadius, height - bottomRightRadius, bottomRightRadius, 0, Math.PI / 2);
98
+
99
+ //矩形下边线
100
+ cxt.lineTo(bottomLeftRadius, height);
101
+
102
+ //左下角圆弧,弧度从1/2PI到PI
103
+ cxt.arc(bottomLeftRadius, height - bottomLeftRadius, bottomLeftRadius, Math.PI / 2, Math.PI);
104
+
105
+ //矩形左边线
106
+ cxt.lineTo(0, topLeftRadius);
107
+
108
+ //左上角圆弧,弧度从PI到3/2PI
109
+ cxt.arc(topLeftRadius, topLeftRadius, topLeftRadius, Math.PI, Math.PI * 3 / 2);
110
+
111
+ //上边线
112
+ cxt.lineTo(width - topRightRadius, 0);
113
+
114
+ //右上角圆弧
115
+ cxt.arc(width - topRightRadius, topRightRadius, topRightRadius, Math.PI * 3 / 2, Math.PI * 2);
116
+
117
+ //右边线
118
+ cxt.lineTo(width, height - bottomRightRadius);
119
+ cxt.closePath();
120
+ }
121
+
122
+ function drawWave(context, audioHeight, waveHeightArr, radius, waveColor) {
123
+ //绘制wave
124
+ for (let i = 0; i < waveHeightArr.length; ++i) {
125
+ fillRoundRect(context, 4 * i, (audioHeight - waveHeightArr[i]) / 2, 2, waveHeightArr[i], radius, waveColor);
126
+ }
127
+ }
128
+
129
+ function drawWaveWhenPlaying(context, audioHeight, playLineX, waveHeightArr, radius, activeWaveColor, inactiveWaveColor) {
130
+ //绘制wave
131
+ for (let i = 0; i < waveHeightArr.length; ++i) {
132
+ if (4 * i + 2 <= playLineX) {
133
+ fillRoundRect(context, 4 * i, (audioHeight - waveHeightArr[i]) / 2, 2, waveHeightArr[i], radius, activeWaveColor);
134
+ } else if (4 * i >= playLineX) {
135
+ fillRoundRect(context, 4 * i, (audioHeight - waveHeightArr[i]) / 2, 2, waveHeightArr[i], radius, inactiveWaveColor);
136
+ } else {
137
+ if (playLineX - 4 * i >= 1) {
138
+ fillRoundRect(context, 4 * i, (audioHeight - waveHeightArr[i]) / 2, 2, waveHeightArr[i], radius, inactiveWaveColor);
139
+ fillRoundRectPro(context, 4 * i, (audioHeight - waveHeightArr[i]) / 2, playLineX - 4 * i, waveHeightArr[i], radius, 0, 0, radius, activeWaveColor);
140
+ } else {
141
+ fillRoundRect(context, 4 * i, (audioHeight - waveHeightArr[i]) / 2, 2, waveHeightArr[i], radius, activeWaveColor);
142
+ fillRoundRectPro(context, 4 * i, (audioHeight - waveHeightArr[i]) / 2, 2 - playLineX + 4 * i, waveHeightArr[i], 0, radius, radius, 0, inactiveWaveColor);
143
+ }
144
+ }
145
+
146
+ }
147
+ }
148
+
149
+ function drawPlayLine(context, playLineHeight, playLineX, playLineColor) {
150
+ // 绘制 playLine
151
+ fillRoundRect(context, playLineX, 0, 1, playLineHeight, 0.1, playLineColor);
152
+ }
153
+
154
+ function createVoiceDom(audios) {
155
+ for (let i = 0; i < audios.length; ++i) {
156
+ let audio = audios[i];
157
+ audio.loop = false;
158
+ let currentTime = audio.currentTime // 当前播放时间
159
+
160
+ if (audio.classList.contains('qq')) {
161
+ if (isNaN(audio.duration) || audio.duration === Infinity) {
162
+ audio.addEventListener('durationchange', ()=>{
163
+ // createCssStyle(audio, i);
164
+ createWaveDom(audio);
165
+ });
166
+ } else {
167
+ // createCssStyle(audio, i);
168
+ createWaveDom(audio);
169
+ }
170
+ } else if (audio.classList.contains('wechat')) {
171
+ if (isNaN(audio.duration) || audio.duration === Infinity) {
172
+ audio.addEventListener('durationchange', ()=>{
173
+ createWechatVoiceDom(audio);
174
+ });
175
+ } else {
176
+ createWechatVoiceDom(audio);
177
+ }
178
+ }
179
+ }
180
+ }
181
+
182
+ // cancas 效果更好
183
+ function createWaveDom(audio) {
184
+ let voiceDom = audio.parentElement;
185
+ let audioCanvas = voiceDom.querySelector('canvas');
186
+ if (audioCanvas.getContext("2d")) { //判断浏览器是否支持canvas标签
187
+ let totalTime = audio.duration;
188
+ let totalTimeInt = Math.floor(totalTime);
189
+ let spanNum = totalTimeInt + 2 > 25 ? 25 : totalTimeInt + 2; // 防止过多溢出容器而导致被hidden切割边缘
190
+
191
+ let pauseBtn = voiceDom.querySelector('.pause-btn');
192
+ let playBtn = voiceDom.querySelector('.play-btn');
193
+ let voiceSecondsSpan = voiceDom.querySelector('.voice-seconds');
194
+
195
+ voiceSecondsSpan.innerHTML = `${totalTimeInt > 60 ? '..' : totalTimeInt}"`;
196
+
197
+ let dpr = window.devicePixelRatio;
198
+
199
+ //设置canvas的宽度和高度
200
+ audioCanvas.width = (spanNum * 2 - 1) * 2 * dpr;
201
+ audioCanvas.height = 23 * dpr;
202
+
203
+ audioCanvas.style.width = (spanNum * 2 - 1) * 2 + 'px';
204
+ audioCanvas.style.height = 23 + 'px';
205
+
206
+ let waveHeightArr = [];
207
+ for (let i = 0; i < spanNum; ++i) {
208
+ // (Math.floor(Math.random()*(100-10+1))+10) [10, 100]之间的随机整数
209
+ let h = (Math.floor(Math.random()*(80-30+1))+30) / 100 * audioCanvas.height * 0.8;
210
+ waveHeightArr.push(h);
211
+ }
212
+
213
+ var context = audioCanvas.getContext("2d"); //获取画布context的上下文环境
214
+ context.scale(dpr, 1);
215
+
216
+ let activeWaveColor = '#333';
217
+ let inactiveWaveColor = '#999';
218
+
219
+ if (audioCanvas.classList.contains('right')) {
220
+ activeWaveColor = '#ffffff';
221
+ inactiveWaveColor = '#1373b3';
222
+ }
223
+
224
+ if (utils.dark.mode === "dark") {
225
+ activeWaveColor = '#ccc';
226
+ inactiveWaveColor = '#707070';
227
+ if (audioCanvas.classList.contains('right')) {
228
+ activeWaveColor = '#fff9';
229
+ inactiveWaveColor = '#6797b780';
230
+ }
231
+ }
232
+
233
+ let playFlag = false;
234
+
235
+ //绘制wave
236
+ drawWave(context,audioCanvas.height,waveHeightArr,1,activeWaveColor);
237
+
238
+ audio.addEventListener('timeupdate', ()=>{
239
+ if (audio.currentTime > 0) {
240
+ if (utils.dark.mode === "dark") {
241
+ activeWaveColor = '#ccc';
242
+ inactiveWaveColor = '#707070';
243
+ if (audioCanvas.classList.contains('right')) {
244
+ activeWaveColor = '#fff9';
245
+ inactiveWaveColor = '#6797b780';
246
+ }
247
+ } else {
248
+ activeWaveColor = '#333';
249
+ inactiveWaveColor = '#999';
250
+ if (audioCanvas.classList.contains('right')) {
251
+ activeWaveColor = '#ffffff';
252
+ inactiveWaveColor = '#1373b3';
253
+ }
254
+ }
255
+ utils.requestAnimationFrame(()=>{
256
+ context.clearRect(0, 0, audioCanvas.width, audioCanvas.height);
257
+ drawWaveWhenPlaying(context,audioCanvas.height,(audio.currentTime / audio.duration) * audioCanvas.width / dpr,waveHeightArr,1,activeWaveColor,inactiveWaveColor);
258
+ drawPlayLine(context,audioCanvas.height,(audio.currentTime / audio.duration / dpr) * audioCanvas.width,activeWaveColor);
259
+ });
260
+ }
261
+ });
262
+
263
+ audio.addEventListener('ended', ()=>{
264
+ audio.pause();
265
+ pauseBtn.style.display = "none";
266
+ playBtn.style.display = "flex";
267
+ audio.currentTime = 0;
268
+ utils.requestAnimationFrame(()=>{
269
+ context.clearRect(0, 0, audioCanvas.width, audioCanvas.height);
270
+ drawWave(context,audioCanvas.height,waveHeightArr,1,activeWaveColor);
271
+ });
272
+ playFlag = false;
273
+ });
274
+ voiceDom.addEventListener('click', ()=>{
275
+ if (pauseBtn.style.display === 'flex') {
276
+ audio.pause();
277
+ pauseBtn.style.display = "none";
278
+ playBtn.style.display = "flex";
279
+ playFlag = false;
280
+ } else {
281
+ audio.play();
282
+ pauseBtn.style.display = "flex";
283
+ playBtn.style.display = "none";
284
+ playFlag = true;
285
+ }
286
+ });
287
+
288
+ utils.dark.push(function () {
289
+ if (!playFlag) {
290
+ if (utils.dark.mode === "dark") {
291
+ activeWaveColor = '#ccc';
292
+ inactiveWaveColor = '#707070';
293
+ if (audioCanvas.classList.contains('right')) {
294
+ activeWaveColor = '#fff9';
295
+ inactiveWaveColor = '#6797b780';
296
+ }
297
+ } else {
298
+ activeWaveColor = '#333';
299
+ inactiveWaveColor = '#999';
300
+ if (audioCanvas.classList.contains('right')) {
301
+ activeWaveColor = '#ffffff';
302
+ inactiveWaveColor = '#1373b3';
303
+ }
304
+ }
305
+ if (audio.currentTime > 0) {
306
+ utils.requestAnimationFrame(()=>{
307
+ context.clearRect(0, 0, audioCanvas.width, audioCanvas.height);
308
+ drawWaveWhenPlaying(context,audioCanvas.height,(audio.currentTime / audio.duration) * audioCanvas.width / dpr,waveHeightArr,1,activeWaveColor,inactiveWaveColor);
309
+ drawPlayLine(context,audioCanvas.height,(audio.currentTime / audio.duration / dpr) * audioCanvas.width,activeWaveColor);
310
+ });
311
+ } else {
312
+ utils.requestAnimationFrame(()=>{
313
+ context.clearRect(0, 0, audioCanvas.width, audioCanvas.height);
314
+ drawWave(context,audioCanvas.height,waveHeightArr,1,activeWaveColor);
315
+ });
316
+ }
317
+ }
318
+ });
319
+
320
+ } else {
321
+ console.log("浏览器不支持canvas");
322
+ }
323
+ }
324
+
325
+ // transition 效果差一些
326
+ function createCssStyle(audio, i) {
327
+ let totalTime = audio.duration;
328
+ let totalTimeInt = Math.floor(totalTime);
329
+ let spanNum = totalTimeInt + 2 > 25 ? 25 : totalTimeInt + 2; // 防止过多溢出容器而导致被hidden切割边缘
330
+
331
+ let voiceDom = audio.parentElement;
332
+ let pauseBtn = voiceDom.querySelector('.pause-btn');
333
+ let playBtn = voiceDom.querySelector('.play-btn');
334
+ let voiceSecondsSpan = voiceDom.querySelector('.voice-seconds');
335
+
336
+ voiceSecondsSpan.innerHTML = `${totalTimeInt > 60 ? '..' : totalTimeInt}"`;
337
+
338
+ let width = (2 * spanNum - 1) * 2;
339
+
340
+ if (totalTimeInt + 2 > 25) {
341
+ voiceDom.style.width = '100%';
342
+ }
343
+
344
+ let waveDiv = document.createElement('div');
345
+ let playLineDiv = document.createElement('div');
346
+ playLineDiv.className = 'play-line';
347
+ waveDiv.append(playLineDiv);
348
+ waveDiv.className = `voice-wave voice-wave-${i + 1}`;
349
+ for (let j = 0; j < spanNum; j++) {
350
+ let itemSpan = document.createElement('span');
351
+ itemSpan.className = 'voice-wave-item';
352
+ waveDiv.append(itemSpan)
353
+ }
354
+ voiceDom.insertBefore(waveDiv, voiceDom.querySelector('.voice-metas'));
355
+
356
+ audio.addEventListener('ended', ()=>{
357
+ audio.pause();
358
+ pauseBtn.style.display = "none";
359
+ playBtn.style.display = "flex";
360
+ audio.currentTime = 0;
361
+ playLineDiv.classList.remove('active');
362
+ playLineDiv.classList.add('back');
363
+ });
364
+ voiceDom.addEventListener('click', ()=>{
365
+ if (pauseBtn.style.display === 'flex') {
366
+ audio.pause();
367
+ pauseBtn.style.display = "none";
368
+ playBtn.style.display = "flex";
369
+ audio.currentTime = 0;
370
+ playLineDiv.classList.remove('active');
371
+ playLineDiv.classList.add('back');
372
+ } else {
373
+ audio.play();
374
+ pauseBtn.style.display = "flex";
375
+ playBtn.style.display = "none";
376
+ playLineDiv.classList.add('active');
377
+ playLineDiv.classList.remove('back');
378
+ }
379
+ });
380
+
381
+ let audio_css_str = `
382
+ .voice-wave.voice-wave-${i + 1}>.play-line {
383
+ transition: transform ${totalTime}s linear;
384
+ -moz-transition: transform ${totalTime}s linear;
385
+ -webkit-transition: transform ${totalTime}s linear;
386
+ -o-transition: transform ${totalTime}s linear;
387
+ }
388
+ .voice-wave.voice-wave-${i + 1}>.play-line.active {
389
+ transform: translateX(${width}px);
390
+ }
391
+ `;
392
+ for (let j = 0; j < spanNum; ++j) {
393
+ audio_css_str += `
394
+ .voice-wave-${i + 1} span.voice-wave-item:nth-child(${j + 1}) {
395
+ height: ${(Math.floor(Math.random() * (10 - 3 + 1)) + 3) * 10}%;
396
+ margin-left: ${j == 0 ? 0 : 2}px;
397
+ }
398
+ `;
399
+ }
400
+ let style_voice_wave = document.createElement('style');
401
+ style_voice_wave.setAttribute('type', 'text/css');
402
+ style_voice_wave.innerHTML = audio_css_str;
403
+ document.getElementsByTagName('head').item(0).appendChild(style_voice_wave);
404
+ }
405
+
406
+ function createWechatVoiceDom(audio) {
407
+ let voiceDom = audio.parentElement;
408
+ let wechatVoice = voiceDom.querySelector('.wechat-voice');
409
+
410
+ let totalTime = audio.duration;
411
+ let totalTimeInt = Math.floor(totalTime);
412
+
413
+ let voiceSecondsSpan = voiceDom.querySelector('.voice-seconds');
414
+ voiceSecondsSpan.innerHTML = `${totalTimeInt > 60 ? '..' : totalTimeInt}"`;
415
+
416
+ let voicePlaceholderDiv = voiceDom.querySelector('.voice-placeholder');
417
+ voicePlaceholderDiv.style.width = totalTimeInt * 2 + 'px';
418
+
419
+ let playFlag = false;
420
+
421
+ audio.addEventListener('ended', ()=>{
422
+ audio.pause();
423
+ wechatVoice.classList.remove('play');
424
+ audio.currentTime = 0;
425
+ playFlag = false;
426
+ });
427
+ voiceDom.addEventListener('click', ()=>{
428
+ if (playFlag) {
429
+ audio.pause();
430
+ wechatVoice.classList.remove('play');
431
+ playFlag = false;
432
+ } else {
433
+ audio.play();
434
+ wechatVoice.classList.add('play');
435
+ playFlag = true;
436
+ }
437
+ });
438
+ }
@@ -1,75 +1,77 @@
1
- utils.jq(() => {
2
- var $inputArea = $("input#search-input");
3
- if ($inputArea.length === 0) {
4
- return;
5
- }
1
+ utils.js(window.searchConfig.js).then(() => {
2
+ utils.jq(() => {
3
+ var $inputArea = $("input#search-input");
4
+ if ($inputArea.length === 0) {
5
+ return;
6
+ }
6
7
 
7
- var $resultArea = $("#search-result");
8
- var $searchWrapper = $("#search-wrapper");
9
- var client = algoliasearch(window.searchConfig.appId, window.searchConfig.apiKey);
10
- var index = client.initIndex(window.searchConfig.indexName);
8
+ var $resultArea = $("#search-result");
9
+ var $searchWrapper = $("#search-wrapper");
10
+ var client = algoliasearch(window.searchConfig.appId, window.searchConfig.apiKey);
11
+ var index = client.initIndex(window.searchConfig.indexName);
11
12
 
12
- function filterResults(hits, filterPath) {
13
- if (!filterPath || filterPath === '/') return hits;
14
- var regex = new RegExp(filterPath);
15
- return hits.filter(hit => regex.test(hit.url));
16
- }
13
+ function filterResults(hits, filterPath) {
14
+ if (!filterPath || filterPath === '/') return hits;
15
+ var regex = new RegExp(filterPath);
16
+ return hits.filter(hit => regex.test(hit.url));
17
+ }
17
18
 
18
- function displayResults(hits) {
19
- var $resultList = $("<ul>").addClass("search-result-list");
20
- if (hits.length === 0) {
21
- $searchWrapper.addClass('noresult');
22
- } else {
23
- $searchWrapper.removeClass('noresult');
24
- hits.forEach(function(hit) {
25
- var contentSnippet = hit._snippetResult.content.value;
26
- var title = hit.hierarchy.lvl1 || 'Untitled';
27
- var $item = $("<li>").html(`<a href="${hit.url}"><span class='search-result-title'>${title}</span><p class="search-result-content">${contentSnippet}</p></a>`);
28
- $resultList.append($item);
29
- });
19
+ function displayResults(hits) {
20
+ var $resultList = $("<ul>").addClass("search-result-list");
21
+ if (hits.length === 0) {
22
+ $searchWrapper.addClass('noresult');
23
+ } else {
24
+ $searchWrapper.removeClass('noresult');
25
+ hits.forEach(function(hit) {
26
+ var contentSnippet = hit._snippetResult.content.value;
27
+ var title = hit.hierarchy.lvl1 || 'Untitled';
28
+ var $item = $("<li>").html(`<a href="${hit.url}"><span class='search-result-title'>${title}</span><p class="search-result-content">${contentSnippet}</p></a>`);
29
+ $resultList.append($item);
30
+ });
31
+ }
32
+ $resultArea.html($resultList);
30
33
  }
31
- $resultArea.html($resultList);
32
- }
33
34
 
34
- $inputArea.on("input", function() {
35
- var query = $(this).val().trim();
36
- var filterPath = $inputArea.data('filter');
35
+ $inputArea.on("input", function() {
36
+ var query = $(this).val().trim();
37
+ var filterPath = $inputArea.data('filter');
37
38
 
38
- if (query.length <= 0) {
39
- $searchWrapper.attr('searching', 'false');
40
- $resultArea.empty();
41
- return;
42
- }
39
+ if (query.length <= 0) {
40
+ $searchWrapper.attr('searching', 'false');
41
+ $resultArea.empty();
42
+ return;
43
+ }
43
44
 
44
- $searchWrapper.attr('searching', 'true');
45
+ $searchWrapper.attr('searching', 'true');
45
46
 
46
- index.search(query, {
47
- hitsPerPage: window.searchConfig.hitsPerPage,
48
- attributesToHighlight: ['content'],
49
- attributesToSnippet: ['content:30'],
50
- highlightPreTag: '<span class="search-keyword">',
51
- highlightPostTag: '</span>',
52
- restrictSearchableAttributes: ['content']
53
- }).then(function(responses) {
54
- displayResults(filterResults(responses.hits, filterPath));
47
+ index.search(query, {
48
+ hitsPerPage: window.searchConfig.hitsPerPage,
49
+ attributesToHighlight: ['content'],
50
+ attributesToSnippet: ['content:30'],
51
+ highlightPreTag: '<span class="search-keyword">',
52
+ highlightPostTag: '</span>',
53
+ restrictSearchableAttributes: ['content']
54
+ }).then(function(responses) {
55
+ displayResults(filterResults(responses.hits, filterPath));
56
+ });
55
57
  });
56
- });
57
58
 
58
- $inputArea.on("keydown", function(e) {
59
- if (e.which == 13) {
60
- e.preventDefault();
61
- }
62
- });
59
+ $inputArea.on("keydown", function(e) {
60
+ if (e.which == 13) {
61
+ e.preventDefault();
62
+ }
63
+ });
63
64
 
64
- var observer = new MutationObserver(function(mutationsList) {
65
- if (mutationsList.length === 1) {
66
- if (mutationsList[0].addedNodes.length) {
67
- $searchWrapper.removeClass('noresult');
68
- } else if (mutationsList[0].removedNodes.length) {
69
- $searchWrapper.addClass('noresult');
65
+ var observer = new MutationObserver(function(mutationsList) {
66
+ if (mutationsList.length === 1) {
67
+ if (mutationsList[0].addedNodes.length) {
68
+ $searchWrapper.removeClass('noresult');
69
+ } else if (mutationsList[0].removedNodes.length) {
70
+ $searchWrapper.addClass('noresult');
71
+ }
70
72
  }
71
- }
72
- });
73
+ });
73
74
 
74
- observer.observe($resultArea[0], { childList: true });
75
+ observer.observe($resultArea[0], { childList: true });
76
+ });
75
77
  });
@@ -0,0 +1,33 @@
1
+ utils.jq(() => {
2
+ $(function () {
3
+ const els = document.getElementsByClassName('ds-artalk');
4
+ for (var i = 0; i < els.length; i++) {
5
+ const el = els[i];
6
+ const limit = parseInt(el.getAttribute('limit')) || 10;
7
+
8
+ const api = el.getAttribute('api') + '&limit=' + limit;
9
+ if (api == null) {
10
+ continue;
11
+ }
12
+ utils.request(el, api, function (data) {
13
+ data = data.data || [];
14
+ data.forEach((item, i) => {
15
+ var cell = '<div class="timenode" index="' + i + '">';
16
+ cell += '<div class="header">';
17
+ cell += '<div class="user-info">';
18
+ // cell += '<img src="https://cravatar.cn/avatar/' + (item.email_encrypted) + '?d=mp&s=240">';
19
+ cell += '<span>' + item.nick + '</span>';
20
+ cell += '</div>';
21
+ cell += '<span>' + new Date(item.date).toLocaleString() + '</span>';
22
+ cell += '</div>';
23
+ cell += '<a class="body" href="' + item.page_url + '#atk-comment-' + item.id + '" target="_blank" rel="external nofollow noopener noreferrer">';
24
+ cell += item.content_marked;
25
+ cell += '</a>';
26
+ cell += '</div>';
27
+ $(el).append(cell);
28
+ });
29
+ });
30
+ }
31
+ });
32
+ });
33
+
@@ -17,6 +17,10 @@ utils.jq(() => {
17
17
  cell += `<div class="name image-meta">`;
18
18
  cell += `<span class="image-caption">${item.title || item.login}</span>`;
19
19
  cell += `</div>`;
20
+ if (item.labels && item.labels.length > 0) {
21
+ let label = item.labels[0];
22
+ cell += `<div class="label" style="background:#${label.color};">${label.name}</div>`;
23
+ }
20
24
  cell += `</a>`;
21
25
  cell += `</div>`;
22
26
  $(el).find('.grid-box').append(cell);
@@ -0,0 +1,36 @@
1
+ utils.jq(() => {
2
+ $(function () {
3
+ const els = document.getElementsByClassName('ds-giscus');
4
+ for (var i = 0; i < els.length; i++) {
5
+ const el = els[i];
6
+ const api = el.getAttribute('api');
7
+ if (api == null) {
8
+ continue;
9
+ }
10
+ const default_avatar = def.avatar;
11
+ // layout
12
+ utils.request(el, api, function(data) {
13
+ const limit = el.getAttribute('limit');
14
+ data.forEach((item, i) => {
15
+ if (limit && i >= limit) {
16
+ return;
17
+ }
18
+ comment = item.body.length > 50 ? item.body.substring(0, 50) + '...' : item.body;
19
+ var cell = '<div class="timenode" index="' + i + '">';
20
+ cell += '<div class="header">';
21
+ cell += '<div class="user-info">';
22
+ cell += '<img src="' + (item.author.avatarUrl || default_avatar) + '" onerror="javascript:this.src=\'' + default_avatar + '\';">';
23
+ cell += '<span>' + item.author.login + '</span>';
24
+ cell += '</div>';
25
+ cell += '<span>' + new Date(item.createdAt).toLocaleString() + '</span>';
26
+ cell += '</div>';
27
+ cell += '<a class="body" href="' + item.url + '" target="_blank" rel="external nofollow noopener noreferrer">';
28
+ cell += comment;
29
+ cell += '</a>';
30
+ cell += '</div>';
31
+ $(el).append(cell);
32
+ });
33
+ });
34
+ }
35
+ });
36
+ });