hexo-theme-solitude 2.0.6 → 2.0.8

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/source/js/main.js CHANGED
@@ -1,716 +1,708 @@
1
1
  const sidebarFn = () => {
2
- const $toggleMenu = document.getElementById('toggle-menu');
3
- const $mobileSidebarMenus = document.getElementById('sidebar-menus');
4
- const $menuMask = document.getElementById('menu-mask');
5
- const $body = document.body;
2
+ const $toggleMenu = document.getElementById('toggle-menu');
3
+ const $mobileSidebarMenus = document.getElementById('sidebar-menus');
4
+ const $menuMask = document.getElementById('menu-mask');
5
+ const $body = document.body;
6
6
 
7
- const toggleMobileSidebar = (isOpen) => {
8
- utils.sidebarPaddingR();
9
- $body.style.overflow = isOpen ? 'hidden' : '';
10
- $body.style.paddingRight = isOpen ? '' : '';
11
- utils[isOpen ? 'fadeIn' : 'fadeOut']($menuMask, 0.5);
12
- $mobileSidebarMenus.classList[isOpen ? 'add' : 'remove']('open');
7
+ const toggleMobileSidebar = (isOpen) => {
8
+ utils.sidebarPaddingR();
9
+ $body.style.overflow = isOpen ? 'hidden' : '';
10
+ $body.style.paddingRight = isOpen ? '' : '';
11
+ utils[isOpen ? 'fadeIn' : 'fadeOut']($menuMask, 0.5);
12
+ $mobileSidebarMenus.classList[isOpen ? 'add' : 'remove']('open');
13
+ }
14
+ const closeMobileSidebar = () => {
15
+ if ($mobileSidebarMenus.classList.contains('open')) {
16
+ toggleMobileSidebar(false);
13
17
  }
14
- const closeMobileSidebar = () => {
15
- if ($mobileSidebarMenus.classList.contains('open')) {
16
- toggleMobileSidebar(false);
17
- }
18
- }
19
- $toggleMenu.addEventListener('click', () => toggleMobileSidebar(true));
20
- $menuMask.addEventListener('click', closeMobileSidebar);
18
+ }
19
+ $toggleMenu.addEventListener('click', () => toggleMobileSidebar(true));
20
+ $menuMask.addEventListener('click', closeMobileSidebar);
21
21
 
22
- window.addEventListener('resize', () => {
23
- if (utils.isHidden($toggleMenu) && $mobileSidebarMenus.classList.contains('open')) {
24
- closeMobileSidebar();
25
- }
26
- sco.refreshWaterFall();
27
- });
22
+ window.addEventListener('resize', () => {
23
+ if (utils.isHidden($toggleMenu) && $mobileSidebarMenus.classList.contains('open')) {
24
+ closeMobileSidebar();
25
+ }
26
+ sco.refreshWaterFall();
27
+ });
28
28
  }
29
29
  const scrollFn = () => {
30
- const innerHeight = window.innerHeight;
31
- let initTop = 0;
32
- const $header = document.getElementById('page-header');
33
- const throttledScroll = utils.throttle((e) => {
34
- initThemeColor();
35
- const currentTop = window.scrollY || document.documentElement.scrollTop;
36
- const isDown = scrollDirection(currentTop);
37
- if (currentTop > 0) {
38
- if (isDown) {
39
- if ($header.classList.contains('nav-visible')) $header.classList.remove('nav-visible');
40
- } else {
41
- if (!$header.classList.contains('nav-visible')) $header.classList.add('nav-visible');
42
- }
43
- $header.classList.add('nav-fixed');
44
- } else {
45
- $header.classList.remove('nav-fixed', 'nav-visible');
46
- }
47
- }, 200);
48
- window.addEventListener('scroll', (e) => {
49
- throttledScroll(e);
50
- if (window.scrollY === 0) {
51
- $header.classList.remove('nav-fixed', 'nav-visible');
52
- }
53
- });
54
-
55
- function scrollDirection(currentTop) {
56
- const result = currentTop > initTop;
57
- initTop = currentTop;
58
- return result;
30
+ const innerHeight = window.innerHeight;
31
+ let initTop = 0;
32
+ const $header = document.getElementById('page-header');
33
+ const throttledScroll = utils.throttle((e) => {
34
+ initThemeColor();
35
+ const currentTop = window.scrollY || document.documentElement.scrollTop;
36
+ const isDown = scrollDirection(currentTop);
37
+ if (currentTop > 0) {
38
+ if (isDown) {
39
+ if ($header.classList.contains('nav-visible')) $header.classList.remove('nav-visible');
40
+ } else {
41
+ if (!$header.classList.contains('nav-visible')) $header.classList.add('nav-visible');
42
+ }
43
+ $header.classList.add('nav-fixed');
44
+ } else {
45
+ $header.classList.remove('nav-fixed', 'nav-visible');
46
+ }
47
+ }, 200);
48
+ window.addEventListener('scroll', (e) => {
49
+ throttledScroll(e);
50
+ if (window.scrollY === 0) {
51
+ $header.classList.remove('nav-fixed', 'nav-visible');
59
52
  }
53
+ });
54
+
55
+ function scrollDirection(currentTop) {
56
+ const result = currentTop > initTop;
57
+ initTop = currentTop;
58
+ return result;
59
+ }
60
60
  }
61
61
  const percent = () => {
62
- const docEl = document.documentElement;
63
- const body = document.body;
64
- const scrollPos = window.pageYOffset || docEl.scrollTop;
65
- const totalScrollableHeight = Math.max(body.scrollHeight, docEl.scrollHeight, body.offsetHeight, docEl.offsetHeight, body.clientHeight, docEl.clientHeight) - docEl.clientHeight;
66
- const scrolledPercent = Math.round((scrollPos / totalScrollableHeight) * 100);
67
- const navToTop = document.querySelector("#nav-totop");
68
- const percentDisplay = document.querySelector("#percent");
69
- const isNearEnd = (window.scrollY + docEl.clientHeight) >= (document.getElementById("post-comment") || document.getElementById("footer")).offsetTop;
70
- navToTop.classList.toggle("long", isNearEnd || scrolledPercent > 90);
71
- percentDisplay.textContent = isNearEnd || scrolledPercent > 90 ? GLOBAL_CONFIG.lang.backtop : scrolledPercent;
72
- document.querySelectorAll(".needEndHide").forEach(item => item.classList.toggle("hide", totalScrollableHeight - scrollPos < 100));
62
+ const docEl = document.documentElement;
63
+ const body = document.body;
64
+ const scrollPos = window.pageYOffset || docEl.scrollTop;
65
+ const totalScrollableHeight = Math.max(body.scrollHeight, docEl.scrollHeight, body.offsetHeight, docEl.offsetHeight, body.clientHeight, docEl.clientHeight) - docEl.clientHeight;
66
+ const scrolledPercent = Math.round((scrollPos / totalScrollableHeight) * 100);
67
+ const navToTop = document.querySelector("#nav-totop");
68
+ const percentDisplay = document.querySelector("#percent");
69
+ const isNearEnd = (window.scrollY + docEl.clientHeight) >= (document.getElementById("post-comment") || document.getElementById("footer")).offsetTop;
70
+ navToTop.classList.toggle("long", isNearEnd || scrolledPercent > 90);
71
+ percentDisplay.textContent = isNearEnd || scrolledPercent > 90 ? GLOBAL_CONFIG.lang.backtop : scrolledPercent;
72
+ document.querySelectorAll(".needEndHide").forEach(item => item.classList.toggle("hide", totalScrollableHeight - scrollPos < 100));
73
73
  }
74
74
  const showTodayCard = () => {
75
- const el = document.getElementById('todayCard');
76
- const topGroup = document.querySelector('.topGroup');
77
- topGroup?.addEventListener('mouseleave', () => el?.classList.remove('hide'));
75
+ const el = document.getElementById('todayCard');
76
+ const topGroup = document.querySelector('.topGroup');
77
+ topGroup?.addEventListener('mouseleave', () => el?.classList.remove('hide'));
78
78
  }
79
79
  const initObserver = () => {
80
- const commentElement = document.getElementById("post-comment");
81
- const paginationElement = document.getElementById("pagination");
82
- const commentBarrageElement = document.querySelector(".comment-barrage");
83
- if (commentElement && paginationElement) {
84
- const observer = new IntersectionObserver(entries => {
85
- entries.forEach(entry => {
86
- const action = entry.isIntersecting ? 'add' : 'remove';
87
- paginationElement.classList[action]("show-window");
88
- if (GLOBAL_CONFIG.comment.commentBarrage) {
89
- commentBarrageElement.style.bottom = entry.isIntersecting ? "-200px" : "0px";
90
- }
91
- });
92
- });
93
- observer.observe(commentElement);
94
- }
80
+ const commentElement = document.getElementById("post-comment");
81
+ const paginationElement = document.getElementById("pagination");
82
+ const commentBarrageElement = document.querySelector(".comment-barrage");
83
+ if (commentElement && paginationElement) {
84
+ const observer = new IntersectionObserver(entries => {
85
+ entries.forEach(entry => {
86
+ const action = entry.isIntersecting ? 'add' : 'remove';
87
+ paginationElement.classList[action]("show-window");
88
+ if (GLOBAL_CONFIG.comment.commentBarrage) {
89
+ commentBarrageElement.style.bottom = entry.isIntersecting ? "-200px" : "0px";
90
+ }
91
+ });
92
+ });
93
+ observer.observe(commentElement);
94
+ }
95
95
  };
96
96
  const addCopyright = () => {
97
- if (!GLOBAL_CONFIG.copyright) return;
98
- const {limit, author, link, source, info} = GLOBAL_CONFIG.copyright;
99
- document.body.addEventListener('copy', (e) => {
100
- e.preventDefault();
101
- const copyText = window.getSelection().toString();
102
- const text = copyText.length > limit ? `${copyText}\n\n${author}\n${link}${window.location.href}\n${source}\n${info}` : copyText;
103
- e.clipboardData.setData('text', text);
104
- });
97
+ if (!GLOBAL_CONFIG.copyright) return;
98
+ const {limit, author, link, source, info} = GLOBAL_CONFIG.copyright;
99
+ document.body.addEventListener('copy', (e) => {
100
+ e.preventDefault();
101
+ const copyText = window.getSelection().toString();
102
+ const text = copyText.length > limit ? `${copyText}\n\n${author}\n${link}${window.location.href}\n${source}\n${info}` : copyText;
103
+ e.clipboardData.setData('text', text);
104
+ });
105
105
  };
106
106
  const asideStatus = () => {
107
- const status = utils.saveToLocal.get('aside-status');
108
- document.documentElement.classList.toggle('hide-aside', status === 'hide');
107
+ const status = utils.saveToLocal.get('aside-status');
108
+ document.documentElement.classList.toggle('hide-aside', status === 'hide');
109
109
  }
110
110
 
111
111
  function initThemeColor() {
112
- const currentTop = window.scrollY || document.documentElement.scrollTop;
113
- const themeColor = currentTop > 0 ? '--efu-card-bg' : PAGE_CONFIG.is_post ? '--efu-main' : '--efu-background';
114
- applyThemeColor(getComputedStyle(document.documentElement).getPropertyValue(themeColor));
112
+ const currentTop = window.scrollY || document.documentElement.scrollTop;
113
+ const themeColor = currentTop > 0 ? '--efu-card-bg' : PAGE_CONFIG.is_post ? '--efu-main' : '--efu-background';
114
+ applyThemeColor(getComputedStyle(document.documentElement).getPropertyValue(themeColor));
115
115
  }
116
116
 
117
117
  function applyThemeColor(color) {
118
- const themeColorMeta = document.querySelector('meta[name="theme-color"]');
119
- const appleMobileWebAppMeta = document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]');
120
- themeColorMeta?.setAttribute("content", color);
121
- appleMobileWebAppMeta?.setAttribute("content", color);
122
- if (window.matchMedia("(display-mode: standalone)").matches) {
123
- document.body.style.backgroundColor = color;
124
- }
118
+ const themeColorMeta = document.querySelector('meta[name="theme-color"]');
119
+ const appleMobileWebAppMeta = document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]');
120
+ themeColorMeta?.setAttribute("content", color);
121
+ appleMobileWebAppMeta?.setAttribute("content", color);
122
+ if (window.matchMedia("(display-mode: standalone)").matches) {
123
+ document.body.style.backgroundColor = color;
124
+ }
125
125
  }
126
126
 
127
127
  const handleThemeChange = mode => {
128
- const themeChange = window.globalFn?.themeChange || {}
129
- for (let key in themeChange) {
130
- themeChange[key](mode)
131
- }
128
+ const themeChange = window.globalFn?.themeChange || {}
129
+ for (let key in themeChange) {
130
+ themeChange[key](mode)
131
+ }
132
132
  }
133
133
  const sco = {
134
- lastSayHello: "",
135
- wasPageHidden: false,
136
- musicPlaying: false,
137
- hideCookie() {
138
- const cookiesWindow = document.getElementById("cookies-window");
139
- if (cookiesWindow) {
140
- setTimeout(() => {
141
- cookiesWindow.classList.add("cw-hide");
142
- setTimeout(() => cookiesWindow.style.display = "none", 1000);
143
- }, 3000);
144
- }
145
- },
146
- scrollTo(elementId) {
147
- const targetElement = document.getElementById(elementId);
148
- if (targetElement) {
149
- const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - 80;
150
- window.scroll({
151
- top: targetPosition,
152
- behavior: "smooth"
153
- });
154
- }
155
- },
156
- musicToggle() {
157
- const $music = document.querySelector('#nav-music');
158
- const $meting = document.querySelector('meting-js');
159
- const $console = document.getElementById('consoleMusic');
160
- const $rm_text = document.querySelector('#menu-music-toggle span');
161
- const $rm_icon = document.querySelector('#menu-music-toggle i');
162
- this.musicPlaying = !this.musicPlaying;
163
- $music.classList.toggle("playing", this.musicPlaying);
164
- $console.classList.toggle("on", this.musicPlaying);
165
- if (this.musicPlaying) {
166
- $meting.aplayer.play();
167
- rm?.menuItems.music[0] && ($rm_text.textContent = GLOBAL_CONFIG.right_menu.music.stop) && ($rm_icon.className = 'solitude st-pause-fill')
168
- } else {
169
- $meting.aplayer.pause();
170
- rm?.menuItems.music[0] && ($rm_text.textContent = GLOBAL_CONFIG.right_menu.music.start) && ($rm_icon.className = 'solitude st-play-fill')
171
- }
172
- },
173
- switchCommentBarrage() {
174
- let commentBarrageElement = document.querySelector(".comment-barrage");
175
- if (!commentBarrageElement) return;
176
- const isDisplayed = window.getComputedStyle(commentBarrageElement).display === "flex";
177
- commentBarrageElement.style.display = isDisplayed ? "none" : "flex";
178
- document.querySelector("#consoleCommentBarrage").classList.toggle("on", !isDisplayed);
179
- utils.saveToLocal.set("commentBarrageSwitch", !isDisplayed, .2);
180
- rm?.menuItems.barrage && rm.barrage(isDisplayed)
181
- },
182
- switchHideAside() {
183
- const htmlClassList = document.documentElement.classList;
184
- const consoleHideAside = document.querySelector("#consoleHideAside");
185
- const isHideAside = htmlClassList.contains("hide-aside");
186
- utils.saveToLocal.set("aside-status", isHideAside ? "show" : "hide", 1);
187
- htmlClassList.toggle("hide-aside");
188
- consoleHideAside.classList.toggle("on", !isHideAside);
189
- },
190
- switchKeyboard() {
191
- this.sco_keyboards = !this.sco_keyboards;
192
- const consoleKeyboard = document.querySelector("#consoleKeyboard");
193
- const keyboardFunction = this.sco_keyboards ? openKeyboard : closeKeyboard;
194
- consoleKeyboard.classList.toggle("on", this.sco_keyboards);
195
- keyboardFunction();
196
- localStorage.setItem("keyboard", this.sco_keyboards);
197
- document.getElementById('keyboard-tips')?.classList.remove('show');
198
- },
199
- initConsoleState() {
200
- const consoleHideAside = document.querySelector("#consoleHideAside");
201
- if(!consoleHideAside) return;
202
- consoleHideAside.classList.toggle("on", document.documentElement.classList.contains("hide-aside"));
203
- },
204
- changeSayHelloText() {
205
- const greetings = GLOBAL_CONFIG.aside.sayhello2;
206
- const greetingElement = document.getElementById("author-info__sayhi");
207
- let randomGreeting;
208
- do {
209
- randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
210
- } while (randomGreeting === this.lastSayHello);
211
- greetingElement.textContent = randomGreeting;
212
- this.lastSayHello = randomGreeting;
213
- },
214
- switchDarkMode() {
215
- const isDarkMode = document.documentElement.getAttribute('data-theme') === 'dark';
216
- const newMode = isDarkMode ? 'light' : 'dark';
217
- document.documentElement.setAttribute('data-theme', newMode);
218
- utils.saveToLocal.set('theme', newMode, 0.02);
219
- utils.snackbarShow(GLOBAL_CONFIG.lang.theme[newMode], false, 2000);
220
- if (typeof rm === 'object') rm.mode(!isDarkMode) && rm.hideRightMenu();
221
- handleThemeChange(newMode);
222
- },
223
- hideTodayCard: () => document.getElementById('todayCard').classList.add('hide'),
224
- toTop: () => utils.scrollToDest(0),
225
- showConsole: () => document.getElementById('console')?.classList.toggle('show', true),
226
- hideConsole: () => document.getElementById('console')?.classList.remove('show'),
227
- refreshWaterFall() {
228
- const observer = new IntersectionObserver((entries) => {
229
- entries.forEach(entry => {
230
- if (entry.isIntersecting) {
231
- setTimeout(() => {
232
- waterfall(entry.target) || entry.target.classList.add('show');
233
- }, 300);
234
- }
235
- });
236
- });
237
- document.querySelectorAll('.waterfall').forEach(el => observer.observe(el));
238
- },
239
- addRuntime() {
240
- let el = document.getElementById('runtimeshow');
241
- el && GLOBAL_CONFIG.runtime && (el.innerText = utils.timeDiff(new Date(GLOBAL_CONFIG.runtime), new Date()) + GLOBAL_CONFIG.lang.day);
242
- },
243
- toTalk(txt) {
244
- const inputs = ["#wl-edit", ".el-textarea__inner", "#veditor", ".atk-textarea"];
245
- inputs.forEach(selector => {
246
- const el = document.querySelector(selector);
247
- if (el) {
248
- el.dispatchEvent(new Event('input', {bubble: true, cancelable: true}));
249
- el.value = '> ' + txt.replace(/\n/g, '\n> ') + '\n\n';
250
- utils.scrollToDest(utils.getEleTop(document.getElementById('post-comment')), 300);
251
- el.focus();
252
- el.setSelectionRange(-1, -1);
253
- }
254
- });
255
- utils.snackbarShow(GLOBAL_CONFIG.lang.totalk, false, 2000);
256
- },
257
- initbbtalk() {
258
- const bberTalkElement = document.querySelector('#bber-talk');
259
- if (bberTalkElement) {
260
- new Swiper('.swiper-container', {
261
- direction: 'vertical',
262
- loop: true,
263
- autoplay: {
264
- delay: 3000,
265
- pauseOnMouseEnter: true
266
- },
267
- });
134
+ lastSayHello: "",
135
+ wasPageHidden: false,
136
+ musicPlaying: false,
137
+ scrollTo(elementId) {
138
+ const targetElement = document.getElementById(elementId);
139
+ if (targetElement) {
140
+ const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - 80;
141
+ window.scroll({
142
+ top: targetPosition,
143
+ behavior: "smooth"
144
+ });
145
+ }
146
+ },
147
+ musicToggle() {
148
+ const $music = document.querySelector('#nav-music');
149
+ const $meting = document.querySelector('meting-js');
150
+ const $console = document.getElementById('consoleMusic');
151
+ const $rm_text = document.querySelector('#menu-music-toggle span');
152
+ const $rm_icon = document.querySelector('#menu-music-toggle i');
153
+ this.musicPlaying = !this.musicPlaying;
154
+ $music.classList.toggle("playing", this.musicPlaying);
155
+ $console.classList.toggle("on", this.musicPlaying);
156
+ if (this.musicPlaying) {
157
+ $meting.aplayer.play();
158
+ rm?.menuItems.music[0] && ($rm_text.textContent = GLOBAL_CONFIG.right_menu.music.stop) && ($rm_icon.className = 'solitude st-pause-fill')
159
+ } else {
160
+ $meting.aplayer.pause();
161
+ rm?.menuItems.music[0] && ($rm_text.textContent = GLOBAL_CONFIG.right_menu.music.start) && ($rm_icon.className = 'solitude st-play-fill')
162
+ }
163
+ },
164
+ switchCommentBarrage() {
165
+ let commentBarrageElement = document.querySelector(".comment-barrage");
166
+ if (!commentBarrageElement) return;
167
+ const isDisplayed = window.getComputedStyle(commentBarrageElement).display === "flex";
168
+ commentBarrageElement.style.display = isDisplayed ? "none" : "flex";
169
+ document.querySelector("#consoleCommentBarrage").classList.toggle("on", !isDisplayed);
170
+ utils.saveToLocal.set("commentBarrageSwitch", !isDisplayed, .2);
171
+ rm?.menuItems.barrage && rm.barrage(isDisplayed)
172
+ },
173
+ switchHideAside() {
174
+ const htmlClassList = document.documentElement.classList;
175
+ const consoleHideAside = document.querySelector("#consoleHideAside");
176
+ const isHideAside = htmlClassList.contains("hide-aside");
177
+ utils.saveToLocal.set("aside-status", isHideAside ? "show" : "hide", 1);
178
+ htmlClassList.toggle("hide-aside");
179
+ consoleHideAside.classList.toggle("on", !isHideAside);
180
+ },
181
+ switchKeyboard() {
182
+ this.sco_keyboards = !this.sco_keyboards;
183
+ const consoleKeyboard = document.querySelector("#consoleKeyboard");
184
+ const keyboardFunction = this.sco_keyboards ? openKeyboard : closeKeyboard;
185
+ consoleKeyboard.classList.toggle("on", this.sco_keyboards);
186
+ keyboardFunction();
187
+ localStorage.setItem("keyboard", this.sco_keyboards);
188
+ document.getElementById('keyboard-tips')?.classList.remove('show');
189
+ },
190
+ initConsoleState() {
191
+ const consoleHideAside = document.querySelector("#consoleHideAside");
192
+ if (!consoleHideAside) return;
193
+ consoleHideAside.classList.toggle("on", document.documentElement.classList.contains("hide-aside"));
194
+ },
195
+ changeSayHelloText() {
196
+ const greetings = GLOBAL_CONFIG.aside.sayhello2;
197
+ const greetingElement = document.getElementById("author-info__sayhi");
198
+ let randomGreeting;
199
+ do {
200
+ randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
201
+ } while (randomGreeting === this.lastSayHello);
202
+ greetingElement.textContent = randomGreeting;
203
+ this.lastSayHello = randomGreeting;
204
+ },
205
+ switchDarkMode() {
206
+ const isDarkMode = document.documentElement.getAttribute('data-theme') === 'dark';
207
+ const newMode = isDarkMode ? 'light' : 'dark';
208
+ document.documentElement.setAttribute('data-theme', newMode);
209
+ utils.saveToLocal.set('theme', newMode, 0.02);
210
+ utils.snackbarShow(GLOBAL_CONFIG.lang.theme[newMode], false, 2000);
211
+ if (typeof rm === 'object') rm.mode(!isDarkMode) && rm.hideRightMenu();
212
+ handleThemeChange(newMode);
213
+ },
214
+ hideTodayCard: () => document.getElementById('todayCard').classList.add('hide'),
215
+ toTop: () => utils.scrollToDest(0),
216
+ showConsole: () => document.getElementById('console')?.classList.toggle('show', true),
217
+ hideConsole: () => document.getElementById('console')?.classList.remove('show'),
218
+ refreshWaterFall() {
219
+ const observer = new IntersectionObserver((entries) => {
220
+ entries.forEach(entry => {
221
+ if (entry.isIntersecting) {
222
+ setTimeout(() => {
223
+ waterfall(entry.target) || entry.target.classList.add('show');
224
+ }, 300);
268
225
  }
269
- },
270
- addPhotoFigcaption() {
271
- document.querySelectorAll('#article-container img:not(.gallery-item img)').forEach(image => {
272
- const captionText = image.getAttribute('alt');
273
- captionText && image.insertAdjacentHTML('afterend', `<div class="img-alt is-center">${captionText}</div>`);
274
- });
275
- },
276
- scrollToComment: () => utils.scrollToDest(utils.getEleTop(document.getElementById('post-comment')), 300),
277
- setTimeState() {
278
- const el = document.getElementById('author-info__sayhi');
279
- if (el) {
280
- const hours = new Date().getHours();
281
- const lang = GLOBAL_CONFIG.aside.sayhello;
226
+ });
227
+ });
228
+ document.querySelectorAll('.waterfall').forEach(el => observer.observe(el));
229
+ },
230
+ addRuntime() {
231
+ let el = document.getElementById('runtimeshow');
232
+ el && GLOBAL_CONFIG.runtime && (el.innerText = utils.timeDiff(new Date(GLOBAL_CONFIG.runtime), new Date()) + GLOBAL_CONFIG.lang.day);
233
+ },
234
+ toTalk(txt) {
235
+ const inputs = ["#wl-edit", ".el-textarea__inner", "#veditor", ".atk-textarea"];
236
+ inputs.forEach(selector => {
237
+ const el = document.querySelector(selector);
238
+ if (el) {
239
+ el.dispatchEvent(new Event('input', {bubble: true, cancelable: true}));
240
+ el.value = '> ' + txt.replace(/\n/g, '\n> ') + '\n\n';
241
+ utils.scrollToDest(utils.getEleTop(document.getElementById('post-comment')), 300);
242
+ el.focus();
243
+ el.setSelectionRange(-1, -1);
244
+ }
245
+ });
246
+ utils.snackbarShow(GLOBAL_CONFIG.lang.totalk, false, 2000);
247
+ },
248
+ initbbtalk() {
249
+ const bberTalkElement = document.querySelector('#bber-talk');
250
+ if (bberTalkElement) {
251
+ new Swiper('.swiper-container', {
252
+ direction: 'vertical',
253
+ loop: true,
254
+ autoplay: {
255
+ delay: 3000,
256
+ pauseOnMouseEnter: true
257
+ },
258
+ });
259
+ }
260
+ },
261
+ addPhotoFigcaption() {
262
+ document.querySelectorAll('#article-container img:not(.gallery-item img)').forEach(image => {
263
+ const captionText = image.getAttribute('alt');
264
+ captionText && image.insertAdjacentHTML('afterend', `<div class="img-alt is-center">${captionText}</div>`);
265
+ });
266
+ },
267
+ scrollToComment: () => utils.scrollToDest(utils.getEleTop(document.getElementById('post-comment')), 300),
268
+ setTimeState() {
269
+ const el = document.getElementById('author-info__sayhi');
270
+ if (el) {
271
+ const hours = new Date().getHours();
272
+ const lang = GLOBAL_CONFIG.aside.sayhello;
282
273
 
283
- const localData = getLocalData(['twikoo', 'WALINE_USER_META', 'WALINE_USER', '_v_Cache_Meta', 'ArtalkUser']);
274
+ const localData = getLocalData(['twikoo', 'WALINE_USER_META', 'WALINE_USER', '_v_Cache_Meta', 'ArtalkUser']);
284
275
 
285
- function getLocalData(keys) {
286
- for (let key of keys) {
287
- const data = localStorage.getItem(key);
288
- if (data) {
289
- return JSON.parse(data);
290
- }
291
- }
292
- return null;
293
- };
294
- const nick = localData ? (localData.nick ? localData.nick : localData.display_name) : null;
276
+ function getLocalData(keys) {
277
+ for (let key of keys) {
278
+ const data = localStorage.getItem(key);
279
+ if (data) {
280
+ return JSON.parse(data);
281
+ }
282
+ }
283
+ return null;
284
+ };
285
+ const nick = localData ? (localData.nick ? localData.nick : localData.display_name) : null;
295
286
 
296
- let prefix;
297
- if (this.wasPageHidden) {
298
- prefix = GLOBAL_CONFIG.aside.sayhello3.back + nick;
299
- this.wasPageHidden = false;
300
- } else {
301
- prefix = GLOBAL_CONFIG.aside.sayhello3.prefix + nick;
302
- }
287
+ let prefix;
288
+ if (this.wasPageHidden) {
289
+ prefix = GLOBAL_CONFIG.aside.sayhello3.back + nick;
290
+ this.wasPageHidden = false;
291
+ } else {
292
+ prefix = GLOBAL_CONFIG.aside.sayhello3.prefix + nick;
293
+ }
303
294
 
304
- const greetings = [
305
- {start: 0, end: 5, text: nick ? prefix : lang.goodnight},
306
- {start: 6, end: 10, text: nick ? prefix : lang.morning},
307
- {start: 11, end: 14, text: nick ? prefix : lang.noon},
308
- {start: 15, end: 18, text: nick ? prefix : lang.afternoon},
309
- {start: 19, end: 24, text: nick ? prefix : lang.night},
310
- ];
311
- const greeting = greetings.find(g => hours >= g.start && hours <= g.end);
312
- el.innerText = greeting.text;
313
- }
314
- },
315
- tagPageActive() {
316
- const decodedPath = decodeURIComponent(window.location.pathname);
317
- const isTagPage = /\/tags\/.*?\//.test(decodedPath);
318
- if (isTagPage) {
319
- const tag = decodedPath.split("/").slice(-2, -1)[0];
320
- const tagElement = document.getElementById(tag);
321
- if (tagElement) {
322
- document.querySelectorAll("a.select").forEach(link => {
323
- link.classList.remove("select");
324
- });
325
- tagElement.classList.add("select");
326
- }
327
- }
328
- },
329
- categoriesBarActive() {
330
- const categoryBar = document.querySelector("#category-bar");
331
- const currentPath = decodeURIComponent(window.location.pathname);
332
- const isHomePage = currentPath === GLOBAL_CONFIG.root;
333
- if (categoryBar) {
334
- const categoryItems = categoryBar.querySelectorAll(".category-bar-item");
335
- categoryItems.forEach(item => item.classList.remove("select"));
336
- const activeItemId = isHomePage ? "category-bar-home" : currentPath.split("/").slice(-2, -1)[0];
337
- const activeItem = document.getElementById(activeItemId);
338
- if (activeItem) {
339
- activeItem.classList.add("select");
340
- }
341
- }
342
- },
343
- scrollCategoryBarToRight() {
344
- const scrollBar = document.getElementById("category-bar-items");
345
- const nextElement = document.getElementById("category-bar-next");
346
- if (scrollBar) {
347
- const isScrollBarAtEnd = () => scrollBar.scrollLeft + scrollBar.clientWidth >= scrollBar.scrollWidth - 8;
348
- const scroll = () => {
349
- if (isScrollBarAtEnd()) {
350
- scrollBar.scroll({left: 0, behavior: "smooth"});
351
- } else {
352
- scrollBar.scrollBy({left: scrollBar.clientWidth, behavior: "smooth"});
353
- }
354
- };
355
- scrollBar.addEventListener("scroll", () => {
356
- clearTimeout(this.timeoutId);
357
- this.timeoutId = setTimeout(() => {
358
- nextElement.style.transform = isScrollBarAtEnd() ? "rotate(180deg)" : "";
359
- }, 150);
360
- });
361
- scroll();
362
- }
363
- },
364
- openAllTags() {
365
- document.querySelectorAll(".card-allinfo .card-tag-cloud").forEach(tagCloudElement => tagCloudElement.classList.add("all-tags"));
366
- document.getElementById("more-tags-btn")?.remove();
367
- },
368
- listenToPageInputPress() {
369
- const toGroup = document.querySelector(".toPageGroup")
370
- const pageText = document.getElementById("toPageText");
371
- if (!pageText) return;
372
- const pageButton = document.getElementById("toPageButton");
373
- const pageNumbers = document.querySelectorAll(".page-number");
374
- const lastPageNumber = +pageNumbers[pageNumbers.length - 1].textContent;
375
- if (!pageText || lastPageNumber === 1) {
376
- toGroup.style.display = "none";
377
- return
378
- }
379
- pageText.addEventListener("keydown", (event) => {
380
- if (event.keyCode === 13) {
381
- sco.toPage();
382
- pjax.loadUrl(pageButton.href);
383
- }
384
- });
385
- pageText.addEventListener("input", () => {
386
- pageButton.classList.toggle("haveValue", pageText.value !== "" && pageText.value !== "0");
387
- if (+pageText.value > lastPageNumber) {
388
- pageText.value = lastPageNumber;
389
- }
295
+ const greetings = [
296
+ {start: 0, end: 5, text: nick ? prefix : lang.goodnight},
297
+ {start: 6, end: 10, text: nick ? prefix : lang.morning},
298
+ {start: 11, end: 14, text: nick ? prefix : lang.noon},
299
+ {start: 15, end: 18, text: nick ? prefix : lang.afternoon},
300
+ {start: 19, end: 24, text: nick ? prefix : lang.night},
301
+ ];
302
+ const greeting = greetings.find(g => hours >= g.start && hours <= g.end);
303
+ el.innerText = greeting.text;
304
+ }
305
+ },
306
+ tagPageActive() {
307
+ const decodedPath = decodeURIComponent(window.location.pathname);
308
+ const isTagPage = /\/tags\/.*?\//.test(decodedPath);
309
+ if (isTagPage) {
310
+ const tag = decodedPath.split("/").slice(-2, -1)[0];
311
+ const tagElement = document.getElementById(tag);
312
+ if (tagElement) {
313
+ document.querySelectorAll("a.select").forEach(link => {
314
+ link.classList.remove("select");
390
315
  });
391
- },
392
- addNavBackgroundInit() {
393
- const scrollTop = document.documentElement.scrollTop;
394
- (scrollTop !== 0) && document.getElementById("page-header").classList.add("nav-fixed", "nav-visible");
395
- },
396
- toPage() {
397
- const pageNumbers = document.querySelectorAll(".page-number");
398
- const maxPageNumber = parseInt(pageNumbers[pageNumbers.length - 1].innerHTML);
399
- const inputElement = document.getElementById("toPageText");
400
- const inputPageNumber = parseInt(inputElement.value);
401
- document.getElementById("toPageButton").href = (!isNaN(inputPageNumber) && inputPageNumber <= maxPageNumber && inputPageNumber > 1)
402
- ? window.location.href.replace(/\/page\/\d+\/$/, "/") + "page/" + inputPageNumber + "/"
403
- : '/';
404
- },
405
- owoBig(owoSelector) {
406
- let owoBig = document.getElementById('owo-big');
407
- if (!owoBig) {
408
- owoBig = document.createElement('div');
409
- owoBig.id = 'owo-big';
410
- document.body.appendChild(owoBig);
411
- }
412
- const showOwoBig = event => {
413
- const target = event.target;
414
- const owoItem = target.closest(owoSelector.item);
415
- if (owoItem && target.closest(owoSelector.body)) {
416
- const imgSrc = owoItem.querySelector('img')?.src;
417
- if (imgSrc) {
418
- owoBig.innerHTML = `<img src="${imgSrc}" style="max-width: 100%; height: auto;">`;
419
- owoBig.style.display = 'block';
420
- positionOwoBig(owoItem);
421
- }
422
- }
423
- };
424
- const hideOwoBig = event => {
425
- if (event.target.closest(owoSelector.item) && event.target.closest(owoSelector.body)) {
426
- owoBig.style.display = 'none';
427
- }
428
- };
429
- const positionOwoBig = owoItem => {
430
- const itemRect = owoItem.getBoundingClientRect();
431
- owoBig.style.left = `${itemRect.left - (owoBig.offsetWidth / 4)}px`;
432
- owoBig.style.top = `${itemRect.top}px`;
316
+ tagElement.classList.add("select");
317
+ }
318
+ }
319
+ },
320
+ categoriesBarActive() {
321
+ const categoryBar = document.querySelector("#category-bar");
322
+ const currentPath = decodeURIComponent(window.location.pathname);
323
+ const isHomePage = currentPath === GLOBAL_CONFIG.root;
324
+ if (categoryBar) {
325
+ const categoryItems = categoryBar.querySelectorAll(".category-bar-item");
326
+ categoryItems.forEach(item => item.classList.remove("select"));
327
+ const activeItemId = isHomePage ? "category-bar-home" : currentPath.split("/").slice(-2, -1)[0];
328
+ const activeItem = document.getElementById(activeItemId);
329
+ if (activeItem) {
330
+ activeItem.classList.add("select");
331
+ }
332
+ }
333
+ },
334
+ scrollCategoryBarToRight() {
335
+ const scrollBar = document.getElementById("category-bar-items");
336
+ const nextElement = document.getElementById("category-bar-next");
337
+ if (scrollBar) {
338
+ const isScrollBarAtEnd = () => scrollBar.scrollLeft + scrollBar.clientWidth >= scrollBar.scrollWidth - 8;
339
+ const scroll = () => {
340
+ if (isScrollBarAtEnd()) {
341
+ scrollBar.scroll({left: 0, behavior: "smooth"});
342
+ } else {
343
+ scrollBar.scrollBy({left: scrollBar.clientWidth, behavior: "smooth"});
433
344
  }
434
- document.addEventListener('mouseover', showOwoBig);
435
- document.addEventListener('mouseout', hideOwoBig);
436
- },
437
- changeTimeFormat(selector) {
438
- selector.forEach(item => {
439
- const timeVal = item.getAttribute('datetime')
440
- item.textContent = utils.diffDate(timeVal, true)
441
- item.style.display = 'inline'
442
- })
443
- },
444
- switchComments() {
445
- const switchBtn = document.getElementById('switch-btn')
446
- if (!switchBtn) return
447
- let switchDone = false
448
- const commentContainer = document.getElementById('post-comment')
449
- const handleSwitchBtn = () => {
450
- commentContainer.classList.toggle('move')
451
- if (!switchDone && typeof loadTwoComment === 'function') {
452
- switchDone = true
453
- loadTwoComment()
454
- }
345
+ };
346
+ scrollBar.addEventListener("scroll", () => {
347
+ clearTimeout(this.timeoutId);
348
+ this.timeoutId = setTimeout(() => {
349
+ nextElement.style.transform = isScrollBarAtEnd() ? "rotate(180deg)" : "";
350
+ }, 150);
351
+ });
352
+ scroll();
353
+ }
354
+ },
355
+ openAllTags() {
356
+ document.querySelectorAll(".card-allinfo .card-tag-cloud").forEach(tagCloudElement => tagCloudElement.classList.add("all-tags"));
357
+ document.getElementById("more-tags-btn")?.remove();
358
+ },
359
+ listenToPageInputPress() {
360
+ const toGroup = document.querySelector(".toPageGroup")
361
+ const pageText = document.getElementById("toPageText");
362
+ if (!pageText) return;
363
+ const pageButton = document.getElementById("toPageButton");
364
+ const pageNumbers = document.querySelectorAll(".page-number");
365
+ const lastPageNumber = +pageNumbers[pageNumbers.length - 1].textContent;
366
+ if (!pageText || lastPageNumber === 1) {
367
+ toGroup.style.display = "none";
368
+ return
369
+ }
370
+ pageText.addEventListener("keydown", (event) => {
371
+ if (event.keyCode === 13) {
372
+ sco.toPage();
373
+ pjax.loadUrl(pageButton.href);
374
+ }
375
+ });
376
+ pageText.addEventListener("input", () => {
377
+ pageButton.classList.toggle("haveValue", pageText.value !== "" && pageText.value !== "0");
378
+ if (+pageText.value > lastPageNumber) {
379
+ pageText.value = lastPageNumber;
380
+ }
381
+ });
382
+ },
383
+ addNavBackgroundInit() {
384
+ const scrollTop = document.documentElement.scrollTop;
385
+ (scrollTop !== 0) && document.getElementById("page-header").classList.add("nav-fixed", "nav-visible");
386
+ },
387
+ toPage() {
388
+ const pageNumbers = document.querySelectorAll(".page-number");
389
+ const maxPageNumber = parseInt(pageNumbers[pageNumbers.length - 1].innerHTML);
390
+ const inputElement = document.getElementById("toPageText");
391
+ const inputPageNumber = parseInt(inputElement.value);
392
+ document.getElementById("toPageButton").href = (!isNaN(inputPageNumber) && inputPageNumber <= maxPageNumber && inputPageNumber > 1)
393
+ ? window.location.href.replace(/\/page\/\d+\/$/, "/") + "page/" + inputPageNumber + "/"
394
+ : '/';
395
+ },
396
+ owoBig(owoSelector) {
397
+ let owoBig = document.getElementById('owo-big');
398
+ if (!owoBig) {
399
+ owoBig = document.createElement('div');
400
+ owoBig.id = 'owo-big';
401
+ document.body.appendChild(owoBig);
402
+ }
403
+ const showOwoBig = event => {
404
+ const target = event.target;
405
+ const owoItem = target.closest(owoSelector.item);
406
+ if (owoItem && target.closest(owoSelector.body)) {
407
+ const imgSrc = owoItem.querySelector('img')?.src;
408
+ if (imgSrc) {
409
+ owoBig.innerHTML = `<img src="${imgSrc}" style="max-width: 100%; height: auto;">`;
410
+ owoBig.style.display = 'block';
411
+ positionOwoBig(owoItem);
455
412
  }
456
- utils.addEventListenerPjax(switchBtn, 'click', handleSwitchBtn)
413
+ }
414
+ };
415
+ const hideOwoBig = event => {
416
+ if (event.target.closest(owoSelector.item) && event.target.closest(owoSelector.body)) {
417
+ owoBig.style.display = 'none';
418
+ }
419
+ };
420
+ const positionOwoBig = owoItem => {
421
+ const itemRect = owoItem.getBoundingClientRect();
422
+ owoBig.style.left = `${itemRect.left - (owoBig.offsetWidth / 4)}px`;
423
+ owoBig.style.top = `${itemRect.top}px`;
457
424
  }
425
+ document.addEventListener('mouseover', showOwoBig);
426
+ document.addEventListener('mouseout', hideOwoBig);
427
+ },
428
+ changeTimeFormat(selector) {
429
+ selector.forEach(item => {
430
+ const timeVal = item.getAttribute('datetime')
431
+ item.textContent = utils.diffDate(timeVal, true)
432
+ item.style.display = 'inline'
433
+ })
434
+ },
435
+ switchComments() {
436
+ const switchBtn = document.getElementById('switch-btn')
437
+ if (!switchBtn) return
438
+ let switchDone = false
439
+ const commentContainer = document.getElementById('post-comment')
440
+ const handleSwitchBtn = () => {
441
+ commentContainer.classList.toggle('move')
442
+ if (!switchDone && typeof loadTwoComment === 'function') {
443
+ switchDone = true
444
+ loadTwoComment()
445
+ }
446
+ }
447
+ utils.addEventListenerPjax(switchBtn, 'click', handleSwitchBtn)
448
+ }
458
449
  };
459
450
  const addHighlight = () => {
460
- const highlight = GLOBAL_CONFIG.highlight;
461
- if (!highlight) return;
462
- const {copy, expand, limit, syntax} = highlight;
463
- const $isPrismjs = syntax === 'prismjs';
464
- const $isShowTool = highlight.enable || copy || expand || limit;
465
- const expandClass = !expand === true ? 'closed' : ''
466
- const $syntaxHighlight = syntax === 'highlight.js' ? document.querySelectorAll('figure.highlight') : document.querySelectorAll('pre[class*="language-"]')
467
- if (!(($isShowTool || limit) && $syntaxHighlight.length)) return
468
- const copyEle = copy ? `<i class="solitude fas fa-copy copy-button"></i>` : '<i></i>';
469
- const expandEle = `<i class="solitude fas fa-angle-down expand"></i>`;
470
- const limitEle = limit ? `<i class="solitude fas fa-angles-down"></i>` : '<i></i>';
471
- const alertInfo = (ele, text) => utils.snackbarShow(text, false, 2000)
472
- const copyFn = (e) => {
473
- const $buttonParent = e.parentNode
474
- $buttonParent.classList.add('copy-true')
475
- const selection = window.getSelection()
476
- const range = document.createRange()
477
- const preCodeSelector = $isPrismjs ? 'pre code' : 'table .code pre'
478
- range.selectNodeContents($buttonParent.querySelectorAll(`${preCodeSelector}`)[0])
479
- selection.removeAllRanges()
480
- selection.addRange(range)
481
- document.execCommand('copy')
482
- alertInfo(e.lastChild, GLOBAL_CONFIG.lang.copy.success)
483
- selection.removeAllRanges()
484
- $buttonParent.classList.remove('copy-true')
485
- }
486
- const expandClose = (e) => e.classList.toggle('closed')
487
- const shrinkEle = function () {
488
- this.classList.toggle('expand-done')
489
- }
490
- const ToolsFn = function (e) {
491
- const $target = e.target.classList
492
- if ($target.contains('expand')) expandClose(this)
493
- else if ($target.contains('copy-button')) copyFn(this)
451
+ const highlight = GLOBAL_CONFIG.highlight;
452
+ if (!highlight) return;
453
+ const {copy, expand, limit, syntax} = highlight;
454
+ const $isPrismjs = syntax === 'prismjs';
455
+ const $isShowTool = highlight.enable || copy || expand || limit;
456
+ const expandClass = !expand === true ? 'closed' : ''
457
+ const $syntaxHighlight = syntax === 'highlight.js' ? document.querySelectorAll('figure.highlight') : document.querySelectorAll('pre[class*="language-"]')
458
+ if (!(($isShowTool || limit) && $syntaxHighlight.length)) return
459
+ const copyEle = copy ? `<i class="solitude fas fa-copy copy-button"></i>` : '<i></i>';
460
+ const expandEle = `<i class="solitude fas fa-angle-down expand"></i>`;
461
+ const limitEle = limit ? `<i class="solitude fas fa-angles-down"></i>` : '<i></i>';
462
+ const alertInfo = (ele, text) => utils.snackbarShow(text, false, 2000)
463
+ const copyFn = (e) => {
464
+ const $buttonParent = e.parentNode
465
+ $buttonParent.classList.add('copy-true')
466
+ const selection = window.getSelection()
467
+ const range = document.createRange()
468
+ const preCodeSelector = $isPrismjs ? 'pre code' : 'table .code pre'
469
+ range.selectNodeContents($buttonParent.querySelectorAll(`${preCodeSelector}`)[0])
470
+ selection.removeAllRanges()
471
+ selection.addRange(range)
472
+ document.execCommand('copy')
473
+ alertInfo(e.lastChild, GLOBAL_CONFIG.lang.copy.success)
474
+ selection.removeAllRanges()
475
+ $buttonParent.classList.remove('copy-true')
476
+ }
477
+ const expandClose = (e) => e.classList.toggle('closed')
478
+ const shrinkEle = function () {
479
+ this.classList.toggle('expand-done')
480
+ }
481
+ const ToolsFn = function (e) {
482
+ const $target = e.target.classList
483
+ if ($target.contains('expand')) expandClose(this)
484
+ else if ($target.contains('copy-button')) copyFn(this)
485
+ }
486
+ const createEle = (lang, item, service) => {
487
+ const fragment = document.createDocumentFragment()
488
+ if ($isShowTool) {
489
+ const hlTools = document.createElement('div')
490
+ hlTools.className = `highlight-tools ${expandClass}`
491
+ hlTools.innerHTML = expandEle + lang + copyEle
492
+ utils.addEventListenerPjax(hlTools, 'click', ToolsFn)
493
+ fragment.appendChild(hlTools)
494
494
  }
495
- const createEle = (lang, item, service) => {
496
- const fragment = document.createDocumentFragment()
497
- if ($isShowTool) {
498
- const hlTools = document.createElement('div')
499
- hlTools.className = `highlight-tools ${expandClass}`
500
- hlTools.innerHTML = expandEle + lang + copyEle
501
- utils.addEventListenerPjax(hlTools, 'click', ToolsFn)
502
- fragment.appendChild(hlTools)
503
- }
504
- if (limit && item.offsetHeight > limit + 30) {
505
- const ele = document.createElement('div')
506
- ele.className = 'code-expand-btn'
507
- ele.innerHTML = limitEle
508
- utils.addEventListenerPjax(ele, 'click', shrinkEle)
509
- fragment.appendChild(ele)
510
- }
511
- if (service === 'hl') {
512
- item.insertBefore(fragment, item.firstChild)
513
- } else {
514
- item.parentNode.insertBefore(fragment, item)
515
- }
495
+ if (limit && item.offsetHeight > limit + 30) {
496
+ const ele = document.createElement('div')
497
+ ele.className = 'code-expand-btn'
498
+ ele.innerHTML = limitEle
499
+ utils.addEventListenerPjax(ele, 'click', shrinkEle)
500
+ fragment.appendChild(ele)
516
501
  }
517
- if ($isPrismjs) {
518
- $syntaxHighlight.forEach(item => {
519
- const langName = item.getAttribute('data-language') || 'Code'
520
- const highlightLangEle = `<div class="code-lang">${langName}</div>`
521
- utils.wrap(item, 'figure', {
522
- class: 'highlight'
523
- })
524
- createEle(highlightLangEle, item)
525
- })
502
+ if (service === 'hl') {
503
+ item.insertBefore(fragment, item.firstChild)
526
504
  } else {
527
- $syntaxHighlight.forEach(item => {
528
- let langName = item.getAttribute('class').split(' ')[1]
529
- if (langName === 'plain' || langName === undefined) langName = 'Code'
530
- const highlightLangEle = `<div class="code-lang">${langName}</div>`
531
- createEle(highlightLangEle, item, 'hl')
532
- })
505
+ item.parentNode.insertBefore(fragment, item)
533
506
  }
507
+ }
508
+ if ($isPrismjs) {
509
+ $syntaxHighlight.forEach(item => {
510
+ const langName = item.getAttribute('data-language') || 'Code'
511
+ const highlightLangEle = `<div class="code-lang">${langName}</div>`
512
+ utils.wrap(item, 'figure', {
513
+ class: 'highlight'
514
+ })
515
+ createEle(highlightLangEle, item)
516
+ })
517
+ } else {
518
+ $syntaxHighlight.forEach(item => {
519
+ let langName = item.getAttribute('class').split(' ')[1]
520
+ if (langName === 'plain' || langName === undefined) langName = 'Code'
521
+ const highlightLangEle = `<div class="code-lang">${langName}</div>`
522
+ createEle(highlightLangEle, item, 'hl')
523
+ })
524
+ }
534
525
  }
535
526
 
536
527
  class toc {
537
- static init() {
538
- const tocContainer = document.getElementById('card-toc')
539
- if (!tocContainer || !tocContainer.querySelector('.toc a')) {
540
- tocContainer.style.display = 'none'
541
- return
542
- }
543
- const el = document.querySelectorAll('.toc a')
544
- el.forEach((e) => {
545
- e.addEventListener('click', (event) => {
546
- event.preventDefault()
547
- utils.scrollToDest(utils.getEleTop(document.getElementById(decodeURI((event.target.className === 'toc-text' ? event.target.parentNode.hash : event.target.hash).replace('#', '')))), 300)
548
- })
549
- })
550
- this.active(el)
528
+ static init() {
529
+ const tocContainer = document.getElementById('card-toc')
530
+ if (!tocContainer || !tocContainer.querySelector('.toc a')) {
531
+ tocContainer.style.display = 'none'
532
+ return
551
533
  }
534
+ const el = document.querySelectorAll('.toc a')
535
+ el.forEach((e) => {
536
+ e.addEventListener('click', (event) => {
537
+ event.preventDefault()
538
+ utils.scrollToDest(utils.getEleTop(document.getElementById(decodeURI((event.target.className === 'toc-text' ? event.target.parentNode.hash : event.target.hash).replace('#', '')))), 300)
539
+ })
540
+ })
541
+ this.active(el)
542
+ }
552
543
 
553
- static active(toc) {
554
- const $article = document.getElementById('article-container')
555
- const $tocContent = document.getElementById('toc-content')
556
- const list = $article.querySelectorAll('h1,h2,h3,h4,h5,h6')
557
- let detectItem = ''
544
+ static active(toc) {
545
+ const $article = document.getElementById('article-container')
546
+ const $tocContent = document.getElementById('toc-content')
547
+ const list = $article.querySelectorAll('h1,h2,h3,h4,h5,h6')
548
+ let detectItem = ''
558
549
 
559
- function autoScroll(el) {
560
- const activePosition = el.getBoundingClientRect().top
561
- const sidebarScrollTop = $tocContent.scrollTop
562
- if (activePosition > (document.documentElement.clientHeight - 100)) {
563
- $tocContent.scrollTop = sidebarScrollTop + 150
564
- }
565
- if (activePosition < 100) {
566
- $tocContent.scrollTop = sidebarScrollTop - 150
567
- }
568
- }
550
+ function autoScroll(el) {
551
+ const activePosition = el.getBoundingClientRect().top
552
+ const sidebarScrollTop = $tocContent.scrollTop
553
+ if (activePosition > (document.documentElement.clientHeight - 100)) {
554
+ $tocContent.scrollTop = sidebarScrollTop + 150
555
+ }
556
+ if (activePosition < 100) {
557
+ $tocContent.scrollTop = sidebarScrollTop - 150
558
+ }
559
+ }
569
560
 
570
- function findHeadPosition(top) {
571
- if (top === 0) return false
572
- let currentIndex = ''
573
- list.forEach(function (ele, index) {
574
- if (top > utils.getEleTop(ele) - 80) {
575
- currentIndex = index
576
- }
577
- })
578
- if (detectItem === currentIndex) return
579
- detectItem = currentIndex
580
- document.querySelectorAll('.toc .active').forEach((i) => {
581
- i.classList.remove('active')
582
- })
583
- const activeitem = toc[detectItem]
584
- if (activeitem) {
585
- let parent = toc[detectItem].parentNode
586
- activeitem.classList.add('active')
587
- autoScroll(activeitem)
588
- for (; !parent.matches('.toc'); parent = parent.parentNode) {
589
- if (parent.matches('li')) parent.classList.add('active')
590
- }
591
- }
561
+ function findHeadPosition(top) {
562
+ if (top === 0) return false
563
+ let currentIndex = ''
564
+ list.forEach(function (ele, index) {
565
+ if (top > utils.getEleTop(ele) - 80) {
566
+ currentIndex = index
592
567
  }
593
-
594
- window.tocScrollFn = utils.throttle(function () {
595
- const currentTop = window.scrollY || document.documentElement.scrollTop
596
- findHeadPosition(currentTop)
597
- }, 100)
598
- window.addEventListener('scroll', tocScrollFn)
568
+ })
569
+ if (detectItem === currentIndex) return
570
+ detectItem = currentIndex
571
+ document.querySelectorAll('.toc .active').forEach((i) => {
572
+ i.classList.remove('active')
573
+ })
574
+ const activeitem = toc[detectItem]
575
+ if (activeitem) {
576
+ let parent = toc[detectItem].parentNode
577
+ activeitem.classList.add('active')
578
+ autoScroll(activeitem)
579
+ for (; !parent.matches('.toc'); parent = parent.parentNode) {
580
+ if (parent.matches('li')) parent.classList.add('active')
581
+ }
582
+ }
599
583
  }
584
+
585
+ window.tocScrollFn = utils.throttle(function () {
586
+ const currentTop = window.scrollY || document.documentElement.scrollTop
587
+ findHeadPosition(currentTop)
588
+ }, 100)
589
+ window.addEventListener('scroll', tocScrollFn)
590
+ }
600
591
  }
601
592
 
602
593
  class tabs {
603
- static init() {
604
- this.clickFnOfTabs();
605
- this.backToTop();
606
- }
594
+ static init() {
595
+ this.clickFnOfTabs();
596
+ this.backToTop();
597
+ }
607
598
 
608
- static clickFnOfTabs() {
609
- document.querySelectorAll('#article-container .tab > button').forEach((item) => {
610
- item.addEventListener('click', function (e) {
611
- const that = this;
612
- const $tabItem = that.parentNode;
613
- if (!$tabItem.classList.contains('active')) {
614
- const $tabContent = $tabItem.parentNode.nextElementSibling;
615
- const $siblings = utils.siblings($tabItem, '.active')[0];
616
- $siblings && $siblings.classList.remove('active');
617
- $tabItem.classList.add('active');
618
- const tabId = that.getAttribute('data-href').replace('#', '');
619
- const childList = [...$tabContent.children];
620
- childList.forEach((item) => {
621
- if (item.id === tabId) item.classList.add('active');
622
- else item.classList.remove('active');
623
- });
624
- }
625
- });
626
- });
627
- }
599
+ static clickFnOfTabs() {
600
+ document.querySelectorAll('#article-container .tab > button').forEach((item) => {
601
+ item.addEventListener('click', function (e) {
602
+ const that = this;
603
+ const $tabItem = that.parentNode;
604
+ if (!$tabItem.classList.contains('active')) {
605
+ const $tabContent = $tabItem.parentNode.nextElementSibling;
606
+ const $siblings = utils.siblings($tabItem, '.active')[0];
607
+ $siblings && $siblings.classList.remove('active');
608
+ $tabItem.classList.add('active');
609
+ const tabId = that.getAttribute('data-href').replace('#', '');
610
+ const childList = [...$tabContent.children];
611
+ childList.forEach((item) => {
612
+ if (item.id === tabId) item.classList.add('active');
613
+ else item.classList.remove('active');
614
+ });
615
+ }
616
+ });
617
+ });
618
+ }
628
619
 
629
- static backToTop() {
630
- document.querySelectorAll('#article-container .tabs .tab-to-top').forEach((item) => {
631
- item.addEventListener('click', function () {
632
- utils.scrollToDest(utils.getEleTop(item.parentElement.parentElement.parentNode), 300);
633
- });
634
- });
635
- }
620
+ static backToTop() {
621
+ document.querySelectorAll('#article-container .tabs .tab-to-top').forEach((item) => {
622
+ item.addEventListener('click', function () {
623
+ utils.scrollToDest(utils.getEleTop(item.parentElement.parentElement.parentNode), 300);
624
+ });
625
+ });
626
+ }
636
627
 
637
- static lureAddListener() {
638
- if (!GLOBAL_CONFIG.lure) return;
639
- let title = document.title;
640
- document.addEventListener('visibilitychange', () => {
641
- const {lure} = GLOBAL_CONFIG;
642
- if (document.visibilityState === 'hidden') {
643
- document.title = lure.jump;
644
- } else if (document.visibilityState === 'visible') {
645
- document.title = lure.back;
646
- setTimeout(() => {
647
- document.title = title;
648
- }, 2000);
649
- }
650
- });
651
- }
628
+ static lureAddListener() {
629
+ if (!GLOBAL_CONFIG.lure) return;
630
+ let title = document.title;
631
+ document.addEventListener('visibilitychange', () => {
632
+ const {lure} = GLOBAL_CONFIG;
633
+ if (document.visibilityState === 'hidden') {
634
+ document.title = lure.jump;
635
+ } else if (document.visibilityState === 'visible') {
636
+ document.title = lure.back;
637
+ setTimeout(() => {
638
+ document.title = title;
639
+ }, 2000);
640
+ }
641
+ });
642
+ }
652
643
 
653
- static expireAddListener() {
654
- const {expire} = GLOBAL_CONFIG;
655
- if (!expire) return;
656
- const post_date = document.querySelector('.post-meta-date time');
657
- if (!post_date) return;
658
- const ex = Math.ceil((new Date().getTime() - new Date(post_date.getAttribute('datetime')).getTime()) / 1000 / 60 / 60 / 24);
659
- if (expire.time > ex) return;
660
- const ele = document.createElement('div');
661
- ele.className = 'expire';
662
- ele.innerHTML = `<i class="solitude st-circle-exclamation-solid"></i>${expire.text_prev}${-(expire.time - ex)}${expire.text_next}`;
663
- const articleContainer = document.getElementById('article-container');
664
- articleContainer.insertAdjacentElement(expire.position === 'top' ? 'afterbegin' : 'beforeend', ele);
665
- }
644
+ static expireAddListener() {
645
+ const {expire} = GLOBAL_CONFIG;
646
+ if (!expire) return;
647
+ const list = document.querySelectorAll('.post-meta-date time');
648
+ const post_date = list.length ? list[list.length - 1] : document.querySelector('.datatime');
649
+ if (!post_date) return;
650
+ const ex = Math.ceil((new Date().getTime() - new Date(post_date.getAttribute('datetime')).getTime()) / 1000 / 60 / 60 / 24);
651
+ if (expire.time > ex) return;
652
+ const ele = document.createElement('div');
653
+ ele.className = 'expire';
654
+ ele.innerHTML = `<i class="solitude st-circle-exclamation-solid"></i>${expire.text_prev}${-(expire.time - ex)}${expire.text_next}`;
655
+ const articleContainer = document.getElementById('article-container');
656
+ articleContainer.insertAdjacentElement(expire.position === 'top' ? 'afterbegin' : 'beforeend', ele);
657
+ }
666
658
  }
667
659
 
668
660
  window.refreshFn = () => {
669
- const {is_home, is_page, page, is_post} = PAGE_CONFIG;
670
- const {runtime, lazyload, lightbox, randomlink, covercolor, post_ai, lure, expire} = GLOBAL_CONFIG;
671
- const timeSelector = (is_home ? '.post-meta-date time' : is_post ? '.post-meta-date time' : '.datatime') + ', .webinfo-item time';
672
- document.body.setAttribute('data-type', page);
673
- sco.changeTimeFormat(document.querySelectorAll(timeSelector));
674
- runtime && sco.addRuntime();
675
- [scrollFn, sidebarFn, sco.hideCookie, sco.addPhotoFigcaption, sco.setTimeState, sco.tagPageActive, sco.categoriesBarActive, sco.listenToPageInputPress, sco.addNavBackgroundInit, sco.refreshWaterFall].forEach(fn => fn());
676
- lazyload.enable && utils.lazyloadImg();
677
- lightbox && utils.lightbox(document.querySelectorAll("#article-container img:not(.flink-avatar,.gallery-group img)"));
678
- randomlink && randomLinksList();
679
- post_ai && is_post && efu_ai.init();
680
- sco.switchComments();
681
- initObserver();
682
- if (is_home){
683
- showTodayCard();
684
- typeof updatePostsBasedOnComments === 'function' && updatePostsBasedOnComments()
685
- }
686
- if (is_post || is_page) {
687
- addHighlight();
688
- tabs.init();
689
- }
690
- if (is_post) {
691
- if (expire) tabs.expireAddListener();
692
- }
693
- if (covercolor.enable) coverColor();
694
- if (PAGE_CONFIG.toc) toc.init();
695
- if (lure) tabs.lureAddListener();
661
+ const {is_home, is_page, page, is_post} = PAGE_CONFIG;
662
+ const {runtime, lazyload, lightbox, randomlink, covercolor, post_ai, lure, expire} = GLOBAL_CONFIG;
663
+ const timeSelector = (is_home ? '.post-meta-date time' : is_post ? '.post-meta-date time' : '.datatime') + ', .webinfo-item time';
664
+ document.body.setAttribute('data-type', page);
665
+ sco.changeTimeFormat(document.querySelectorAll(timeSelector));
666
+ runtime && sco.addRuntime();
667
+ [scrollFn, sidebarFn, sco.addPhotoFigcaption, sco.setTimeState, sco.tagPageActive, sco.categoriesBarActive, sco.listenToPageInputPress, sco.addNavBackgroundInit, sco.refreshWaterFall].forEach(fn => fn());
668
+ lazyload.enable && utils.lazyloadImg();
669
+ lightbox && utils.lightbox(document.querySelectorAll("#article-container img:not(.flink-avatar,.gallery-group img)"));
670
+ randomlink && randomLinksList();
671
+ post_ai && is_post && efu_ai.init();
672
+ sco.switchComments();
673
+ initObserver();
674
+ if (is_home) {
675
+ showTodayCard();
676
+ typeof updatePostsBasedOnComments === 'function' && updatePostsBasedOnComments()
677
+ }
678
+ if (is_post || is_page) {
679
+ addHighlight();
680
+ tabs.init();
681
+ }
682
+ if (is_post) {
683
+ if (expire) tabs.expireAddListener();
684
+ }
685
+ if (covercolor.enable) coverColor();
686
+ if (PAGE_CONFIG.toc) toc.init();
687
+ if (lure) tabs.lureAddListener();
696
688
  }
697
689
  document.addEventListener('DOMContentLoaded', () => {
698
- [addCopyright, window.refreshFn, asideStatus, () => window.onscroll = percent, sco.initConsoleState].forEach(fn => fn());
690
+ [addCopyright, window.refreshFn, asideStatus, () => window.onscroll = percent, sco.initConsoleState].forEach(fn => fn());
699
691
  });
700
692
  document.addEventListener('visibilitychange', () => {
701
- if (document.hidden) {
702
- sco.wasPageHidden = true;
703
- }
693
+ if (document.hidden) {
694
+ sco.wasPageHidden = true;
695
+ }
704
696
  });
705
697
  window.onkeydown = e => {
706
- const {keyCode, ctrlKey, shiftKey} = e;
707
- if (keyCode === 123 || (ctrlKey && shiftKey && keyCode === 67)) {
708
- utils.snackbarShow(GLOBAL_CONFIG.lang.f12, false, 3000);
709
- }
710
- if (keyCode === 27) {
711
- sco.hideConsole();
712
- }
698
+ const {keyCode, ctrlKey, shiftKey} = e;
699
+ if (keyCode === 123 || (ctrlKey && shiftKey && keyCode === 67)) {
700
+ utils.snackbarShow(GLOBAL_CONFIG.lang.f12, false, 3000);
701
+ }
702
+ if (keyCode === 27) {
703
+ sco.hideConsole();
704
+ }
713
705
  };
714
706
  document.addEventListener('copy', () => {
715
- utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 3000);
707
+ utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 3000);
716
708
  });