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.
- package/_config.yml +29 -9
- package/_data/chat_users.yml +0 -0
- package/_data/widgets.yml +7 -0
- package/languages/zh-TW.yml +2 -2
- package/layout/_partial/head.ejs +2 -1
- package/layout/_partial/main/navbar/nav_tabs_blog.ejs +10 -10
- package/layout/_partial/scripts/defines.ejs +3 -0
- package/layout/_partial/scripts/services.ejs +91 -0
- package/layout/_partial/scripts/theme.ejs +5 -0
- package/layout/_partial/scripts/utils.ejs +67 -7
- package/layout/_partial/scripts.ejs +1 -1
- package/layout/_plugins/mermaid.ejs +1 -1
- package/layout/_plugins/scrollreveal.ejs +1 -0
- package/layout/_plugins/search/algolia_search.ejs +11 -12
- package/layout/layout.ejs +1 -1
- package/package.json +1 -1
- package/scripts/events/lib/config.js +3 -0
- package/scripts/events/lib/doc_tree.js +1 -6
- package/scripts/filters/index.js +26 -0
- package/scripts/generators/notebooks.js +1 -1
- package/scripts/generators/search.js +21 -2
- package/scripts/helpers/dynamic_color.js +138 -0
- package/scripts/tags/index.js +1 -0
- package/scripts/tags/lib/box.js +1 -1
- package/scripts/tags/lib/chat.js +515 -0
- package/scripts/tags/lib/folders.js +1 -1
- package/scripts/tags/lib/folding.js +2 -2
- package/scripts/tags/lib/sites.js +1 -1
- package/scripts/tags/lib/video.js +7 -2
- package/source/css/_components/tag-plugins/chat.styl +621 -0
- package/source/css/_components/tag-plugins/friends.styl +10 -0
- package/source/css/_components/tag-plugins/sites.styl +12 -0
- package/source/css/_components/tag-plugins/tabs.styl +5 -2
- package/source/css/_custom.styl +1 -0
- package/source/css/_defines/func.styl +7 -6
- package/source/css/_defines/theme.styl +38 -0
- package/source/css/_plugins/katex.styl +0 -1
- package/source/js/plugins/download-file.js +198 -0
- package/source/js/plugins/video.js +65 -0
- package/source/js/plugins/voice.js +438 -0
- package/source/js/search/algolia-search.js +63 -61
- package/source/js/services/artalk_latest_comment.js +33 -0
- package/source/js/services/friends.js +4 -0
- package/source/js/services/giscus_latest_comment.js +36 -0
- package/source/js/services/memos.js +91 -69
- package/source/js/services/sites.js +4 -0
- package/source/js/services/twikoo_latest_comment.js +47 -0
- 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.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
$inputArea.on("input", function() {
|
|
36
|
+
var query = $(this).val().trim();
|
|
37
|
+
var filterPath = $inputArea.data('filter');
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
if (query.length <= 0) {
|
|
40
|
+
$searchWrapper.attr('searching', 'false');
|
|
41
|
+
$resultArea.empty();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
$searchWrapper.attr('searching', 'true');
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
$inputArea.on("keydown", function(e) {
|
|
60
|
+
if (e.which == 13) {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
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
|
+
});
|