hexo-theme-solitude 2.0.6 → 2.0.7

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,717 @@
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
+ 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);
268
234
  }
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;
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
+ });
268
+ }
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;
282
282
 
283
- const localData = getLocalData(['twikoo', 'WALINE_USER_META', 'WALINE_USER', '_v_Cache_Meta', 'ArtalkUser']);
283
+ const localData = getLocalData(['twikoo', 'WALINE_USER_META', 'WALINE_USER', '_v_Cache_Meta', 'ArtalkUser']);
284
284
 
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;
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;
295
295
 
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
- }
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
+ }
303
303
 
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
- }
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");
390
324
  });
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`;
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"});
433
353
  }
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
- }
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
+ }
390
+ });
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);
455
421
  }
456
- utils.addEventListenerPjax(switchBtn, 'click', handleSwitchBtn)
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`;
457
433
  }
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
+ }
455
+ }
456
+ utils.addEventListenerPjax(switchBtn, 'click', handleSwitchBtn)
457
+ }
458
458
  };
459
459
  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)
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)
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)
494
503
  }
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
- }
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)
516
510
  }
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
- })
511
+ if (service === 'hl') {
512
+ item.insertBefore(fragment, item.firstChild)
526
513
  } 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
- })
514
+ item.parentNode.insertBefore(fragment, item)
533
515
  }
516
+ }
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
+ })
526
+ } 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
+ })
533
+ }
534
534
  }
535
535
 
536
536
  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)
537
+ static init() {
538
+ const tocContainer = document.getElementById('card-toc')
539
+ if (!tocContainer || !tocContainer.querySelector('.toc a')) {
540
+ tocContainer.style.display = 'none'
541
+ return
551
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)
551
+ }
552
552
 
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 = ''
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 = ''
558
558
 
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
- }
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
+ }
569
569
 
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
- }
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
592
576
  }
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)
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
+ }
599
592
  }
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)
599
+ }
600
600
  }
601
601
 
602
602
  class tabs {
603
- static init() {
604
- this.clickFnOfTabs();
605
- this.backToTop();
606
- }
603
+ static init() {
604
+ this.clickFnOfTabs();
605
+ this.backToTop();
606
+ }
607
607
 
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
- }
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
+ }
628
628
 
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
- }
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
+ }
636
636
 
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
- }
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
+ }
652
652
 
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
- }
653
+ static expireAddListener() {
654
+ const {expire} = GLOBAL_CONFIG;
655
+ if (!expire) return;
656
+ const list = document.querySelectorAll('.post-meta-date time');
657
+ const post_date = list.length ? list[list.length - 1] : document.querySelector('.datatime');
658
+ if (!post_date) return;
659
+ const ex = Math.ceil((new Date().getTime() - new Date(post_date.getAttribute('datetime')).getTime()) / 1000 / 60 / 60 / 24);
660
+ if (expire.time > ex) return;
661
+ const ele = document.createElement('div');
662
+ ele.className = 'expire';
663
+ ele.innerHTML = `<i class="solitude st-circle-exclamation-solid"></i>${expire.text_prev}${-(expire.time - ex)}${expire.text_next}`;
664
+ const articleContainer = document.getElementById('article-container');
665
+ articleContainer.insertAdjacentElement(expire.position === 'top' ? 'afterbegin' : 'beforeend', ele);
666
+ }
666
667
  }
667
668
 
668
669
  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();
670
+ const {is_home, is_page, page, is_post} = PAGE_CONFIG;
671
+ const {runtime, lazyload, lightbox, randomlink, covercolor, post_ai, lure, expire} = GLOBAL_CONFIG;
672
+ const timeSelector = (is_home ? '.post-meta-date time' : is_post ? '.post-meta-date time' : '.datatime') + ', .webinfo-item time';
673
+ document.body.setAttribute('data-type', page);
674
+ sco.changeTimeFormat(document.querySelectorAll(timeSelector));
675
+ runtime && sco.addRuntime();
676
+ [scrollFn, sidebarFn, sco.hideCookie, sco.addPhotoFigcaption, sco.setTimeState, sco.tagPageActive, sco.categoriesBarActive, sco.listenToPageInputPress, sco.addNavBackgroundInit, sco.refreshWaterFall].forEach(fn => fn());
677
+ lazyload.enable && utils.lazyloadImg();
678
+ lightbox && utils.lightbox(document.querySelectorAll("#article-container img:not(.flink-avatar,.gallery-group img)"));
679
+ randomlink && randomLinksList();
680
+ post_ai && is_post && efu_ai.init();
681
+ sco.switchComments();
682
+ initObserver();
683
+ if (is_home) {
684
+ showTodayCard();
685
+ typeof updatePostsBasedOnComments === 'function' && updatePostsBasedOnComments()
686
+ }
687
+ if (is_post || is_page) {
688
+ addHighlight();
689
+ tabs.init();
690
+ }
691
+ if (is_post) {
692
+ if (expire) tabs.expireAddListener();
693
+ }
694
+ if (covercolor.enable) coverColor();
695
+ if (PAGE_CONFIG.toc) toc.init();
696
+ if (lure) tabs.lureAddListener();
696
697
  }
697
698
  document.addEventListener('DOMContentLoaded', () => {
698
- [addCopyright, window.refreshFn, asideStatus, () => window.onscroll = percent, sco.initConsoleState].forEach(fn => fn());
699
+ [addCopyright, window.refreshFn, asideStatus, () => window.onscroll = percent, sco.initConsoleState].forEach(fn => fn());
699
700
  });
700
701
  document.addEventListener('visibilitychange', () => {
701
- if (document.hidden) {
702
- sco.wasPageHidden = true;
703
- }
702
+ if (document.hidden) {
703
+ sco.wasPageHidden = true;
704
+ }
704
705
  });
705
706
  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
- }
707
+ const {keyCode, ctrlKey, shiftKey} = e;
708
+ if (keyCode === 123 || (ctrlKey && shiftKey && keyCode === 67)) {
709
+ utils.snackbarShow(GLOBAL_CONFIG.lang.f12, false, 3000);
710
+ }
711
+ if (keyCode === 27) {
712
+ sco.hideConsole();
713
+ }
713
714
  };
714
715
  document.addEventListener('copy', () => {
715
- utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 3000);
716
+ utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 3000);
716
717
  });