hexo-theme-solitude 1.6.0 → 1.7.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 (83) hide show
  1. package/README.md +1 -1
  2. package/README_zh-cn.md +1 -1
  3. package/README_zh-tw.md +1 -1
  4. package/SECURITY.md +5 -5
  5. package/_config.yml +50 -51
  6. package/languages/en.yml +59 -63
  7. package/languages/zh-CN.yml +52 -55
  8. package/languages/zh-TW.yml +52 -55
  9. package/layout/404.pug +1 -1
  10. package/layout/category.pug +1 -1
  11. package/layout/includes/console.pug +13 -12
  12. package/layout/includes/footer.pug +6 -6
  13. package/layout/includes/head/config.pug +70 -38
  14. package/layout/includes/head/opengraph.pug +2 -2
  15. package/layout/includes/head/pwa.pug +6 -6
  16. package/layout/includes/head.pug +1 -1
  17. package/layout/includes/inject/body.pug +7 -7
  18. package/layout/includes/inject/head.pug +35 -1
  19. package/layout/includes/keyboard.pug +1 -1
  20. package/layout/includes/nav.pug +1 -1
  21. package/layout/includes/sidebar.pug +19 -3
  22. package/layout/includes/widgets/home/categoryBar.pug +2 -2
  23. package/layout/includes/widgets/home/postList.pug +4 -4
  24. package/layout/includes/widgets/home/topGroup.pug +2 -2
  25. package/layout/includes/widgets/nav/group.pug +2 -2
  26. package/layout/includes/widgets/nav/right.pug +1 -1
  27. package/layout/includes/widgets/page/about/award.pug +8 -9
  28. package/layout/includes/widgets/page/about/hobbies.pug +1 -1
  29. package/layout/includes/widgets/page/about/other.pug +1 -1
  30. package/layout/includes/widgets/page/banner.pug +1 -1
  31. package/layout/includes/widgets/page/links/banner.pug +5 -4
  32. package/layout/includes/widgets/page/moments/angle.pug +1 -1
  33. package/layout/includes/widgets/post/award.pug +10 -15
  34. package/layout/includes/widgets/post/copyright.pug +2 -2
  35. package/layout/includes/widgets/post/postMeta.pug +17 -10
  36. package/layout/includes/widgets/randomlink.pug +3 -2
  37. package/layout/includes/widgets/third-party/comments/comment.pug +5 -7
  38. package/layout/includes/widgets/third-party/comments/twikoo.pug +1 -0
  39. package/layout/includes/widgets/third-party/comments/valine.pug +44 -0
  40. package/layout/includes/widgets/third-party/comments/waline.pug +40 -11
  41. package/layout/includes/widgets/third-party/news-comment/newest-comment.pug +5 -3
  42. package/layout/includes/widgets/third-party/news-comment/twikoo.pug +12 -10
  43. package/layout/includes/widgets/third-party/news-comment/valine.pug +79 -0
  44. package/layout/includes/widgets/third-party/news-comment/waline.pug +25 -20
  45. package/layout/page.pug +3 -0
  46. package/layout/tag.pug +1 -1
  47. package/package.json +1 -1
  48. package/plugins.yml +15 -3
  49. package/scripts/event/cdn.js +9 -9
  50. package/scripts/event/init.js +4 -2
  51. package/scripts/event/merge_config.js +15 -6
  52. package/scripts/helper/related_post.js +2 -2
  53. package/scripts/tags/tabs.js +1 -1
  54. package/source/css/_comments/{index.styl → comment.styl} +15 -22
  55. package/source/css/_comments/twikoo.styl +3 -0
  56. package/source/css/_comments/valine.styl +245 -0
  57. package/source/css/_global/index.styl +3 -0
  58. package/source/css/_highlight/highlight/index.styl +1 -1
  59. package/source/css/_highlight/prismjs/line-number.styl +1 -1
  60. package/source/css/_layout/article-sort.styl +1 -1
  61. package/source/css/_layout/aside.styl +3 -3
  62. package/source/css/_layout/console.styl +7 -6
  63. package/source/css/_layout/footer.styl +1 -0
  64. package/source/css/_layout/header.styl +2 -0
  65. package/source/css/_layout/sidebar.styl +30 -20
  66. package/source/css/_page/_home/home-top.styl +1 -1
  67. package/source/css/_page/_home/recent-post.styl +2 -2
  68. package/source/css/_page/index.styl +1 -4
  69. package/source/css/_page/links.styl +5 -5
  70. package/source/css/_post/content.styl +26 -7
  71. package/source/css/_post/tools.styl +3 -9
  72. package/source/css/index.styl +1 -3
  73. package/source/img/flower.gif +0 -0
  74. package/source/js/{comment/twikoo_commentBarrage.js → commentBarrage/twikoo.js} +4 -10
  75. package/source/js/commentBarrage/valine.js +156 -0
  76. package/source/js/{comment/waline_commentBarrage.js → commentBarrage/waline.js} +3 -5
  77. package/source/js/main.js +92 -96
  78. package/source/js/third_party/efu_ai.min.js +6 -0
  79. package/source/js/utils.js +15 -2
  80. package/layout/includes/widgets/rightside/index.pug +0 -87
  81. package/source/css/_comments/waline.styl +0 -455
  82. package/source/js/rightside.js +0 -221
  83. package/source/js/third_party/sco-ai.min.js +0 -8
@@ -108,6 +108,7 @@
108
108
  .reward-title
109
109
  font-weight 700
110
110
  color var(--efu-red)
111
+ text-wrap wrap
111
112
 
112
113
  .reward-group
113
114
  display flex
@@ -119,14 +120,6 @@
119
120
  list-style-type none
120
121
  vertical-align top
121
122
 
122
- &:first-child
123
- img
124
- border-color var(--efu-green)
125
-
126
- &:last-child
127
- img
128
- border-color var(--efu-blue)
129
-
130
123
  img
131
124
  width 130px
132
125
  height 130px
@@ -156,7 +149,7 @@
156
149
  &:hover
157
150
  color var(--efu-white)
158
151
  background var(--efu-red)
159
- background-image url(https://bu.dusays.com/2023/11/01/6541f7aeb5752.gif)
152
+ background-image url(/img/flower.gif)
160
153
  box-shadow var(--efu-shadow-red)
161
154
 
162
155
  .reward-text
@@ -165,6 +158,7 @@
165
158
 
166
159
  .reward-dec
167
160
  font-size .6rem
161
+ text-wrap wrap
168
162
 
169
163
  // rss
170
164
 
@@ -27,6 +27,4 @@ if hexo-config('search.enable')
27
27
 
28
28
  // comment
29
29
  if hexo-config('comment.enable')
30
- @import '_comments/index.styl'
31
- @import '_comments/twikoo.styl' when hexo-config('comment.type') == 'twikoo'
32
- @import '_comments/waline.styl' when hexo-config('comment.type') == 'waline'
30
+ @import '_comments/comment.styl'
Binary file
@@ -3,9 +3,9 @@ function initializeCommentBarrage() {
3
3
  const e = {
4
4
  maxBarrage: 1,
5
5
  barrageTime: 8e3,
6
- twikooUrl: GLOBAL_CONFIG.comment.twikoo.url,
6
+ twikooUrl: GLOBAL_CONFIG.comment.url,
7
7
  pageUrl: window.location.pathname,
8
- accessToken: GLOBAL_CONFIG.comment.twikoo.accessToken,
8
+ accessToken: GLOBAL_CONFIG.comment.accessToken,
9
9
  };
10
10
 
11
11
  class CommentBarrage {
@@ -79,9 +79,9 @@ function initializeCommentBarrage() {
79
79
  commentBarrageItem.className = "comment-barrage-item";
80
80
  commentBarrageItem.innerHTML = `
81
81
  <div class="barrageHead">
82
- <a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">热评</a>
82
+ <a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">${GLOBAL_CONFIG.lang.barrage.title}</a>
83
83
  <div class="barrageNick">${comment.nick}</div>
84
- <img class="barrageAvatar" src="https://cravatar.cn/avatar/${comment.mailMd5}"/>
84
+ <img class="barrageAvatar" src="${GLOBAL_CONFIG.comment.avatar}/avatar/${comment.mailMd5}"/>
85
85
  <a class="comment-barrage-close" href="javascript:sco.switchCommentBarrage();"><i class="solitude st-close-fill"></i></a>
86
86
  </div>
87
87
  <a class="barrageContent" href="javascript:sco.scrollTo('${comment.id}');">${commentContent}</a>
@@ -102,15 +102,9 @@ function initializeCommentBarrage() {
102
102
  const commentBarrageSwitch = localStorage.getItem("commentBarrageSwitch");
103
103
  if (commentBarrageSwitch != null) {
104
104
  document.querySelector(".comment-barrage").style.display = "flex";
105
- if (GLOBAL_CONFIG.rightside.enable) {
106
- document.querySelector(".menu-commentBarrage-text").textContent = "关闭热评";
107
- }
108
105
  document.querySelector("#consoleCommentBarrage").classList.add("on");
109
106
  } else {
110
107
  document.querySelector(".comment-barrage").style.display = "none";
111
- if (GLOBAL_CONFIG.rightside.enable) {
112
- document.querySelector(".menu-commentBarrage-text").textContent = "显示热评";
113
- }
114
108
  document.querySelector("#consoleCommentBarrage").classList.remove("on");
115
109
  }
116
110
  const comments = await this.fetchComments();
@@ -0,0 +1,156 @@
1
+ function initializeCommentBarrage() {
2
+ window.commentBarrageInitialized = !0;
3
+ let config = {
4
+ maxBarrage: 1,
5
+ barrageTime: 8e3,
6
+ valineUrl: GLOBAL_CONFIG.comment.url,
7
+ pageUrl: window.location.pathname,
8
+ }
9
+ new class {
10
+ commentInterval = null
11
+
12
+ constructor(config) {
13
+ this.config = {
14
+ ...config,
15
+ barrageTimer: [],
16
+ barrageList: [],
17
+ barrageIndex: 0,
18
+ dom: document.querySelector(".comment-barrage")
19
+ };
20
+ this.commentInterval = null;
21
+ this.hoverOnCommentBarrage = false;
22
+ this.init();
23
+ }
24
+
25
+ async fetchComments() {
26
+ const url = new URL(`${this.config.valineUrl}/1.1/classes/Comment`);
27
+ const params = {
28
+ url: this.config.pageUrl,
29
+ order: '-createdAt'
30
+ };
31
+
32
+ for (const [key, value] of Object.entries(params)) {
33
+ url.searchParams.append(key, value);
34
+ }
35
+
36
+ try {
37
+ const response = await fetch(url, {
38
+ method: "GET",
39
+ headers: {
40
+ "X-LC-Id": GLOBAL_CONFIG.comment.appId,
41
+ "X-LC-Key": GLOBAL_CONFIG.comment.appKey,
42
+ "Content-Type": "application/json"
43
+ },
44
+ });
45
+
46
+ if (!response.ok) {
47
+ throw new Error(`HTTP error! status: ${response.status}`);
48
+ }
49
+
50
+ const data = await response.json();
51
+ return data.results.filter(item => item.url === this.config.pageUrl)
52
+ } catch (error) {
53
+ console.error("An error occurred while fetching comments: ", error);
54
+ }
55
+ }
56
+
57
+ commentLinkFilter(comments) {
58
+ return comments.flatMap(comment => this.getCommentReplies(comment));
59
+ }
60
+
61
+ getCommentReplies(comment) {
62
+ window.comment = comment
63
+ if (!comment.replies) {
64
+ return [comment];
65
+ }
66
+ return [comment, ...comment.replies.flatMap(reply => this.getCommentReplies(reply))];
67
+ }
68
+
69
+ processCommentContent(comment) {
70
+ const processed = comment.replace(/```[\s\S]*?```|<blockquote\b[^>]*>[\s\S]*?<\/blockquote>|<[^>]*>|\n|`([^`]{1,9})`:/g, "").trim();
71
+ return processed ? `<p>${processed}</p>` : "";
72
+ }
73
+
74
+ createCommentBarrage(comment) {
75
+ const content = this.processCommentContent(comment.comment).trim();
76
+ if (!content) {
77
+ return false;
78
+ }
79
+
80
+ const element = document.createElement("div");
81
+ element.classList.add("comment-barrage-item");
82
+ element.innerHTML = `
83
+ <div class="barrageHead">
84
+ <a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">${GLOBAL_CONFIG.lang.barrage.title}</a>
85
+ <div class="barrageNick">${comment.nick}</div>
86
+ <img class="barrageAvatar" src="${GLOBAL_CONFIG.comment.avatar}/avatar/${md5(comment.mail.toLowerCase())}"/>
87
+ <a class="comment-barrage-close" href="javascript:sco.switchCommentBarrage();">
88
+ <i class="solitude st-close-fill"></i>
89
+ </a>
90
+ </div>
91
+ <a class="barrageContent" href="javascript:sco.scrollTo('${comment.objectId}');">${comment.comment}</a>
92
+ `;
93
+
94
+ this.config.dom.appendChild(element);
95
+ this.config.barrageTimer.push(element);
96
+
97
+ return true;
98
+ }
99
+
100
+ removeCommentBarrage(element) {
101
+ element.className = "comment-barrage-item out";
102
+ setTimeout(() => {
103
+ this.config.dom.removeChild(element);
104
+ }, 1000);
105
+ }
106
+
107
+ async initCommentBarrage() {
108
+ const commentBarrage = document.querySelector(".comment-barrage");
109
+ const menuCommentBarrageText = document.querySelector(".menu-commentBarrage-text");
110
+ const consoleCommentBarrage = document.querySelector("#consoleCommentBarrage");
111
+
112
+ if (localStorage.getItem("commentBarrageSwitch") != null) {
113
+ commentBarrage.style.display = "flex";
114
+ consoleCommentBarrage.classList.add("on");
115
+ } else {
116
+ commentBarrage.style.display = "none";
117
+ consoleCommentBarrage.classList.remove("on");
118
+ }
119
+
120
+ const comments = await this.fetchComments();
121
+ this.config.barrageList = this.commentLinkFilter(comments);
122
+ this.config.dom.innerHTML = "";
123
+ clearInterval(this.commentInterval);
124
+ this.commentInterval = null;
125
+
126
+ const createOrRemoveBarrage = () => {
127
+ if (this.config.barrageList.length && !this.hoverOnCommentBarrage) {
128
+ if (!this.createCommentBarrage(this.config.barrageList[this.config.barrageIndex])) {
129
+ this.config.barrageIndex = (this.config.barrageIndex + 1) % this.config.barrageList.length;
130
+ return createOrRemoveBarrage();
131
+ }
132
+ this.config.barrageIndex = (this.config.barrageIndex + 1) % this.config.barrageList.length;
133
+ }
134
+ if (this.config.barrageTimer.length > (this.config.barrageList.length > this.config.maxBarrage ? this.config.maxBarrage : this.config.barrageList.length) && !this.hoverOnCommentBarrage) {
135
+ this.removeCommentBarrage(this.config.barrageTimer.shift());
136
+ }
137
+ };
138
+
139
+ setTimeout(() => {
140
+ createOrRemoveBarrage();
141
+ if (this.commentInterval) {
142
+ clearInterval(this.commentInterval);
143
+ }
144
+ this.commentInterval = setInterval(createOrRemoveBarrage, this.config.barrageTime);
145
+ }, 3000);
146
+ }
147
+
148
+ async init() {
149
+ await this.initCommentBarrage();
150
+ const commentBarrage = document.querySelector(".comment-barrage");
151
+ commentBarrage.addEventListener('mouseover', () => this.hoverOnCommentBarrage = true);
152
+ commentBarrage.addEventListener('mouseout', () => this.hoverOnCommentBarrage = false);
153
+ }
154
+ }
155
+ (config)
156
+ }
@@ -3,7 +3,7 @@ function initializeCommentBarrage() {
3
3
  let config = {
4
4
  maxBarrage: 1,
5
5
  barrageTime: 8e3,
6
- walineUrl: GLOBAL_CONFIG.comment.waline.url,
6
+ walineUrl: GLOBAL_CONFIG.comment.url,
7
7
  pageUrl: window.location.pathname,
8
8
  }
9
9
  new class {
@@ -78,9 +78,9 @@ function initializeCommentBarrage() {
78
78
  element.classList.add("comment-barrage-item");
79
79
  element.innerHTML = `
80
80
  <div class="barrageHead">
81
- <a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">热评</a>
81
+ <a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">${GLOBAL_CONFIG.lang.barrage.title}</a>
82
82
  <div class="barrageNick">${comment.nick}</div>
83
- <img class="barrageAvatar" src="https://cravatar.cn/avatar/${comment.avatar}"/>
83
+ <img class="barrageAvatar" src="${GLOBAL_CONFIG.comment.avatar}/avatar/${comment.avatar}"/>
84
84
  <a class="comment-barrage-close" href="javascript:sco.switchCommentBarrage();">
85
85
  <i class="solitude st-close-fill"></i>
86
86
  </a>
@@ -108,11 +108,9 @@ function initializeCommentBarrage() {
108
108
 
109
109
  if (localStorage.getItem("commentBarrageSwitch") != null) {
110
110
  commentBarrage.style.display = "flex";
111
- GLOBAL_CONFIG.rightside.enable && (menuCommentBarrageText.textContent = "关闭热评");
112
111
  consoleCommentBarrage.classList.add("on");
113
112
  } else {
114
113
  commentBarrage.style.display = "none";
115
- GLOBAL_CONFIG.rightside.enable && (menuCommentBarrageText.textContent = "显示热评");
116
114
  consoleCommentBarrage.classList.remove("on");
117
115
  }
118
116
 
package/source/js/main.js CHANGED
@@ -74,7 +74,7 @@ const percent = () => {
74
74
 
75
75
  if ((document.getElementById("post-comment") || document.getElementById("footer")).offsetTop < viewportBottom || scrollPercent > 90) {
76
76
  document.querySelector("#nav-totop").classList.add("long")
77
- percentElement.innerHTML = "返回顶部"
77
+ percentElement.innerHTML = GLOBAL_CONFIG.lang.backtop
78
78
  } else {
79
79
  document.querySelector("#nav-totop").classList.remove("long")
80
80
  if (scrollPercent >= 0) {
@@ -234,17 +234,29 @@ let sco = {
234
234
  }));
235
235
  }
236
236
  },
237
+ musicToggle: function () {
238
+ const $music = document.querySelector('#nav-music');
239
+ const $meting = document.querySelector('meting-js');
240
+ const $console = document.getElementById('consoleMusic');
241
+ const $toggleButton = document.getElementById('menu-music-toggle');
242
+ wleelw_musicPlaying = !wleelw_musicPlaying;
243
+ $music.classList.toggle("playing", wleelw_musicPlaying);
244
+ $console.classList.toggle("on", wleelw_musicPlaying);
245
+ if (wleelw_musicPlaying) {
246
+ $meting.aplayer.play();
247
+ } else {
248
+ $meting.aplayer.pause();
249
+ }
250
+ },
237
251
  switchCommentBarrage: function () {
238
252
  let commentBarrageElement = document.querySelector(".comment-barrage");
239
253
  if (commentBarrageElement) {
240
254
  if (window.getComputedStyle(commentBarrageElement).display === "flex") {
241
255
  commentBarrageElement.style.display = "none";
242
- document.querySelector(".menu-commentBarrage-text").textContent = "显示热评";
243
256
  document.querySelector("#consoleCommentBarrage").classList.remove("on");
244
257
  localStorage.removeItem("commentBarrageSwitch");
245
258
  } else {
246
259
  commentBarrageElement.style.display = "flex";
247
- document.querySelector(".menu-commentBarrage-text").textContent = "关闭热评";
248
260
  document.querySelector("#consoleCommentBarrage").classList.add("on");
249
261
  localStorage.setItem("commentBarrageSwitch", "false");
250
262
  }
@@ -290,12 +302,10 @@ let sco = {
290
302
  document.documentElement.setAttribute('data-theme', 'dark')
291
303
  saveToLocal.set('theme', 'dark', 0.02);
292
304
  utils.snackbarShow(GLOBAL_CONFIG.lang.theme.dark, false, 2000)
293
- GLOBAL_CONFIG.rightside && (document.querySelector(".menu-darkmode-text").textContent = "浅色模式");
294
305
  } else {
295
306
  document.documentElement.setAttribute('data-theme', 'light')
296
307
  saveToLocal.set('theme', 'light', 0.02);
297
308
  utils.snackbarShow(GLOBAL_CONFIG.lang.theme.light, false, 2000)
298
- GLOBAL_CONFIG.rightside && (document.querySelector(".menu-darkmode-text").textContent = "深色模式");
299
309
  }
300
310
  },
301
311
  hideTodayCard: () => document.getElementById('todayCard').classList.add('hide'),
@@ -336,10 +346,6 @@ let sco = {
336
346
  el.setSelectionRange(-1, -1)
337
347
  }
338
348
  }
339
- const commentTips = document.querySelector("#comment-tips");
340
- if (commentTips) {
341
- commentTips.classList.add("show");
342
- }
343
349
  },
344
350
  initbbtalk: function () {
345
351
  if (document.querySelector('#bber-talk')) {
@@ -368,67 +374,6 @@ let sco = {
368
374
  }
369
375
  });
370
376
  },
371
- downloadImage: function (imageUrl, filename = 'photo') {
372
- if (rm.downloadimging) {
373
- utils.snackbarShow("有正在进行中的下载,请稍后再试");
374
- return;
375
- }
376
-
377
- rm.hideRightMenu();
378
- rm.downloadimging = true;
379
- utils.snackbarShow("正在下载中,请稍后", false, 10000);
380
-
381
- let img = new Image();
382
- img.setAttribute("crossOrigin", "anonymous");
383
- img.onload = function () {
384
- let canvas = document.createElement("canvas");
385
- canvas.width = img.width;
386
- canvas.height = img.height;
387
- let ctx = canvas.getContext("2d");
388
- ctx.drawImage(img, 0, 0, img.width, img.height);
389
-
390
- let dataUrl = canvas.toDataURL("image/png");
391
- let link = document.createElement("a");
392
- link.download = filename;
393
- link.href = dataUrl;
394
-
395
- let clickEvent = new MouseEvent("click");
396
- link.dispatchEvent(clickEvent);
397
-
398
- utils.snackbarShow("图片已添加盲水印,请遵守版权协议");
399
- rm.downloadimging = false;
400
- };
401
- img.src = imageUrl;
402
- },
403
- musicToggle: function () {
404
- const $music = document.querySelector('#nav-music');
405
- const $meting = document.querySelector('meting-js');
406
- const $console = document.getElementById('consoleMusic');
407
- const $toggleButton = document.getElementById('menu-music-toggle');
408
- wleelw_musicPlaying = !wleelw_musicPlaying;
409
- $music.classList.toggle("playing", wleelw_musicPlaying);
410
- $console.classList.toggle("on", wleelw_musicPlaying);
411
- if (wleelw_musicPlaying) {
412
- $meting.aplayer.play();
413
- $toggleButton.innerHTML = `<i class="solitude st-pause-fill"></i><span>暂停音乐</span>`;
414
- } else {
415
- $meting.aplayer.pause();
416
- $toggleButton.innerHTML = `<i class="solitude st-play-fill"></i><span>播放音乐</span>`;
417
- }
418
- rm.hideRightMenu();
419
- },
420
- musicSkipBack: function () {
421
- document.querySelector('meting-js').aplayer.skipBack()
422
- rm.hideRightMenu()
423
- },
424
- musicSkipForward: function () {
425
- document.querySelector('meting-js').aplayer.skipForward()
426
- rm.hideRightMenu()
427
- },
428
- musicGetName: function () {
429
- const titles = Array.from(document.querySelectorAll('.aplayer-title')).map(e => e.innerText);
430
- return titles[0];
431
- },
432
377
  scrollToComment: function () {
433
378
  utils.scrollToDest(utils.getEleTop(document.getElementById('post-comment')), 300)
434
379
  },
@@ -581,13 +526,13 @@ let sco = {
581
526
  });
582
527
  },
583
528
  addNavBackgroundInit: function () {
584
- var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
529
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
585
530
  if (scrollTop !== 0) {
586
- var pageHeader = document.getElementById("page-header");
531
+ const pageHeader = document.getElementById("page-header");
587
532
  if (pageHeader) {
588
533
  pageHeader.classList.add("nav-fixed", "nav-visible");
589
534
  }
590
- var cookiesWindow = document.getElementById("cookies-window");
535
+ const cookiesWindow = document.getElementById("cookies-window");
591
536
  if (cookiesWindow) {
592
537
  cookiesWindow.style.display = 'none';
593
538
  }
@@ -637,28 +582,59 @@ let sco = {
637
582
  document.getElementById("toPageButton").href = targetPageUrl;
638
583
  }
639
584
  },
640
- addRandomCommentInfo: function () {
641
- const e = `${GLOBAL_CONFIG.comment.randomInfoStart[Math.floor(Math.random() * GLOBAL_CONFIG.comment.randomInfoStart.length)]}${GLOBAL_CONFIG.comment.randomInfoEnd[Math.floor(Math.random() * GLOBAL_CONFIG.comment.randomInfoEnd.length)]}`;
585
+ owoBig() {
586
+ const owoSelectors = GLOBAL_CONFIG.comment.owo
587
+
588
+ let owoBig = document.getElementById('owo-big');
589
+ if (!owoBig) {
590
+ owoBig = document.createElement('div');
591
+ owoBig.id = 'owo-big';
592
+ document.body.appendChild(owoBig);
593
+ }
594
+
595
+ const debounce = (func, wait) => {
596
+ let timeout;
597
+ return function (...args) {
598
+ const later = () => {
599
+ clearTimeout(timeout);
600
+ func(...args);
601
+ };
602
+ clearTimeout(timeout);
603
+ timeout = setTimeout(later, wait);
604
+ };
605
+ };
642
606
 
643
- const nameSelectors = ["#author", "input[name='comname']", "#inpName", "input[name='author']", "#ds-dialog-name", "#name", "input[name='nick']", "#comment_author"];
644
- const emailSelectors = ["#mail", "#email", "input[name='commail']", "#inpEmail", "input[name='email']", "#ds-dialog-email", "input[name='mail']", "#comment_email"];
607
+ const showOwoBig = (event) => {
608
+ const target = event.target;
609
+ const owoItem = target.closest(owoSelectors.item);
610
+ if (owoItem && target.closest(owoSelectors.body)) {
611
+ const imgSrc = owoItem.querySelector('img')?.src;
612
+ if (imgSrc) {
613
+ owoBig.innerHTML = `<img src="${imgSrc}" style="max-width: 100%; height: auto;">`;
614
+ owoBig.style.display = 'block';
615
+ positionOwoBig(owoItem);
616
+ }
617
+ }
618
+ };
645
619
 
646
- const nameElements = nameSelectors.map(selector => document.querySelector(selector)).filter(Boolean);
647
- const emailElements = emailSelectors.map(selector => document.querySelector(selector)).filter(Boolean);
620
+ const hideOwoBig = (event) => {
621
+ if (event.target.closest(owoSelectors.item) && event.target.closest(owoSelectors.body)) {
622
+ owoBig.style.display = 'none';
623
+ }
624
+ };
648
625
 
649
- nameElements.forEach(element => {
650
- element.value = e;
651
- element.dispatchEvent(new Event("input"));
652
- });
626
+ function positionOwoBig(owoItem) {
627
+ const itemRect = owoItem.getBoundingClientRect();
628
+ owoBig.style.left = `${itemRect.left - (owoBig.offsetWidth / 4)}px`;
629
+ owoBig.style.top = `${itemRect.top}px`;
630
+ }
653
631
 
654
- emailElements.forEach(element => {
655
- element.value = "donotreply@examp.com";
656
- element.dispatchEvent(new Event("input"));
657
- });
658
- },
632
+ document.addEventListener('mouseover', debounce(showOwoBig, 100));
633
+ document.addEventListener('mouseout', hideOwoBig);
634
+ }
659
635
  }
660
636
 
661
- const AddHighLightTool = () => {
637
+ const addHighlight = () => {
662
638
  const highlight = GLOBAL_CONFIG.highlight;
663
639
  if (!highlight) return;
664
640
 
@@ -759,6 +735,25 @@ const AddHighLightTool = () => {
759
735
  }
760
736
  }
761
737
 
738
+ const addCopyright = () => {
739
+ if (!GLOBAL_CONFIG.copyright) return
740
+ const {limit, author, link, source, info} = GLOBAL_CONFIG.copyright
741
+ const handleCopy = (e) => {
742
+ e.preventDefault()
743
+ const copyText = window.getSelection(0).toString()
744
+ let text = copyText
745
+ if (copyText.length > limit) {
746
+ text = `${copyText}\n\n${author}\n${link}${window.location.href}\n${source}\n${info}`
747
+ }
748
+ if (e.clipboardData) {
749
+ return e.clipboardData.setData('text', text)
750
+ } else {
751
+ return window.clipboardData.setData('text', text)
752
+ }
753
+ }
754
+ document.body.addEventListener('copy', handleCopy)
755
+ }
756
+
762
757
  class tabs {
763
758
  static init() {
764
759
  this.clickFnOfTabs()
@@ -810,21 +805,20 @@ window.refreshFn = () => {
810
805
  sco.listenToPageInputPress()
811
806
  sco.addNavBackgroundInit()
812
807
  utils.changeTimeFormat()
813
- GLOBAL_CONFIG.rightside.enable && addRightMenuClickEvent()
814
808
  GLOBAL_CONFIG.lazyload.enable && utils.lazyloadImg()
815
809
  GLOBAL_CONFIG.lightbox && utils.lightbox(document.querySelectorAll("#article-container img:not(.flink-avatar)"))
816
- GLOBAL_CONFIG.randomlinks && randomLinksList()
810
+ GLOBAL_CONFIG.randomlink && randomLinksList()
817
811
  PAGE_CONFIG.comment && initComment()
818
812
  PAGE_CONFIG.toc && toc.init();
819
- (PAGE_CONFIG.is_post || PAGE_CONFIG.is_page) && ((AddHighLightTool()) || tabs.init())
813
+ (PAGE_CONFIG.is_post || PAGE_CONFIG.is_page) && ((addHighlight()) || tabs.init())
814
+ addCopyright()
820
815
  PAGE_CONFIG.is_home && showTodayCard()
821
816
  GLOBAL_CONFIG.covercolor.enable && coverColor()
822
817
  sco.initConsoleState()
823
818
  GLOBAL_CONFIG.comment.commentBarrage && PAGE_CONFIG.comment && initializeCommentBarrage()
824
819
  document.body.setAttribute('data-type', PAGE_CONFIG.page)
825
820
  PAGE_CONFIG.page === "music" && scoMusic.init()
826
- GLOBAL_CONFIG.ai.enable && PAGE_CONFIG.page === "post" && ScoAI.init()
827
- preloader.removePaceDone()
821
+ GLOBAL_CONFIG.post_ai && PAGE_CONFIG.page === "post" && efu_ai.init()
828
822
  }
829
823
 
830
824
  document.addEventListener('DOMContentLoaded', function () {
@@ -832,6 +826,8 @@ document.addEventListener('DOMContentLoaded', function () {
832
826
  })
833
827
 
834
828
  window.onkeydown = function (e) {
835
- (123 === e.keyCode || (17 === e.ctrlKey && 16 === e.shiftKey && 67 === e.keyCode)) && utils.snackbarShow("开发者模式已打开,请遵循GPL协议", !1, 3e3);
829
+ (123 === e.keyCode || (17 === e.ctrlKey && 16 === e.shiftKey && 67 === e.keyCode)) && utils.snackbarShow(GLOBAL_CONFIG.lang.f12, !1, 3e3);
836
830
  (27 === e.keyCode) && sco.hideConsole();
837
- }
831
+ }
832
+
833
+ document.addEventListener('copy', () => utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success,false,3e3))
@@ -0,0 +1,6 @@
1
+ /**
2
+ * author: Efu AI
3
+ * email: o@efu.me
4
+ * website: https://efu.me
5
+ */
6
+ class efuAI{constructor(){this.root="https://summary.tianli0.top",this.aiTalkMode=!1,this.aiPostExplanation="",this.config=GLOBAL_CONFIG.post_ai,this.scoGPTIsRunning=!1}init(){this.generate(),this.AIEngine()}getTitleAndContent(){const e=document.getElementById("article-container"),t=document.title,n=e.getElementsByTagName("p"),i=e.querySelectorAll("h1, h2, h3, h4, h5");return(t+" "+Array.from(i).concat(Array.from(n)).map((e=>e.innerText.replace(/https?:\/\/[^\s]+/g,""))).join(" ")).slice(0,1e3)}async generate(){this.aiShowAnimation(this.fetch(document.title,this.getTitleAndContent(),this.config.key))}async fetch(e,t,n){const i=`${this.root}/?content=${encodeURIComponent(t)}&title=${e}&key=${encodeURIComponent(n)}&url=${encodeURIComponent(window.location.href)}`,s=await fetch(i),o=await s.json();return s.ok?(this.aiPostExplanation=o.summary,o.summary):(console.error("Request failed:",o.err_msg),o.err_msg)}aiShowAnimation(e,t=!1){const n=document.querySelector(".ai-explanation"),i=document.querySelector(".ai-tag");if(!n||this.scoGPTIsRunning)return;this.scoGPTIsRunning=!0,this.cleanSuggestions(),i.classList.add("loadingAI"),n.style.display="block",n.innerHTML='生成中...<span class="blinking-cursor"></span>';let s,o,a=!0,c=0,r=!0;const l=new IntersectionObserver((e=>{a=e[0].isIntersecting,a&&requestAnimationFrame(o)}),{threshold:0});e.then((e=>{s=performance.now(),o=()=>{if(c<e.length&&a){const r=performance.now(),g=r-s,h=e.slice(c,c+1),u=/[,。!、?,.!?]/.test(h),m=/[a-zA-Z0-9]/.test(h);g>=(u?100*Math.random()+100:m?10:25)&&(n.innerText=e.slice(0,c+1),s=r,c++,c<e.length?n.innerHTML=e.slice(0,c)+'<span class="blinking-cursor"></span>':(n.innerHTML=e,n.style.display="block",this.scoGPTIsRunning=!1,i.classList.remove("loadingAI"),l.disconnect(),t&&this.createSuggestions())),a&&requestAnimationFrame(o)}},a&&r&&setTimeout((()=>{requestAnimationFrame(o),r=!1}),3e3),l.observe(n)})).catch((e=>{console.error("检索信息失败:",e),n.innerHTML="检索信息失败",n.style.display="block",this.scoGPTIsRunning=!1,i.classList.remove("loadingAI"),l.disconnect()}))}AIEngine(){const e=document.querySelector(".ai-tag");e&&e.addEventListener("click",(()=>{this.scoGPTIsRunning||(this.aiTalkMode=!0,this.aiShowAnimation(Promise.resolve(this.config.talk),!0))}))}cleanSuggestions(){const e=document.querySelector(".ai-suggestions");e?e.innerHTML="":console.error("没有这个元素:'ai-suggestions'")}createSuggestions(){this.aiTalkMode&&(this.cleanSuggestions(),this.createSuggestionItemWithAction("这篇文章讲了什么?",(()=>{""===this.aiPostExplanation?this.generate():this.aiShowAnimation(Promise.resolve(this.aiPostExplanation),!0)})),this.config.randomPost&&this.createSuggestionItemWithAction("带我去看看其他文章",(()=>toRandomPost())),this.aiTalkMode=!0)}createSuggestionItemWithAction(e,t){const n=document.querySelector(".ai-suggestions");if(!n)return void console.error("无法找到具有class为ai-suggestions的元素");const i=document.createElement("div");i.classList.add("ai-suggestions-item"),i.textContent=e,i.addEventListener("click",t),n.appendChild(i)}}const efu_ai=new efuAI;
@@ -224,10 +224,23 @@ const utils = {
224
224
  }
225
225
  }
226
226
  },
227
- changeTimeFormat(){
227
+ changeTimeFormat() {
228
228
  window.Lately && Lately.init({
229
229
  target: 'time',
230
230
  lang: GLOBAL_CONFIG.lang.lately,
231
231
  })
232
- }
232
+ },
233
+ loadComment: (dom, callback) => {
234
+ if ('IntersectionObserver' in window) {
235
+ const observerItem = new IntersectionObserver((entries) => {
236
+ if (entries[0].isIntersecting) {
237
+ callback()
238
+ observerItem.disconnect()
239
+ }
240
+ }, { threshold: [0] })
241
+ observerItem.observe(dom)
242
+ } else {
243
+ callback()
244
+ }
245
+ },
233
246
  }