hexo-theme-solitude 3.0.20 → 4.0.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 (143) hide show
  1. package/.github/FUNDING.yml +3 -3
  2. package/README.md +11 -1
  3. package/README_en-US.md +11 -1
  4. package/_config.yml +16 -7
  5. package/languages/default.yml +56 -36
  6. package/languages/en.yml +90 -69
  7. package/languages/es.yml +94 -73
  8. package/languages/zh-CN.yml +56 -34
  9. package/languages/zh-TW.yml +80 -57
  10. package/layout/archive.pug +60 -14
  11. package/layout/category.pug +13 -11
  12. package/layout/includes/body/gadsense.pug +2 -2
  13. package/layout/includes/console.pug +71 -72
  14. package/layout/includes/footer.pug +38 -24
  15. package/layout/includes/head/config.pug +83 -39
  16. package/layout/includes/head/mode.pug +7 -7
  17. package/layout/includes/head/page_config.pug +20 -11
  18. package/layout/includes/inject/body.pug +18 -40
  19. package/layout/includes/keyboard.pug +3 -3
  20. package/layout/includes/loading.pug +1 -37
  21. package/layout/includes/mixins/articleSort.pug +3 -3
  22. package/layout/includes/mixins/common.pug +8 -4
  23. package/layout/includes/mixins/pace.pug +1 -1
  24. package/layout/includes/mixins/pagination.pug +3 -3
  25. package/layout/includes/nav.pug +5 -4
  26. package/layout/includes/page/about.pug +9 -8
  27. package/layout/includes/page/brevity.pug +2 -2
  28. package/layout/includes/page/links.pug +23 -11
  29. package/layout/includes/page/music.pug +0 -5
  30. package/layout/includes/rightmenu.pug +20 -20
  31. package/layout/includes/sidebar.pug +2 -2
  32. package/layout/includes/widgets/aside/asideInfoCard.pug +2 -2
  33. package/layout/includes/widgets/aside/asideTag.pug +2 -2
  34. package/layout/includes/widgets/home/bbTimeList.pug +3 -3
  35. package/layout/includes/widgets/home/categoryBar.pug +30 -15
  36. package/layout/includes/widgets/home/hometop.pug +113 -8
  37. package/layout/includes/widgets/home/postList.pug +1 -2
  38. package/layout/includes/widgets/home/topGroup.pug +3 -7
  39. package/layout/includes/widgets/nav/group.pug +4 -2
  40. package/layout/includes/widgets/nav/menu.pug +6 -4
  41. package/layout/includes/widgets/nav/right.pug +7 -6
  42. package/layout/includes/widgets/page/about/award.pug +67 -38
  43. package/layout/includes/widgets/page/about/hobbies.pug +12 -3
  44. package/layout/includes/widgets/page/banner.pug +1 -1
  45. package/layout/includes/widgets/page/kit/content.pug +2 -2
  46. package/layout/includes/widgets/page/links/banner.pug +30 -19
  47. package/layout/includes/widgets/page/message/artalk.pug +3 -3
  48. package/layout/includes/widgets/page/message/content.pug +3 -3
  49. package/layout/includes/widgets/page/message/twikoo.pug +3 -3
  50. package/layout/includes/widgets/page/message/valine.pug +4 -4
  51. package/layout/includes/widgets/page/message/waline.pug +3 -3
  52. package/layout/includes/widgets/page/recentcomment/artalk.pug +5 -9
  53. package/layout/includes/widgets/page/recentcomment/twikoo.pug +5 -9
  54. package/layout/includes/widgets/page/recentcomment/valine.pug +6 -10
  55. package/layout/includes/widgets/page/recentcomment/waline.pug +5 -9
  56. package/layout/includes/widgets/post/award.pug +1 -28
  57. package/layout/includes/widgets/post/copyright.pug +10 -10
  58. package/layout/includes/widgets/post/postInfo.pug +10 -11
  59. package/layout/includes/widgets/post/postMeta.pug +3 -2
  60. package/layout/includes/widgets/rightside/hide.pug +5 -5
  61. package/layout/includes/widgets/rightside/show.pug +7 -7
  62. package/layout/includes/widgets/third-party/comments/artalk.pug +9 -9
  63. package/layout/includes/widgets/third-party/comments/giscus.pug +2 -2
  64. package/layout/includes/widgets/third-party/comments/twikoo.pug +5 -5
  65. package/layout/includes/widgets/third-party/comments/valine.pug +6 -6
  66. package/layout/includes/widgets/third-party/comments/waline.pug +6 -6
  67. package/layout/includes/widgets/third-party/hot/index.pug +1 -1
  68. package/layout/includes/widgets/third-party/hot/twikoo.pug +1 -1
  69. package/layout/includes/widgets/third-party/music.pug +9 -5
  70. package/layout/includes/widgets/third-party/news-comment/artalk.pug +6 -6
  71. package/layout/includes/widgets/third-party/news-comment/twikoo.pug +7 -7
  72. package/layout/includes/widgets/third-party/news-comment/valine.pug +8 -8
  73. package/layout/includes/widgets/third-party/news-comment/waline.pug +7 -7
  74. package/layout/includes/widgets/third-party/pjax.pug +16 -10
  75. package/layout/includes/widgets/third-party/search/algolia-search.pug +2 -2
  76. package/layout/includes/widgets/third-party/search/docsearch.pug +3 -3
  77. package/layout/includes/widgets/third-party/search/index.pug +1 -3
  78. package/layout/includes/widgets/third-party/search/local-search.pug +9 -9
  79. package/layout/index.pug +10 -8
  80. package/package.json +8 -7
  81. package/plugins.yml +22 -21
  82. package/scripts/event/cdn.js +11 -6
  83. package/scripts/event/friend_links.js +30 -0
  84. package/scripts/event/merge_config.js +15 -7
  85. package/scripts/filter/comment.js +2 -2
  86. package/scripts/filter/default.js +1 -1
  87. package/scripts/helper/inject_head_js.js +79 -33
  88. package/scripts/helper/related_post.js +16 -21
  89. package/scripts/tags/chart.js +1 -1
  90. package/scripts/tags/typeit.js +1 -1
  91. package/source/css/_components/capsule.styl +259 -168
  92. package/source/css/_components/rightside.styl +98 -242
  93. package/source/css/_global/animation.styl +1 -10
  94. package/source/css/_global/index.styl +27 -1
  95. package/source/css/_layout/aside.styl +7 -1
  96. package/source/css/_layout/console.styl +144 -163
  97. package/source/css/_layout/header.styl +238 -47
  98. package/source/css/_layout/pagination.styl +176 -132
  99. package/source/css/_layout/rightmenu.styl +11 -2
  100. package/source/css/_layout/sidebar.styl +39 -17
  101. package/source/css/_mode/index.styl +7 -1
  102. package/source/css/_page/_about/about.styl +18 -2
  103. package/source/css/_page/_about/buff.styl +1 -1
  104. package/source/css/_page/_about/contentinfo.styl +2 -1
  105. package/source/css/_page/_about/game.styl +57 -1
  106. package/source/css/_page/_about/like.styl +7 -2
  107. package/source/css/_page/_about/maxim.styl +1 -1
  108. package/source/css/_page/_about/reward.styl +226 -108
  109. package/source/css/_page/_about/skills.styl +5 -3
  110. package/source/css/_page/_home/category-bar.styl +162 -88
  111. package/source/css/_page/_home/home-top.styl +309 -263
  112. package/source/css/_page/_home/home.styl +34 -7
  113. package/source/css/_page/archive.styl +412 -0
  114. package/source/css/_page/category.styl +27 -1
  115. package/source/css/_page/index.styl +2 -0
  116. package/source/css/_page/links.styl +190 -0
  117. package/source/css/_page/other.styl +37 -0
  118. package/source/css/_post/index.styl +2 -1
  119. package/source/css/_post/meta.styl +245 -217
  120. package/source/css/_search/local-search.styl +158 -82
  121. package/source/css/var.styl +2 -2
  122. package/source/js/archive-page.js +191 -0
  123. package/source/js/core/actions.js +48 -0
  124. package/source/js/core/api.js +32 -0
  125. package/source/js/core/config.js +13 -0
  126. package/source/js/core/lifecycle.js +52 -0
  127. package/source/js/core/preloader.js +34 -0
  128. package/source/js/core/resources.js +65 -0
  129. package/source/js/covercolor/api.js +13 -103
  130. package/source/js/covercolor/ave.js +14 -77
  131. package/source/js/covercolor/local.js +22 -116
  132. package/source/js/covercolor/shared.js +102 -0
  133. package/source/js/friend_links.js +502 -0
  134. package/source/js/main.js +793 -177
  135. package/source/js/music.js +24 -14
  136. package/source/js/post_ai.js +13 -2
  137. package/source/js/right_menu.js +44 -24
  138. package/source/js/search/algolia.js +29 -21
  139. package/source/js/search/local.js +231 -266
  140. package/source/js/tw_cn.js +37 -12
  141. package/source/js/utils.js +37 -25
  142. package/layout/includes/widgets/randomlink.pug +0 -43
  143. package/scripts/filter/randomPosts.js +0 -16
@@ -1,3 +1,5 @@
1
+ import { Solitude } from "./core/api.js";
2
+
1
3
  class MusicPlayer {
2
4
  constructor() {
3
5
  this.init();
@@ -14,12 +16,13 @@ class MusicPlayer {
14
16
  }
15
17
 
16
18
  addEventListeners() {
17
- document.addEventListener("keydown", this.handleKeydown.bind(this));
19
+ this.boundKeydown = this.handleKeydown.bind(this);
20
+ document.addEventListener("keydown", this.boundKeydown);
18
21
  const aplayerList = document.querySelector(".aplayer-list");
19
22
  const aplayerLrc = document.querySelector(".aplayer-lrc");
20
23
  if (aplayerLrc && !aplayerLrc.dataset.clickBound) {
21
24
  aplayerLrc.addEventListener("click", () => {
22
- aplayerList.classList.toggle("aplayer-list-hide");
25
+ aplayerList?.classList.toggle("aplayer-list-hide");
23
26
  });
24
27
  aplayerLrc.dataset.clickBound = true;
25
28
  }
@@ -34,6 +37,7 @@ class MusicPlayer {
34
37
 
35
38
  updateBackgroundImage(element) {
36
39
  const musicCover = document.querySelector("#Music-page .aplayer-pic");
40
+ if (!element || !musicCover) return;
37
41
  const img = new Image();
38
42
  img.src = this.extractValue(musicCover.style.backgroundImage);
39
43
  img.onload = () => {
@@ -43,14 +47,15 @@ class MusicPlayer {
43
47
  }
44
48
 
45
49
  setLoadingScreen(loadingElement, backgroundElement) {
46
- const timer = setInterval(() => {
47
- this.addEventListeners();
50
+ clearInterval(this.loadingTimer);
51
+ this.loadingTimer = setInterval(() => {
48
52
  const musicCover = document.querySelector("#Music-page .aplayer-pic");
49
53
  if (musicCover) {
50
- loadingElement.style.display = "none";
51
- clearInterval(timer);
54
+ if (loadingElement) loadingElement.style.display = "none";
55
+ clearInterval(this.loadingTimer);
56
+ this.loadingTimer = null;
52
57
  this.addEventListenerChangeMusicBg();
53
- backgroundElement.style.display = "block";
58
+ if (backgroundElement) backgroundElement.style.display = "block";
54
59
  }
55
60
  }, 100);
56
61
  }
@@ -61,13 +66,15 @@ class MusicPlayer {
61
66
  }
62
67
 
63
68
  addEventListenerChangeMusicBg() {
64
- const aplayer = document.querySelector("#Music-page meting-js").aplayer;
69
+ const aplayer = document.querySelector("#Music-page meting-js")?.aplayer;
70
+ if (!aplayer) return;
65
71
  aplayer.on('loadeddata', () => this.changeMusicBg(true));
66
72
  aplayer.on('timeupdate', this.lrcUpdate.bind(this));
67
73
  }
68
74
 
69
75
  lrcUpdate() {
70
76
  const aplayerLrcContents = document.querySelector('.aplayer-lrc-contents');
77
+ if (!aplayerLrcContents) return;
71
78
  const currentLrc = aplayerLrcContents.querySelector('p.aplayer-lrc-current');
72
79
  if (currentLrc) {
73
80
  const currentIndex = Array.from(aplayerLrcContents.children).indexOf(currentLrc);
@@ -76,7 +83,9 @@ class MusicPlayer {
76
83
  }
77
84
 
78
85
  handleKeydown(event) {
79
- const aplayer = document.querySelector('meting-js').aplayer;
86
+ if (event.target?.matches?.('input, textarea, [contenteditable="true"]')) return;
87
+ const aplayer = document.querySelector('#Music-page meting-js')?.aplayer;
88
+ if (!aplayer) return;
80
89
  const actions = {
81
90
  "Space": () => aplayer.toggle(),
82
91
  "ArrowRight": () => aplayer.skipForward(),
@@ -92,12 +101,13 @@ class MusicPlayer {
92
101
  }
93
102
 
94
103
  destroy() {
95
- document.removeEventListener("keydown", this.handleKeydown);
104
+ clearInterval(this.loadingTimer);
105
+ document.removeEventListener("keydown", this.boundKeydown);
96
106
  }
97
107
  }
98
108
 
99
- function initializeMusicPlayer() {
100
- const exitingMusic = window.scoMusic;
109
+ export function initializeMusicPlayer() {
110
+ const exitingMusic = Solitude.musicPlayer;
101
111
  if (exitingMusic) exitingMusic.destroy();
102
- window.scoMusic = new MusicPlayer();
103
- }
112
+ Solitude.musicPlayer = new MusicPlayer();
113
+ }
@@ -1,3 +1,5 @@
1
+ import { Solitude } from "./core/api.js";
2
+
1
3
  class AIPostRenderer {
2
4
  static ANIMATION_DELAY_MS = 30;
3
5
  static AI_EXPLANATION_SELECTOR = ".ai-explanation";
@@ -99,8 +101,16 @@ class AIPostRenderer {
99
101
  document.dispatchEvent(event);
100
102
  }
101
103
 
104
+ cancel() {
105
+ cancelAnimationFrame(this.animationFrame);
106
+ this.animationFrame = null;
107
+ this.fragment = null;
108
+ this.isAnimating = false;
109
+ this.tagElement?.classList.remove("loadingAI");
110
+ }
111
+
102
112
  get aiContent() {
103
- return PAGE_CONFIG?.ai_text || "";
113
+ return Solitude.page?.ai_text || "";
104
114
  }
105
115
  }
106
116
 
@@ -115,4 +125,5 @@ const aiPostRenderer = (() => {
115
125
  };
116
126
  })();
117
127
 
118
- const ai = aiPostRenderer();
128
+ export const ai = aiPostRenderer();
129
+ export default ai;
@@ -1,11 +1,15 @@
1
+ import { Solitude } from "./core/api.js";
2
+
1
3
  let selectTextNow = "";
2
4
  let firstShowRightMenu = true;
3
5
 
4
6
  const selectText = () => {
5
7
  selectTextNow = document.selection ? document.selection.createRange().text : window.getSelection().toString() || "";
8
+ Solitude.selectedText = selectTextNow;
6
9
  };
7
10
 
8
- document.onmouseup = document.ondbclick = selectText;
11
+ document.addEventListener("mouseup", selectText);
12
+ document.addEventListener("dblclick", selectText);
9
13
 
10
14
  const rm = {
11
15
  mask: document.getElementById("rightmenu-mask"),
@@ -59,7 +63,7 @@ const rm = {
59
63
  copyText(e) {
60
64
  if (navigator.clipboard) {
61
65
  navigator.clipboard.writeText(e);
62
- utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 2000);
66
+ Solitude.snackbarShow(Solitude.config.lang.copy.success, false, 2000);
63
67
  }
64
68
  this.hideRightMenu();
65
69
  },
@@ -76,35 +80,51 @@ const rm = {
76
80
  document.body.removeChild(link);
77
81
  URL.revokeObjectURL(url);
78
82
  } catch (error) {
79
- utils.snackbarShow(GLOBAL_CONFIG.right_menu.img_error, false, 2000);
83
+ Solitude.snackbarShow(Solitude.config.right_menu.img_error, false, 2000);
80
84
  }
81
85
  },
82
86
  copyImage(imgUrl = this.domsrc) {
83
87
  window.open(imgUrl);
84
88
  },
89
+ setLabel(element, label) {
90
+ if (!element || !label) return;
91
+ element.textContent = label;
92
+ element.setAttribute("title", label);
93
+ element.setAttribute("heotip", label);
94
+ const menuItem = element.closest(".rightMenu-item");
95
+ if (menuItem) {
96
+ menuItem.setAttribute("title", label);
97
+ menuItem.setAttribute("heotip", label);
98
+ }
99
+ },
85
100
  mode(darkmode) {
86
- document.querySelector(".menu-darkmode-text").textContent = darkmode ? GLOBAL_CONFIG.right_menu.mode.light : GLOBAL_CONFIG.right_menu.mode.dark;
101
+ const label = darkmode ? Solitude.config.right_menu.mode.light : Solitude.config.right_menu.mode.dark;
102
+ this.setLabel(document.querySelector(".menu-darkmode-text"), label);
87
103
  this.hideRightMenu();
88
104
  },
89
105
  barrage(enable) {
90
- document.querySelector(".menu-commentBarrage-text").textContent = enable ? GLOBAL_CONFIG.right_menu.barrage.open : GLOBAL_CONFIG.right_menu.barrage.close;
106
+ const label = enable ? Solitude.config.right_menu.barrage.open : Solitude.config.right_menu.barrage.close;
107
+ this.setLabel(document.querySelector(".menu-commentBarrage-text"), label);
91
108
  this.hideRightMenu();
92
109
  },
93
110
  };
94
111
 
112
+ Solitude.rightMenu = rm;
113
+ Solitude.hideRightMenu = rm.hideRightMenu.bind(rm);
114
+
95
115
  function stopMaskScroll() {
96
116
  const hideMenu = rm.hideRightMenu.bind(rm);
97
- utils.addEventListenerPjax(rm.menu, "mousewheel", hideMenu, { passive: true });
98
- utils.addEventListenerPjax(rm.mask, "mousewheel", hideMenu, { passive: true });
99
- utils.addEventListenerPjax(rm.mask, "click", hideMenu, { passive: true });
117
+ Solitude.addEventListenerPjax(rm.menu, "mousewheel", hideMenu, { passive: true });
118
+ Solitude.addEventListenerPjax(rm.mask, "mousewheel", hideMenu, { passive: true });
119
+ Solitude.addEventListenerPjax(rm.mask, "click", hideMenu, { passive: true });
100
120
  }
101
121
 
102
- window.oncontextmenu = (ele) => {
122
+ document.addEventListener("contextmenu", (ele) => {
103
123
  if (document.body.clientWidth <= 768) return;
104
- if (GLOBAL_CONFIG.right_menu.ctrlOriginalMenu) {
124
+ if (Solitude.config.right_menu.ctrlOriginalMenu) {
105
125
  if (firstShowRightMenu) {
106
126
  firstShowRightMenu = false;
107
- utils.snackbarShow(GLOBAL_CONFIG.right_menu.ctrlOriginalMenu, false, 2000);
127
+ Solitude.snackbarShow(Solitude.config.right_menu.ctrlOriginalMenu, false, 2000);
108
128
  }
109
129
  if (ele.ctrlKey) return true;
110
130
  }
@@ -122,7 +142,7 @@ window.oncontextmenu = (ele) => {
122
142
  const display = !!(selectTextNow && window.getSelection()) || !!link || !!src || (tagName === "input" || tagName === "textarea") || cls.match(/aplayer/);
123
143
 
124
144
  rm.menuItems.copy.style.display = selectTextNow && window.getSelection() ? "flex" : "none";
125
- GLOBAL_CONFIG.comment && (rm.menuItems.comment.style.display = selectTextNow && window.getSelection() ? "flex" : "none");
145
+ Solitude.config.comment && (rm.menuItems.comment.style.display = selectTextNow && window.getSelection() ? "flex" : "none");
126
146
  rm.menuItems.search && (rm.menuItems.search.style.display = selectTextNow && window.getSelection() ? "flex" : "none");
127
147
 
128
148
  rm.menuItems.new.style.display = link ? "flex" : "none";
@@ -135,7 +155,7 @@ window.oncontextmenu = (ele) => {
135
155
 
136
156
  rm.menuItems.paste.style.display = (tagName === "input" || tagName === "textarea") ? "flex" : "none";
137
157
 
138
- if (GLOBAL_CONFIG.right_menu.music) {
158
+ if (Solitude.config.right_menu.music) {
139
159
  if (cls.match(/aplayer/)) {
140
160
  rm.menuItems.music.forEach(item => item.style.display = "flex");
141
161
  } else {
@@ -151,20 +171,20 @@ window.oncontextmenu = (ele) => {
151
171
  y = (y + rm.height > window.innerHeight) ? y - (y + rm.height - window.innerHeight) : y;
152
172
 
153
173
  rm.showRightMenu(true, x, y);
154
- return false;
155
- };
174
+ ele.preventDefault();
175
+ });
156
176
 
157
177
  (function () {
158
- const addEventListener = (element, event, handler) => element.addEventListener(event, handler);
178
+ const addEventListener = (element, event, handler) => element?.addEventListener(event, handler);
159
179
 
160
180
  addEventListener(rm.menuItems.back, "click", () => window.history.back() || rm.hideRightMenu());
161
181
  addEventListener(rm.menuItems.forward, "click", () => window.history.forward() || rm.hideRightMenu());
162
182
  addEventListener(rm.menuItems.refresh, "click", () => window.location.reload());
163
- addEventListener(rm.menuItems.top, "click", () => sco.toTop() || rm.hideRightMenu());
183
+ addEventListener(rm.menuItems.top, "click", () => Solitude.toTop() || rm.hideRightMenu());
164
184
 
165
- if (GLOBAL_CONFIG.right_menu.music) {
185
+ if (Solitude.config.right_menu.music) {
166
186
  addEventListener(rm.menuItems.music[0], "click", () => {
167
- sco.musicToggle();
187
+ Solitude.musicToggle();
168
188
  rm.hideRightMenu();
169
189
  });
170
190
  addEventListener(rm.menuItems.music[1], "click", () => {
@@ -182,18 +202,18 @@ window.oncontextmenu = (ele) => {
182
202
  }
183
203
 
184
204
  addEventListener(rm.menuItems.copy, "click", () => {
185
- if (GLOBAL_CONFIG.copyright && selectTextNow.length > GLOBAL_CONFIG.right_menu.limit) {
186
- selectTextNow += `\n\n${GLOBAL_CONFIG.right_menu.author}\n${GLOBAL_CONFIG.right_menu.link}${window.location.href}\n${GLOBAL_CONFIG.right_menu.source}\n${GLOBAL_CONFIG.right_menu.info}`;
205
+ if (Solitude.config.copyright && selectTextNow.length > Solitude.config.right_menu.limit) {
206
+ selectTextNow += `\n\n${Solitude.config.right_menu.author}\n${Solitude.config.right_menu.link}${window.location.href}\n${Solitude.config.right_menu.source}\n${Solitude.config.right_menu.info}`;
187
207
  }
188
208
  rm.copyText(selectTextNow);
189
209
  });
190
210
 
191
- if (utils.saveToLocal.get("commentBarrageSwitch") !== null) {
192
- rm.menuItems.barrage && rm.barrage(!utils.saveToLocal.get("commentBarrageSwitch"));
211
+ if (Solitude.saveToLocal.get("commentBarrageSwitch") !== null) {
212
+ rm.menuItems.barrage && rm.barrage(!Solitude.saveToLocal.get("commentBarrageSwitch"));
193
213
  }
194
214
 
195
215
  addEventListener(rm.menuItems.paste, "click", () => rm.pasteText() && rm.hideRightMenu());
196
- GLOBAL_CONFIG.comment && addEventListener(rm.menuItems.comment, "click", () => rm.hideRightMenu() || sco.toTalk(selectTextNow));
216
+ Solitude.config.comment && addEventListener(rm.menuItems.comment, "click", () => rm.hideRightMenu() || Solitude.toTalk(selectTextNow));
197
217
  addEventListener(rm.menuItems.new, "click", () => window.open(rm.domhref) && rm.hideRightMenu());
198
218
  addEventListener(rm.menuItems.downloadImg, "click", () => rm.downloadImage() && rm.hideRightMenu());
199
219
  addEventListener(rm.menuItems.copyImg, "click", () => rm.copyImage() && rm.hideRightMenu());
@@ -1,3 +1,5 @@
1
+ import { Solitude } from "../core/api.js";
2
+
1
3
  class AlgoliaSearch {
2
4
  constructor() {
3
5
  this.searchInstance = null;
@@ -7,7 +9,7 @@ class AlgoliaSearch {
7
9
  this.elements = this.cacheElements();
8
10
 
9
11
  // Algolia 配置
10
- this.config = GLOBAL_CONFIG.algolia;
12
+ this.config = Solitude.config.algolia;
11
13
 
12
14
  // 初始化
13
15
  this.init();
@@ -91,7 +93,7 @@ class AlgoliaSearch {
91
93
  */
92
94
  showLoading() {
93
95
  if (this.elements.hitsContainer) {
94
- const loadingHtml = `<div class="loading">${GLOBAL_CONFIG.lang?.search?.loading || 'Searching...'}</div>`;
96
+ const loadingHtml = `<div class="loading">${Solitude.config.lang?.search?.loading || 'Searching...'}</div>`;
95
97
  this.elements.hitsContainer.innerHTML = loadingHtml;
96
98
  }
97
99
  }
@@ -137,7 +139,7 @@ class AlgoliaSearch {
137
139
  container: this.elements.inputContainer,
138
140
  showReset: false,
139
141
  showSubmit: false,
140
- placeholder: GLOBAL_CONFIG.lang?.search?.placeholder || 'Search by keywords',
142
+ placeholder: Solitude.config.lang?.search?.placeholder || 'Search by keywords',
141
143
  showLoadingIndicator: false,
142
144
  searchAsYouType: true,
143
145
  });
@@ -159,7 +161,7 @@ class AlgoliaSearch {
159
161
  * 格式化统计文本
160
162
  */
161
163
  formatStatsText(data) {
162
- const statsText = GLOBAL_CONFIG.lang?.search?.hit
164
+ const statsText = Solitude.config.lang?.search?.hit
163
165
  ?.replace(/\$\{hits}/, data.nbHits)
164
166
  ?.replace(/\$\{time}/, data.processingTimeMS) ||
165
167
  `Found ${data.nbHits} results, took ${data.processingTimeMS} ms`;
@@ -188,7 +190,7 @@ class AlgoliaSearch {
188
190
  */
189
191
  renderHitItem(data) {
190
192
  try {
191
- const link = data.permalink || (GLOBAL_CONFIG.root + data.path);
193
+ const link = data.permalink || (Solitude.config.root + data.path);
192
194
  const result = data._highlightResult;
193
195
 
194
196
  // 隐藏加载状态
@@ -214,7 +216,7 @@ class AlgoliaSearch {
214
216
  this.hideLoadingIndicator();
215
217
  this.delayedFocus();
216
218
 
217
- const emptyText = GLOBAL_CONFIG.lang?.search?.empty?.replace(/\$\{query}/, data.query) ||
219
+ const emptyText = Solitude.config.lang?.search?.empty?.replace(/\$\{query}/, data.query) ||
218
220
  `No results found for "${data.query}"`;
219
221
 
220
222
  return `<div id="algolia-hits-empty">${emptyText}</div>`;
@@ -294,7 +296,7 @@ class AlgoliaSearch {
294
296
  bindSearchEvents() {
295
297
  // 搜索按钮
296
298
  if (this.elements.searchButton) {
297
- utils.addEventListenerPjax(this.elements.searchButton, "click", () => this.openSearch());
299
+ Solitude.addEventListenerPjax(this.elements.searchButton, "click", () => this.openSearch());
298
300
  }
299
301
 
300
302
  // 关闭按钮和遮罩
@@ -311,16 +313,16 @@ class AlgoliaSearch {
311
313
  * 绑定右键菜单搜索
312
314
  */
313
315
  bindRightMenuSearch() {
314
- if (GLOBAL_CONFIG.right_menu && this.elements.menuSearch) {
316
+ if (Solitude.config.right_menu && this.elements.menuSearch) {
315
317
  this.elements.menuSearch.addEventListener("click", () => {
316
- rm.hideRightMenu();
318
+ Solitude.hideRightMenu?.();
317
319
  this.openSearch();
318
320
 
319
321
  // 设置选中文本
320
- if (window.selectTextNow) {
322
+ if (Solitude.selectedText) {
321
323
  const searchInput = document.querySelector('.ais-SearchBox-input');
322
324
  if (searchInput) {
323
- searchInput.value = window.selectTextNow;
325
+ searchInput.value = Solitude.selectedText;
324
326
  const event = new Event('input', { bubbles: true });
325
327
  searchInput.dispatchEvent(event);
326
328
  }
@@ -334,7 +336,7 @@ class AlgoliaSearch {
334
336
  */
335
337
  bindPjaxEvents() {
336
338
  window.addEventListener("pjax:complete", () => {
337
- if (!utils.isHidden(this.elements.searchMask)) {
339
+ if (!Solitude.isHidden(this.elements.searchMask)) {
338
340
  this.closeSearch();
339
341
  }
340
342
 
@@ -344,11 +346,11 @@ class AlgoliaSearch {
344
346
  });
345
347
 
346
348
  // PJAX 刷新搜索结果
347
- if (window.pjax && this.searchInstance) {
349
+ if (Solitude.pjax && this.searchInstance) {
348
350
  this.searchInstance.on("render", () => {
349
351
  const hitsElement = document.getElementById("algolia-hits");
350
352
  if (hitsElement) {
351
- window.pjax.refresh(hitsElement);
353
+ Solitude.pjax.refresh(hitsElement);
352
354
  }
353
355
  });
354
356
  }
@@ -379,7 +381,7 @@ class AlgoliaSearch {
379
381
  openSearch() {
380
382
  if (!this.elements.searchMask || !this.elements.searchDialog) return;
381
383
 
382
- utils.animateIn(this.elements.searchMask, "to_show 0.5s");
384
+ Solitude.animateIn(this.elements.searchMask, "to_show 0.5s");
383
385
  this.elements.searchDialog.style.display = "flex";
384
386
 
385
387
  // 延迟聚焦以确保动画完成
@@ -392,7 +394,7 @@ class AlgoliaSearch {
392
394
  window.addEventListener("resize", this.fixSafariHeight);
393
395
 
394
396
  // 暴露到全局作用域以保持兼容性
395
- window.openSearch = () => this.openSearch();
397
+ Solitude.openSearch = () => this.openSearch();
396
398
  }
397
399
 
398
400
  /**
@@ -401,8 +403,8 @@ class AlgoliaSearch {
401
403
  closeSearch() {
402
404
  if (!this.elements.searchMask || !this.elements.searchDialog) return;
403
405
 
404
- utils.animateOut(this.elements.searchDialog, "search_close .5s");
405
- utils.animateOut(this.elements.searchMask, "to_hide 0.5s");
406
+ Solitude.animateOut(this.elements.searchDialog, "search_close .5s");
407
+ Solitude.animateOut(this.elements.searchMask, "to_hide 0.5s");
406
408
  window.removeEventListener("resize", this.fixSafariHeight);
407
409
  }
408
410
 
@@ -435,6 +437,12 @@ class AlgoliaSearch {
435
437
  }
436
438
 
437
439
  // DOM 加载完成后初始化搜索功能
438
- document.addEventListener("DOMContentLoaded", () => {
439
- window.algoliaSearch = new AlgoliaSearch();
440
- });
440
+ const initializeAlgoliaSearch = () => {
441
+ Solitude.algoliaSearch ||= new AlgoliaSearch();
442
+ };
443
+
444
+ if (document.readyState === "loading") {
445
+ document.addEventListener("DOMContentLoaded", initializeAlgoliaSearch, { once: true });
446
+ } else {
447
+ initializeAlgoliaSearch();
448
+ }