hexo-theme-stellar 1.34.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_config.yml +25 -19
- package/layout/_partial/comments/artalk/layout.ejs +2 -2
- package/layout/_partial/comments/artalk/script.ejs +3 -9
- package/layout/_partial/comments/beaudar/script.ejs +2 -8
- package/layout/_partial/comments/giscus/script.ejs +2 -8
- package/layout/_partial/comments/twikoo/layout.ejs +2 -2
- package/layout/_partial/comments/twikoo/script.ejs +3 -9
- package/layout/_partial/comments/utterances/script.ejs +2 -8
- package/layout/_partial/comments/waline/layout.ejs +1 -1
- package/layout/_partial/comments/waline/script.ejs +1 -7
- package/layout/_partial/head.ejs +0 -3
- package/layout/_partial/scripts/defines.ejs +118 -1
- package/layout/_partial/scripts/lazyload.ejs +7 -6
- package/layout/_partial/scripts/services.ejs +11 -13
- package/layout/_partial/scripts/utils.ejs +358 -66
- package/layout/_partial/widgets/tagtree.ejs +1 -1
- package/layout/_partial/widgets/toc.ejs +1 -4
- package/layout/_partial/widgets/tree.ejs +1 -1
- package/layout/_plugins/fancybox.ejs +23 -8
- package/layout/_plugins/scrollreveal.ejs +77 -13
- package/layout/layout.ejs +0 -1
- package/package.json +4 -2
- package/scripts/events/index.js +2 -1
- package/scripts/events/lib/doc_tree.js +7 -4
- package/scripts/events/lib/merge_posts.js +3 -1
- package/scripts/events/lib/notebooks.js +5 -3
- package/scripts/events/lib/path_normalize.js +22 -0
- package/scripts/filters/lib/img_lazyload.js +9 -9
- package/scripts/generators/search.js +3 -1
- package/scripts/helpers/json_ld.js +3 -2
- package/scripts/helpers/pretty_url.js +9 -10
- package/scripts/lib/path_utils.js +24 -0
- package/scripts/tags/lib/emoji.js +17 -2
- package/scripts/tags/lib/image.js +13 -18
- package/source/css/_common/html.styl +0 -2
- package/source/css/_components/widgets/toc.styl +2 -2
- package/source/css/_plugins/index.styl +0 -3
- package/source/css/_plugins/lazyload.styl +40 -26
- package/source/css/_plugins/scrollreveal.styl +5 -1
- package/source/js/main.js +157 -73
- package/source/js/search/algolia-search.js +62 -62
- package/source/js/search/local-search.js +37 -36
- package/source/js/services/artalk_latest_comment.js +5 -7
- package/source/js/services/contributors.js +4 -6
- package/source/js/services/fcircle.js +4 -6
- package/source/js/services/friends.js +4 -6
- package/source/js/services/friends_and_posts.js +4 -6
- package/source/js/services/ghinfo.js +6 -8
- package/source/js/services/giscus_latest_comment.js +4 -6
- package/source/js/services/mdrender.js +2 -2
- package/source/js/services/memos.js +3 -4
- package/source/js/services/rss.js +10 -12
- package/source/js/services/siteinfo.js +24 -26
- package/source/js/services/sites.js +4 -6
- package/source/js/services/timeline.js +4 -6
- package/source/js/services/twikoo_latest_comment.js +5 -7
- package/source/js/services/waline_latest_comment.js +4 -6
- package/source/js/services/weibo.js +4 -6
- package/CLAUDE.md +0 -217
- package/docs/audits/2026-08-08-stellar-analysis.md +0 -267
- package/docs/release-process.md +0 -59
- package/layout/_plugins/pjax.ejs +0 -8
- package/source/css/_plugins/pjax.styl +0 -61
- package/source/js/plugins/pjax.js +0 -646
package/_config.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
######## Stellar info ########
|
|
2
2
|
stellar:
|
|
3
|
-
version: '1.
|
|
3
|
+
version: '1.36.0'
|
|
4
4
|
homepage: 'https://xaoxuu.com/wiki/stellar/'
|
|
5
5
|
repo: 'https://github.com/xaoxuu/hexo-theme-stellar'
|
|
6
6
|
main_css: /css/main.css
|
|
@@ -222,7 +222,6 @@ search:
|
|
|
222
222
|
comments:
|
|
223
223
|
service: # beaudar, utterances, giscus, twikoo, waline, artalk
|
|
224
224
|
comment_title: 快来参与讨论吧~
|
|
225
|
-
lazyload: false # true / false
|
|
226
225
|
custom_css: # artalk,twikoo,... 可以为没有全局启用的评论加载自定义样式
|
|
227
226
|
# beaudar
|
|
228
227
|
# https://beaudar.lipk.org/
|
|
@@ -319,7 +318,6 @@ comments:
|
|
|
319
318
|
server: # 后端服务地址
|
|
320
319
|
site: '' # 站点名称
|
|
321
320
|
darkMode: auto # 其它模式都有问题,慎用,否则后果自负
|
|
322
|
-
fancybox: true # 是否为评论区启用 fancybox
|
|
323
321
|
# artalk 有三类图片:1.上传至服务端 2.上传至服务端后利用upgit上传至图床 3.前端上传至图床(本配置为此类)
|
|
324
322
|
# 配置此项时将覆盖服务端上传能力
|
|
325
323
|
imageUploader:
|
|
@@ -409,7 +407,7 @@ tag_plugins:
|
|
|
409
407
|
default_color: theme # theme, accent, red, orange, yellow, green, cyan, blue, purple
|
|
410
408
|
# {% image %}
|
|
411
409
|
image:
|
|
412
|
-
|
|
410
|
+
parse_markdown: false # true / false(自动将 markdown 图片转为 {% image %} 标签)
|
|
413
411
|
# {% copy xxx %}
|
|
414
412
|
copy:
|
|
415
413
|
toast: 复制成功
|
|
@@ -454,8 +452,8 @@ tag_plugins:
|
|
|
454
452
|
|
|
455
453
|
# 基础依赖
|
|
456
454
|
dependencies:
|
|
457
|
-
jquery: https://gcore.jsdelivr.net/npm/jquery@3.7/dist/jquery.slim.min.js
|
|
458
455
|
marked: https://gcore.jsdelivr.net/npm/marked@13.0/lib/marked.umd.min.js
|
|
456
|
+
# 懒加载强制开启(无 enable 开关),图片默认懒加载,no-lazy 是唯一例外
|
|
459
457
|
lazyload:
|
|
460
458
|
js: https://gcore.jsdelivr.net/npm/vanilla-lazyload@19.1/dist/lazyload.min.js
|
|
461
459
|
transition: fade # blur, fade
|
|
@@ -522,6 +520,22 @@ data_services:
|
|
|
522
520
|
rss:
|
|
523
521
|
js: /js/services/rss.js
|
|
524
522
|
|
|
523
|
+
# 动态数据缓存
|
|
524
|
+
# 将动态数据缓存到浏览器本地:TTL 未过期直接显示缓存,过期后先显示缓存再后台刷新
|
|
525
|
+
data_cache:
|
|
526
|
+
enable: true # 总开关
|
|
527
|
+
default_ttl: 3600 # 默认缓存时长(秒)
|
|
528
|
+
ttl: # 按服务覆盖缓存时长(秒),未列出的服务使用 default_ttl;设为 0 表示该服务不缓存
|
|
529
|
+
giscus: 600
|
|
530
|
+
waline: 600
|
|
531
|
+
artalk: 600
|
|
532
|
+
memos: 600
|
|
533
|
+
sites: 86400
|
|
534
|
+
friends: 86400
|
|
535
|
+
friends_and_posts: 86400
|
|
536
|
+
siteinfo: 86400
|
|
537
|
+
max_entries: 200 # 本地缓存条目上限,超出后按写入时间淘汰最旧的
|
|
538
|
+
|
|
525
539
|
# 扩展插件接入方法:(插件名下面用 #plugin# 代替)
|
|
526
540
|
# 1. 在这里增加 #plugin# 配置,至少应含有 enable 字段,默认为空(不启用)
|
|
527
541
|
# 2. 新建文件 layout/_plugins/#plugin#.ejs 文件中设置编写加载代码。
|
|
@@ -537,19 +551,12 @@ plugins:
|
|
|
537
551
|
service: flying_pages # flying_pages
|
|
538
552
|
flying_pages: https://gcore.jsdelivr.net/npm/flying-pages@2/flying-pages.min.js
|
|
539
553
|
|
|
540
|
-
# pjax - 无刷新加载
|
|
541
|
-
# 启用后点击链接将使用 AJAX 加载内容,无需整页刷新
|
|
542
|
-
pjax:
|
|
543
|
-
enable: false # 还在测试中,可能存在兼容问题
|
|
544
|
-
selectors: ['title', '#l_cover', '.l_body'] # 需要替换的元素选择器
|
|
545
|
-
timeout: 10000 # 请求超时时间(毫秒)
|
|
546
|
-
cacheBust: false # 是否添加时间戳防止缓存
|
|
547
|
-
translate-distance: 8px # 动画
|
|
548
|
-
|
|
549
554
|
# https://fancyapps.com/docs/ui/fancybox/
|
|
550
555
|
# available for {% image xxx %}
|
|
556
|
+
# mode: auto=按需(页面有可弹窗图片才加载)/ global=全局(所有页面加载)
|
|
551
557
|
fancybox:
|
|
552
|
-
enable: true
|
|
558
|
+
enable: true # 插件注册必需字段,恒为 true(不再支持关闭)
|
|
559
|
+
mode: auto # auto / global
|
|
553
560
|
js: https://gcore.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.umd.js
|
|
554
561
|
css: https://gcore.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.css
|
|
555
562
|
# 让 md 语法图片支持放大可以这样写: .md-text img:not([class]), .md-text .image img
|
|
@@ -566,7 +573,7 @@ plugins:
|
|
|
566
573
|
|
|
567
574
|
# https://scrollrevealjs.org/api/reveal.html
|
|
568
575
|
scrollreveal:
|
|
569
|
-
enable:
|
|
576
|
+
enable: true
|
|
570
577
|
js: https://gcore.jsdelivr.net/npm/scrollreveal@4.0/dist/scrollreveal.min.js
|
|
571
578
|
distance: 8px
|
|
572
579
|
duration: 1000 # ms
|
|
@@ -622,8 +629,8 @@ plugins:
|
|
|
622
629
|
mermaid:
|
|
623
630
|
enable: # true # 可以在特定文章的 front-matter 中设置 mermaid: true 来开启,也可以在这里设置全局开启
|
|
624
631
|
style_optimization: false # use custom style in stellar
|
|
625
|
-
# js: https://unpkg.com/mermaid@
|
|
626
|
-
js: https://gcore.jsdelivr.net/npm/mermaid@
|
|
632
|
+
# js: https://unpkg.com/mermaid@11/dist/mermaid.min.js
|
|
633
|
+
js: https://gcore.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js
|
|
627
634
|
# Available themes: default | dark | forest | neutral
|
|
628
635
|
theme: neutral
|
|
629
636
|
|
|
@@ -645,7 +652,6 @@ plugins:
|
|
|
645
652
|
|
|
646
653
|
style:
|
|
647
654
|
prefers_theme: auto # auto / light / dark
|
|
648
|
-
smooth_scroll: true # true / false 开启时如果目录过长可能无法准确定位
|
|
649
655
|
font-size:
|
|
650
656
|
root: 16px # 改这个会影响全局所有文字的字号
|
|
651
657
|
body: 17px # 影响正文区域的字号,如果改成 px 则不受 root 影响
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%
|
|
2
2
|
function layoutDiv() {
|
|
3
3
|
var el = '';
|
|
4
|
-
el += `<div class="artalk
|
|
4
|
+
el += `<div class="artalk with-fancybox" id="artalk_container"`;
|
|
5
5
|
let cfg = {};
|
|
6
6
|
if (page.comment_id) {
|
|
7
7
|
cfg['comment_id'] = page.comment_id;
|
|
@@ -16,4 +16,4 @@ function layoutDiv() {
|
|
|
16
16
|
}
|
|
17
17
|
%>
|
|
18
18
|
|
|
19
|
-
<%- layoutDiv() %>
|
|
19
|
+
<%- layoutDiv() %>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script type="module">
|
|
2
2
|
(function() {
|
|
3
|
-
const lazyload = <%= theme.comments.lazyload ?? false %>;
|
|
4
3
|
|
|
5
4
|
function initArtalk() {
|
|
6
5
|
const el = document.getElementById('artalk_container');
|
|
@@ -43,15 +42,10 @@
|
|
|
43
42
|
});
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
util.viewportLazyload(el, load_artalk
|
|
45
|
+
util.viewportLazyload(el, load_artalk);
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
// Store in global stellar namespace for PJAX reinitialization
|
|
50
|
-
window.stellar = window.stellar || {};
|
|
51
|
-
window.stellar.initComments = window.stellar.initComments || {};
|
|
52
|
-
window.stellar.initComments.artalk = initArtalk;
|
|
53
|
-
|
|
54
48
|
// Initialize on page load
|
|
55
49
|
initArtalk();
|
|
56
50
|
})();
|
|
57
|
-
</script>
|
|
51
|
+
</script>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script type="module">
|
|
2
2
|
(function() {
|
|
3
|
-
const lazyload = <%= theme.comments.lazyload ?? false %>;
|
|
4
3
|
|
|
5
4
|
function initBeaudar() {
|
|
6
5
|
const el = document.querySelector('#comments #beaudar');
|
|
@@ -24,14 +23,9 @@
|
|
|
24
23
|
el.appendChild(script);
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
util.viewportLazyload(el, load_beaudar
|
|
26
|
+
util.viewportLazyload(el, load_beaudar);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
// Store in global stellar namespace for PJAX reinitialization
|
|
31
|
-
window.stellar = window.stellar || {};
|
|
32
|
-
window.stellar.initComments = window.stellar.initComments || {};
|
|
33
|
-
window.stellar.initComments.beaudar = initBeaudar;
|
|
34
|
-
|
|
35
29
|
// Initialize on page load
|
|
36
30
|
initBeaudar();
|
|
37
31
|
})();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script type="module">
|
|
2
2
|
(function() {
|
|
3
|
-
const lazyload = <%= theme.comments.lazyload ?? false %>;
|
|
4
3
|
|
|
5
4
|
function initGiscus() {
|
|
6
5
|
const el = document.querySelector('#comments #giscus');
|
|
@@ -23,14 +22,9 @@
|
|
|
23
22
|
el.appendChild(script);
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
util.viewportLazyload(el, load_giscus
|
|
25
|
+
util.viewportLazyload(el, load_giscus);
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
// Store in global stellar namespace for PJAX reinitialization
|
|
30
|
-
window.stellar = window.stellar || {};
|
|
31
|
-
window.stellar.initComments = window.stellar.initComments || {};
|
|
32
|
-
window.stellar.initComments.giscus = initGiscus;
|
|
33
|
-
|
|
34
28
|
// Initialize on page load
|
|
35
29
|
initGiscus();
|
|
36
30
|
})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%
|
|
2
2
|
function layoutDiv() {
|
|
3
3
|
var el = '';
|
|
4
|
-
el += '<div id="twikoo_container"';
|
|
4
|
+
el += '<div id="twikoo_container" class="with-fancybox"';
|
|
5
5
|
let cfg = {};
|
|
6
6
|
if (page.comment_id) {
|
|
7
7
|
cfg['comment_id'] = page.comment_id;
|
|
@@ -16,4 +16,4 @@ function layoutDiv() {
|
|
|
16
16
|
}
|
|
17
17
|
%>
|
|
18
18
|
|
|
19
|
-
<%- layoutDiv() %>
|
|
19
|
+
<%- layoutDiv() %>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script type="module">
|
|
2
2
|
(function() {
|
|
3
|
-
const lazyload = <%= theme.comments.lazyload ?? false %>;
|
|
4
3
|
|
|
5
4
|
function initTwikoo() {
|
|
6
5
|
const el = document.getElementById('twikoo_container');
|
|
@@ -16,15 +15,10 @@
|
|
|
16
15
|
});
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
util.viewportLazyload(el, load_twikoo
|
|
18
|
+
util.viewportLazyload(el, load_twikoo);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
// Store in global stellar namespace for PJAX reinitialization
|
|
23
|
-
window.stellar = window.stellar || {};
|
|
24
|
-
window.stellar.initComments = window.stellar.initComments || {};
|
|
25
|
-
window.stellar.initComments.twikoo = initTwikoo;
|
|
26
|
-
|
|
27
21
|
// Initialize on page load
|
|
28
22
|
initTwikoo();
|
|
29
23
|
})();
|
|
30
|
-
</script>
|
|
24
|
+
</script>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script type="module">
|
|
2
2
|
(function() {
|
|
3
|
-
const lazyload = <%= theme.comments.lazyload ?? false %>;
|
|
4
3
|
|
|
5
4
|
function initUtterances() {
|
|
6
5
|
const el = document.querySelector("#comments #utterances");
|
|
@@ -24,14 +23,9 @@
|
|
|
24
23
|
el.appendChild(script);
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
util.viewportLazyload(el, load_utterances
|
|
26
|
+
util.viewportLazyload(el, load_utterances);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
// Store in global stellar namespace for PJAX reinitialization
|
|
31
|
-
window.stellar = window.stellar || {};
|
|
32
|
-
window.stellar.initComments = window.stellar.initComments || {};
|
|
33
|
-
window.stellar.initComments.utterances = initUtterances;
|
|
34
|
-
|
|
35
29
|
// Initialize on page load
|
|
36
30
|
initUtterances();
|
|
37
31
|
})();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script type="module">
|
|
2
2
|
import { init } from '<%- theme.comments.waline.js %>';
|
|
3
3
|
|
|
4
|
-
const lazyload = <%= theme.comments.lazyload ?? false %>;
|
|
5
4
|
|
|
6
5
|
function initWaline() {
|
|
7
6
|
const el = document.getElementById('waline_container');
|
|
@@ -35,14 +34,9 @@
|
|
|
35
34
|
}));
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
util.viewportLazyload(el, load_waline
|
|
37
|
+
util.viewportLazyload(el, load_waline);
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
// Store in global stellar namespace for PJAX reinitialization
|
|
42
|
-
window.stellar = window.stellar || {};
|
|
43
|
-
window.stellar.initComments = window.stellar.initComments || {};
|
|
44
|
-
window.stellar.initComments.waline = initWaline;
|
|
45
|
-
|
|
46
40
|
// Initialize on page load
|
|
47
41
|
initWaline();
|
|
48
42
|
</script>
|
package/layout/_partial/head.ejs
CHANGED
|
@@ -139,9 +139,6 @@ function generate_canonical() {
|
|
|
139
139
|
if (path.startsWith('/404') || path.startsWith('404')) {
|
|
140
140
|
return '';
|
|
141
141
|
}
|
|
142
|
-
if (path.endsWith('.html') && path.length > 5) {
|
|
143
|
-
path = path.split('.html')[0];
|
|
144
|
-
}
|
|
145
142
|
return `<link rel="canonical" href="https://${originalHost}${path}">`;
|
|
146
143
|
}
|
|
147
144
|
return '';
|
|
@@ -19,6 +19,123 @@
|
|
|
19
19
|
const scrollHandler = () => {
|
|
20
20
|
const wikiCover = document.querySelector('#l_cover .l_cover.wiki');
|
|
21
21
|
const startEl = document.getElementById('start');
|
|
22
|
+
// 存在有效锚点时,等待布局稳定后滚动到目标
|
|
23
|
+
// (浏览器原生锚点滚动发生在布局完成前,长文章的懒加载图片/异步组件会把目标顶偏)
|
|
24
|
+
const hash = window.location.hash;
|
|
25
|
+
if (hash.length > 1) {
|
|
26
|
+
let anchorId = hash.slice(1);
|
|
27
|
+
try {
|
|
28
|
+
anchorId = decodeURIComponent(anchorId);
|
|
29
|
+
} catch (e) {
|
|
30
|
+
// 片段含非法编码时按原样查找
|
|
31
|
+
}
|
|
32
|
+
const anchor = document.getElementById(anchorId);
|
|
33
|
+
if (anchor) {
|
|
34
|
+
const offset = 32; // 与 TOC 点击滚动保持一致
|
|
35
|
+
const targetY = () => anchor.getBoundingClientRect().top + window.scrollY - offset;
|
|
36
|
+
let timer = null;
|
|
37
|
+
let lastY = null;
|
|
38
|
+
let quiet = 0;
|
|
39
|
+
let attempts = 0;
|
|
40
|
+
// 记录最近一次资源加载完成时间,判断异步数据/图片是否仍在改变布局
|
|
41
|
+
let lastResourceTime = performance.now();
|
|
42
|
+
let observer = null;
|
|
43
|
+
try {
|
|
44
|
+
observer = new PerformanceObserver(function (list) {
|
|
45
|
+
lastResourceTime = performance.now();
|
|
46
|
+
});
|
|
47
|
+
observer.observe({ entryTypes: ['resource'] });
|
|
48
|
+
} catch (e) {}
|
|
49
|
+
// 统计进行中的 fetch/XHR 请求,异步组件(timeline 等)未完成前不判定布局稳定
|
|
50
|
+
let pendingRequests = 0;
|
|
51
|
+
const trackRequest = (fn) => {
|
|
52
|
+
pendingRequests++;
|
|
53
|
+
try {
|
|
54
|
+
const result = fn();
|
|
55
|
+
if (result && typeof result.finally === 'function') {
|
|
56
|
+
result.finally(function () {
|
|
57
|
+
pendingRequests = Math.max(0, pendingRequests - 1);
|
|
58
|
+
});
|
|
59
|
+
} else {
|
|
60
|
+
pendingRequests = Math.max(0, pendingRequests - 1);
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
} catch (e) {
|
|
64
|
+
pendingRequests = Math.max(0, pendingRequests - 1);
|
|
65
|
+
throw e;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
if (typeof window.fetch === 'function') {
|
|
69
|
+
const origFetch = window.fetch.bind(window);
|
|
70
|
+
window.fetch = function () {
|
|
71
|
+
const args = arguments;
|
|
72
|
+
return trackRequest(function () {
|
|
73
|
+
return origFetch.apply(window, args);
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (window.XMLHttpRequest) {
|
|
78
|
+
const origOpen = window.XMLHttpRequest.prototype.open;
|
|
79
|
+
const origSend = window.XMLHttpRequest.prototype.send;
|
|
80
|
+
window.XMLHttpRequest.prototype.open = function () {
|
|
81
|
+
this.__anchorTracked = true;
|
|
82
|
+
return origOpen.apply(this, arguments);
|
|
83
|
+
};
|
|
84
|
+
window.XMLHttpRequest.prototype.send = function () {
|
|
85
|
+
if (this.__anchorTracked) {
|
|
86
|
+
pendingRequests++;
|
|
87
|
+
const done = () => {
|
|
88
|
+
if (this.__anchorTracked) {
|
|
89
|
+
this.__anchorTracked = false;
|
|
90
|
+
pendingRequests = Math.max(0, pendingRequests - 1);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
this.addEventListener('loadend', done);
|
|
94
|
+
}
|
|
95
|
+
return origSend.apply(this, arguments);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const cancel = () => {
|
|
99
|
+
if (timer !== null) {
|
|
100
|
+
clearInterval(timer);
|
|
101
|
+
timer = null;
|
|
102
|
+
}
|
|
103
|
+
if (observer !== null) {
|
|
104
|
+
try {
|
|
105
|
+
observer.disconnect();
|
|
106
|
+
} catch (e) {}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const adjust = () => {
|
|
110
|
+
const y = targetY();
|
|
111
|
+
const atTarget = Math.abs(window.scrollY - y) <= 2;
|
|
112
|
+
if (!atTarget || lastY === null || Math.abs(y - lastY) > 2) {
|
|
113
|
+
window.scrollTo({ top: y, behavior: 'instant' });
|
|
114
|
+
lastY = y;
|
|
115
|
+
quiet = 0;
|
|
116
|
+
} else {
|
|
117
|
+
quiet++;
|
|
118
|
+
}
|
|
119
|
+
attempts++;
|
|
120
|
+
const resourceQuiet = performance.now() - lastResourceTime > 3000;
|
|
121
|
+
// 位置连续 1.8 秒无变化、无进行中的请求且最近 3 秒无资源加载才视为稳定;最长等待 30 秒
|
|
122
|
+
if ((quiet >= 3 && pendingRequests === 0 && resourceQuiet) || attempts >= 50) {
|
|
123
|
+
cancel();
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
requestAnimationFrame(() => {
|
|
127
|
+
// 锚点链接打开时直接定位,不做动画;用户主动点击(如 TOC)仍走平滑滚动
|
|
128
|
+
window.scrollTo({ top: targetY(), behavior: 'instant' });
|
|
129
|
+
timer = setInterval(adjust, 600);
|
|
130
|
+
});
|
|
131
|
+
// 用户主动滚动时停止自动校正
|
|
132
|
+
window.addEventListener('wheel', cancel, { passive: true });
|
|
133
|
+
window.addEventListener('touchstart', cancel, { passive: true });
|
|
134
|
+
window.addEventListener('mousedown', cancel, { passive: true });
|
|
135
|
+
window.addEventListener('keydown', cancel, { passive: true });
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
22
139
|
if (wikiCover && startEl) {
|
|
23
140
|
window.scrollTo(0, startEl.offsetTop);
|
|
24
141
|
} else {
|
|
@@ -54,9 +171,9 @@
|
|
|
54
171
|
avatar: `<%- theme.default.avatar %>`,
|
|
55
172
|
cover: `<%- theme.default.cover %>`,
|
|
56
173
|
loading: `<%- theme.default.loading %>`,
|
|
174
|
+
data_cache: <%- JSON.stringify(theme.data_cache || {}) %>,
|
|
57
175
|
};
|
|
58
176
|
const deps = {
|
|
59
|
-
jquery: `<%- url_for(theme.dependencies.jquery) %>`,
|
|
60
177
|
marked: `<%- url_for(theme.dependencies.marked) %>`,
|
|
61
178
|
lazyload: `<%- url_for(theme.dependencies.lazyload.js) %>`
|
|
62
179
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
<script async src="<%- url_for(theme.dependencies.lazyload.js) %>"></script>
|
|
2
1
|
<script>
|
|
2
|
+
// 先声明配置与初始化监听,再异步加载库:
|
|
3
|
+
// 保证库执行时 lazyLoadOptions 已就绪,避免 async 脚本抢先执行导致自初始化失败
|
|
3
4
|
// https://www.npmjs.com/package/vanilla-lazyload
|
|
4
5
|
// Set the options globally
|
|
5
6
|
// to make LazyLoad self-initialize
|
|
@@ -7,13 +8,13 @@
|
|
|
7
8
|
elements_selector: ".lazy",
|
|
8
9
|
callback_loaded: (el) => {
|
|
9
10
|
el.classList.add('loaded');
|
|
10
|
-
|
|
11
|
+
// {% image %} 没有 .lazy-box 包裹,回退到父元素查找加载图标
|
|
12
|
+
const wrapper = el.closest('.lazy-box') || el.parentElement;
|
|
11
13
|
const icon = wrapper?.querySelector('.lazy-icon');
|
|
12
14
|
if (icon) icon.remove();
|
|
13
15
|
}
|
|
14
16
|
};
|
|
15
|
-
//
|
|
16
|
-
// and get the instance of LazyLoad
|
|
17
|
+
// 监听初始化事件,获取 LazyLoad 实例
|
|
17
18
|
window.addEventListener(
|
|
18
19
|
"LazyLoad::Initialized",
|
|
19
20
|
function (event) {
|
|
@@ -63,5 +64,5 @@
|
|
|
63
64
|
window.lazyLoadInstance.update();
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
</script>
|
|
68
|
+
<script async src="<%- url_for(theme.dependencies.lazyload.js) %>"></script>
|
|
@@ -42,28 +42,26 @@
|
|
|
42
42
|
} else {
|
|
43
43
|
const els = document.getElementsByClassName(`ds-${id}`);
|
|
44
44
|
if (els?.length > 0) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
utils.js(deps.marked).then(function () {
|
|
48
|
-
utils.js(js, { defer: true });
|
|
49
|
-
});
|
|
50
|
-
} else {
|
|
45
|
+
if (id == 'timeline' || id == 'memos' || id == 'marked' || id == 'mdrender') {
|
|
46
|
+
utils.js(deps.marked).then(function () {
|
|
51
47
|
utils.js(js, { defer: true });
|
|
52
|
-
}
|
|
53
|
-
}
|
|
48
|
+
});
|
|
49
|
+
} else {
|
|
50
|
+
utils.js(js, { defer: true });
|
|
51
|
+
}
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
}
|
|
57
55
|
|
|
58
56
|
// search
|
|
59
57
|
if (ctx.search && typeof searchFunc === 'function') {
|
|
60
|
-
const
|
|
61
|
-
if (
|
|
58
|
+
const inputArea = document.querySelector("input#search-input");
|
|
59
|
+
if (inputArea && !inputArea._searchInitialized) {
|
|
62
60
|
const path = ctx.search.path.startsWith('/') ? ctx.root + ctx.search.path.substring(1) : ctx.root + ctx.search.path;
|
|
63
|
-
const filter =
|
|
61
|
+
const filter = inputArea.getAttribute('data-filter') || '';
|
|
64
62
|
searchFunc(path, filter, 'search-wrapper', 'search-input', 'search-result');
|
|
65
63
|
// 标记为已初始化,防止重复绑定
|
|
66
|
-
|
|
64
|
+
inputArea._searchInitialized = true;
|
|
67
65
|
}
|
|
68
66
|
}
|
|
69
67
|
|
|
@@ -177,4 +175,4 @@
|
|
|
177
175
|
};
|
|
178
176
|
|
|
179
177
|
utils.initPlugin(initServices, 'services');
|
|
180
|
-
</script>
|
|
178
|
+
</script>
|