hexo-theme-linen 1.0.28 → 1.0.30
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/package.json +1 -1
- package/scripts/lazyload/inject.js +5 -3
- package/source/linen-theme/css/_mediaquery.scss +2 -0
- package/source/linen-theme/css/linen.scss +1 -3
- package/source/linen-theme/js/hdr.js +2 -2
- package/source/linen-theme/js/linen.js +82 -39
- package/source/linen-theme/js/replace-emoji.js +11 -3
package/package.json
CHANGED
|
@@ -19,9 +19,11 @@ module.exports = function (hexo) {
|
|
|
19
19
|
...(hexo?.config?.theme_config?.lazyload || {}),
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const placeholderImage =
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const placeholderImage =
|
|
23
|
+
/^(https?:\/\/|\/|data:image|\.\.\/)/i.test(loadingImage) ||
|
|
24
|
+
/\.(svg|png|jpg|jpeg|webp|gif)$/i.test(loadingImage)
|
|
25
|
+
? `url(${loadingImage})`
|
|
26
|
+
: loadingImage;
|
|
25
27
|
|
|
26
28
|
const injectedStyles = `.lazyload-outer-wrap .caption{
|
|
27
29
|
width: 100%;
|
|
@@ -239,8 +239,6 @@ body {
|
|
|
239
239
|
background-color: #fff;
|
|
240
240
|
// backdrop-filter: saturate(180%) blur(20px);
|
|
241
241
|
transform: translateY(0);
|
|
242
|
-
transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
|
|
243
|
-
will-change: transform;
|
|
244
242
|
z-index: 9;
|
|
245
243
|
position: relative;
|
|
246
244
|
top: 0;
|
|
@@ -369,7 +367,7 @@ body {
|
|
|
369
367
|
}
|
|
370
368
|
}
|
|
371
369
|
&.hide {
|
|
372
|
-
transform: translateY(
|
|
370
|
+
transform: translateY(0);
|
|
373
371
|
}
|
|
374
372
|
}
|
|
375
373
|
|
|
@@ -52,7 +52,7 @@ function switchHDR() {
|
|
|
52
52
|
} else {
|
|
53
53
|
var hrefAttr = link.getAttribute("href");
|
|
54
54
|
if (hrefAttr && hrefAttr.includes(SDRPath)) {
|
|
55
|
-
link.setAttribute("href", HDRPath);
|
|
55
|
+
link.setAttribute("href", hrefAttr.replace(SDRPath, HDRPath));
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
} else {
|
|
@@ -61,7 +61,7 @@ function switchHDR() {
|
|
|
61
61
|
} else {
|
|
62
62
|
var hrefAttr = link.getAttribute("href");
|
|
63
63
|
if (hrefAttr && hrefAttr.includes(HDRPath)) {
|
|
64
|
-
link.setAttribute("href", SDRPath);
|
|
64
|
+
link.setAttribute("href", hrefAttr.replace(HDRPath, SDRPath));
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -5,6 +5,7 @@ var isAnchoring = false;
|
|
|
5
5
|
var anchoringId = null;
|
|
6
6
|
var anchoringTimer = null;
|
|
7
7
|
function triggerAnchoring() {
|
|
8
|
+
if (window.innerWidth > 1280) return;
|
|
8
9
|
isAnchoring = true;
|
|
9
10
|
var header = document.querySelector(".nav-header");
|
|
10
11
|
if (header) {
|
|
@@ -13,6 +14,12 @@ function triggerAnchoring() {
|
|
|
13
14
|
clearTimeout(anchoringTimer);
|
|
14
15
|
anchoringTimer = setTimeout(function () {
|
|
15
16
|
isAnchoring = false;
|
|
17
|
+
if (window.scrollY <= 60) {
|
|
18
|
+
var header = document.querySelector(".nav-header");
|
|
19
|
+
if (header) {
|
|
20
|
+
header.classList.remove("hide");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
16
23
|
}, 800);
|
|
17
24
|
}
|
|
18
25
|
|
|
@@ -147,30 +154,27 @@ function isElementInViewport(el) {
|
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
function copyToClipboard(text) {
|
|
150
|
-
if (navigator.clipboard) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
.catch((err) => {
|
|
156
|
-
console.error("复制失败:", err);
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
} else {
|
|
160
|
-
copyToClipboard = function () {
|
|
161
|
-
const textArea = document.createElement("textarea");
|
|
162
|
-
textArea.value = text;
|
|
163
|
-
document.body.appendChild(textArea);
|
|
164
|
-
textArea.select();
|
|
165
|
-
try {
|
|
166
|
-
document.execCommand("copy");
|
|
167
|
-
} catch (err) {
|
|
157
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
158
|
+
navigator.clipboard
|
|
159
|
+
.writeText(text)
|
|
160
|
+
.then(() => {})
|
|
161
|
+
.catch((err) => {
|
|
168
162
|
console.error("复制失败:", err);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
163
|
+
});
|
|
164
|
+
} else {
|
|
165
|
+
const textArea = document.createElement("textarea");
|
|
166
|
+
textArea.value = text;
|
|
167
|
+
textArea.style.position = "fixed";
|
|
168
|
+
textArea.style.opacity = "0";
|
|
169
|
+
document.body.appendChild(textArea);
|
|
170
|
+
textArea.select();
|
|
171
|
+
try {
|
|
172
|
+
document.execCommand("copy");
|
|
173
|
+
} catch (err) {
|
|
174
|
+
console.error("复制失败:", err);
|
|
175
|
+
}
|
|
176
|
+
document.body.removeChild(textArea);
|
|
172
177
|
}
|
|
173
|
-
copyToClipboard(text);
|
|
174
178
|
}
|
|
175
179
|
|
|
176
180
|
function highlightAnchor(hash, highlightClass = "anchor-highlight") {
|
|
@@ -278,20 +282,28 @@ function onScroll() {
|
|
|
278
282
|
typeof loadGitalk !== "undefined" && loadGitalk();
|
|
279
283
|
}
|
|
280
284
|
|
|
281
|
-
|
|
282
|
-
header.classList.
|
|
283
|
-
|
|
284
|
-
|
|
285
|
+
var isMobilePost =
|
|
286
|
+
window.innerWidth <= 1280 && header.classList.contains("is-post");
|
|
287
|
+
|
|
288
|
+
// PC 端没有 header 隐藏逻辑,确保无 hide 类
|
|
289
|
+
if (!isMobilePost && header.classList.contains("hide")) {
|
|
290
|
+
header.classList.remove("hide");
|
|
285
291
|
}
|
|
286
292
|
|
|
287
293
|
// 接近顶部时(<= 60px),强制展开并退出,消除 iOS/Mac 橡皮筋回弹误判与闪烁
|
|
288
294
|
if (currentScrollY <= 60) {
|
|
289
|
-
header.classList.remove("hide");
|
|
295
|
+
if (isMobilePost) header.classList.remove("hide");
|
|
290
296
|
if (backToTop) backToTop.classList.remove("visible");
|
|
291
297
|
previousScrollY = currentScrollY;
|
|
292
298
|
return;
|
|
293
299
|
}
|
|
294
300
|
|
|
301
|
+
if (isMobilePost && isAnchoring) {
|
|
302
|
+
header.classList.add("hide");
|
|
303
|
+
previousScrollY = currentScrollY;
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
295
307
|
var scrollDelta = currentScrollY - previousScrollY;
|
|
296
308
|
// 滤除手指微小抖动
|
|
297
309
|
if (Math.abs(scrollDelta) < 8) {
|
|
@@ -300,7 +312,7 @@ function onScroll() {
|
|
|
300
312
|
|
|
301
313
|
if (scrollDelta < 0) {
|
|
302
314
|
// 向上滑动:即刻平滑展开导航栏
|
|
303
|
-
if (!document.querySelector(".pswp--open")) {
|
|
315
|
+
if (isMobilePost && !document.querySelector(".pswp--open")) {
|
|
304
316
|
header.classList.remove("hide");
|
|
305
317
|
}
|
|
306
318
|
if (backToTop && currentScrollY >= triggerHeight) {
|
|
@@ -309,7 +321,7 @@ function onScroll() {
|
|
|
309
321
|
} else {
|
|
310
322
|
// 向下滑动:离开顶部 60% 视口后平滑收起导航栏
|
|
311
323
|
if (backToTop) backToTop.classList.remove("visible");
|
|
312
|
-
if (currentScrollY > window.innerHeight * 0.6) {
|
|
324
|
+
if (isMobilePost && currentScrollY > window.innerHeight * 0.6) {
|
|
313
325
|
header.classList.add("hide");
|
|
314
326
|
}
|
|
315
327
|
}
|
|
@@ -340,6 +352,11 @@ window.addEventListener("resize", function () {
|
|
|
340
352
|
body.classList.add("resizing");
|
|
341
353
|
viewportWidth = window.innerWidth;
|
|
342
354
|
|
|
355
|
+
if (window.innerWidth > 1280) {
|
|
356
|
+
const header = document.querySelector(".nav-header");
|
|
357
|
+
if (header) header.classList.remove("hide");
|
|
358
|
+
}
|
|
359
|
+
|
|
343
360
|
clearTimeout(resizeTimer);
|
|
344
361
|
resizeTimer = setTimeout(function () {
|
|
345
362
|
body.classList.remove("resizing");
|
|
@@ -448,23 +465,46 @@ function handleClick(e) {
|
|
|
448
465
|
maskElement.classList.remove("visible");
|
|
449
466
|
setBodyScrollLocked(false);
|
|
450
467
|
}
|
|
451
|
-
|
|
468
|
+
const firstTocLink = tocElement
|
|
469
|
+
? tocElement.querySelector(".toc-item-link")
|
|
470
|
+
: null;
|
|
471
|
+
const isFirstToc =
|
|
472
|
+
target === firstTocLink ||
|
|
473
|
+
target.closest(".toc-item-link") === firstTocLink;
|
|
474
|
+
|
|
475
|
+
if (targetId === "to-page-top" || targetId === "page-top") {
|
|
452
476
|
window.scrollTo({
|
|
453
477
|
top: 0,
|
|
454
478
|
left: 0,
|
|
455
479
|
behavior: "instant",
|
|
456
480
|
});
|
|
481
|
+
isAnchoring = false;
|
|
482
|
+
clearTimeout(anchoringTimer);
|
|
483
|
+
var header = document.querySelector(".nav-header");
|
|
484
|
+
if (header) {
|
|
485
|
+
header.classList.remove("hide");
|
|
486
|
+
}
|
|
457
487
|
} else {
|
|
458
488
|
anchor &&
|
|
459
489
|
anchor.scrollIntoView({
|
|
460
490
|
behavior: "instant",
|
|
461
491
|
block: "start",
|
|
462
492
|
});
|
|
463
|
-
|
|
493
|
+
if (isFirstToc) {
|
|
494
|
+
isAnchoring = false;
|
|
495
|
+
clearTimeout(anchoringTimer);
|
|
496
|
+
var header = document.querySelector(".nav-header");
|
|
497
|
+
if (header) {
|
|
498
|
+
header.classList.remove("hide");
|
|
499
|
+
}
|
|
500
|
+
} else {
|
|
501
|
+
triggerAnchoring();
|
|
502
|
+
}
|
|
464
503
|
}
|
|
465
504
|
highlightAnchor(targetId);
|
|
466
505
|
if (
|
|
467
506
|
target.className?.includes("toc-item-link") &&
|
|
507
|
+
anchor &&
|
|
468
508
|
isElementInViewport(anchor)
|
|
469
509
|
) {
|
|
470
510
|
anchoringId = anchor.id;
|
|
@@ -548,24 +588,27 @@ function handleClick(e) {
|
|
|
548
588
|
}
|
|
549
589
|
}
|
|
550
590
|
|
|
591
|
+
var isClickHandlerBound = false;
|
|
551
592
|
function bindClickHandler() {
|
|
593
|
+
if (isClickHandlerBound) return;
|
|
552
594
|
document.addEventListener("click", handleClick, true);
|
|
595
|
+
isClickHandlerBound = true;
|
|
553
596
|
}
|
|
554
597
|
|
|
555
598
|
window.addEventListener("load", bindClickHandler);
|
|
556
|
-
window.addEventListener("pageshow", (
|
|
557
|
-
|
|
558
|
-
bindClickHandler();
|
|
559
|
-
});
|
|
599
|
+
window.addEventListener("pageshow", () => {
|
|
600
|
+
bindClickHandler();
|
|
560
601
|
});
|
|
561
602
|
|
|
562
603
|
function initAgeWarning() {
|
|
563
604
|
const ageWarningElement = document.getElementById("post-age-warning");
|
|
564
605
|
if (!ageWarningElement) return;
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
606
|
+
const dateElement = document.querySelector("#post .post-meta .date");
|
|
607
|
+
const dateStr = dateElement ? dateElement.getAttribute("datetime") : null;
|
|
608
|
+
if (!dateStr) return;
|
|
609
|
+
|
|
568
610
|
const postDate = new Date(dateStr);
|
|
611
|
+
if (isNaN(postDate.getTime())) return;
|
|
569
612
|
const now = new Date();
|
|
570
613
|
|
|
571
614
|
const diffTime = now - postDate;
|
|
@@ -578,7 +621,7 @@ function initAgeWarning() {
|
|
|
578
621
|
}
|
|
579
622
|
} else {
|
|
580
623
|
if (ageWarningElement) {
|
|
581
|
-
ageWarningElement.style = "
|
|
624
|
+
ageWarningElement.style.display = "none";
|
|
582
625
|
}
|
|
583
626
|
}
|
|
584
627
|
return diffDays;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
function replaceEmojis() {
|
|
2
|
+
if (!document.body) return;
|
|
2
3
|
const replacements = [{ emoji: "✅", className: "custom-checked-checkbox" }];
|
|
3
4
|
|
|
4
5
|
replacements.forEach(({ emoji, className }) => {
|
|
@@ -7,9 +8,16 @@ function replaceEmojis() {
|
|
|
7
8
|
NodeFilter.SHOW_TEXT,
|
|
8
9
|
{
|
|
9
10
|
acceptNode(node) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
if (!node.nodeValue || !node.nodeValue.includes(emoji)) {
|
|
12
|
+
return NodeFilter.FILTER_REJECT;
|
|
13
|
+
}
|
|
14
|
+
if (
|
|
15
|
+
node.parentElement &&
|
|
16
|
+
node.parentElement.closest("pre, code, textarea, script, style")
|
|
17
|
+
) {
|
|
18
|
+
return NodeFilter.FILTER_REJECT;
|
|
19
|
+
}
|
|
20
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
13
21
|
},
|
|
14
22
|
},
|
|
15
23
|
);
|