hexo-theme-nblog 1.1.0 → 1.2.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 +10 -2
- package/layout/index.ejs +166 -117
- package/layout/layout.ejs +78 -31
- package/package.json +1 -1
- package/scripts/helpers.js +9 -9
- package/source/css/lazyload.css +1 -1
- package/source/css/main.css +206 -8
- package/source/css/markdown.css +1 -1
- package/source/js/main.js +211 -4
package/_config.yml
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#! 注意! 为了更新 npm package 后你的数据不会丢失
|
|
2
|
-
#! 请将此文件复制到根目录并重命名为 `_config.nblog.yml`
|
|
2
|
+
#! 请将此文件复制到根目录并重命名为 `_config.nblog.yml` 并在此文件的基础上进行站点配置
|
|
3
3
|
default_license: CC BY-NC-SA 4.0
|
|
4
4
|
|
|
5
|
+
primary_color: '#FF7F78'
|
|
6
|
+
|
|
5
7
|
site_name: My Blog
|
|
6
8
|
author: Your Name
|
|
7
9
|
avatar: /images/avatar.png
|
|
@@ -82,4 +84,10 @@ medium_zoom:
|
|
|
82
84
|
|
|
83
85
|
lazyload:
|
|
84
86
|
enable: true
|
|
85
|
-
placeholder: blur
|
|
87
|
+
placeholder: blur
|
|
88
|
+
|
|
89
|
+
notifications:
|
|
90
|
+
enable: true
|
|
91
|
+
interval: 10000
|
|
92
|
+
items:
|
|
93
|
+
- message: '欢迎访问我的博客!'
|
package/layout/index.ejs
CHANGED
|
@@ -1,127 +1,176 @@
|
|
|
1
1
|
<div class="posts-page container">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<span class="post-card__date">
|
|
17
|
-
<%= date(post.date, 'YYYY-MM-DD' ) %>
|
|
18
|
-
</span>
|
|
19
|
-
<% if (post.categories && post.categories.length> 0) { %>
|
|
20
|
-
<span class="post-card__category">
|
|
21
|
-
<%= post.categories.toArray()[0].name %>
|
|
22
|
-
</span>
|
|
23
|
-
<% } %>
|
|
24
|
-
</div>
|
|
25
|
-
<h2 class="post-card__title">
|
|
26
|
-
<%= post.title %>
|
|
27
|
-
</h2>
|
|
28
|
-
</div>
|
|
2
|
+
<h1 class="sr-only">
|
|
3
|
+
<%= config.title %>
|
|
4
|
+
</h1>
|
|
5
|
+
<% if (theme.notifications && theme.notifications.enable && theme.notifications.items &&
|
|
6
|
+
theme.notifications.items.length> 0) { %>
|
|
7
|
+
<div class="notification-banner notification-banner--mobile material-card" id="notificationBannerMobile"
|
|
8
|
+
data-interval="<%= theme.notifications.interval || 5000 %>">
|
|
9
|
+
<div class="notification-banner__inner">
|
|
10
|
+
<div class="notification-banner__content">
|
|
11
|
+
<% theme.notifications.items.forEach(function(item, index) { %>
|
|
12
|
+
<div class="notification-banner__item<%= index === 0 ? ' is-active' : '' %>">
|
|
13
|
+
<span class="notification-banner__message">
|
|
14
|
+
<%- markdown(item.message) %>
|
|
15
|
+
</span>
|
|
29
16
|
</div>
|
|
30
|
-
|
|
31
|
-
</article>
|
|
32
|
-
<% }); %>
|
|
33
|
-
|
|
34
|
-
<% if (page.total> 1) { %>
|
|
35
|
-
<nav class="pagination">
|
|
36
|
-
<%- paginator({
|
|
37
|
-
prev_text: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"></polyline></svg>'
|
|
38
|
-
,
|
|
39
|
-
next_text: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"></polyline></svg>'
|
|
40
|
-
, escape: false }) %>
|
|
41
|
-
</nav>
|
|
42
|
-
<% } %>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<aside class="sidebar">
|
|
46
|
-
<div class="author-card material-card animate-fade-in-right">
|
|
47
|
-
<div class="author-card__avatar">
|
|
48
|
-
<img data-src="<%= theme.avatar %>" alt="<%= theme.author %>">
|
|
49
|
-
</div>
|
|
50
|
-
<h3 class="author-card__name">
|
|
51
|
-
<%= theme.author %>
|
|
52
|
-
</h3>
|
|
53
|
-
<p class="author-card__bio">
|
|
54
|
-
<%= theme.bio %>
|
|
55
|
-
</p>
|
|
56
|
-
<div class="author-card__stats">
|
|
57
|
-
<div class="author-card__stat">
|
|
58
|
-
<span class="author-card__stat-value">
|
|
59
|
-
<%= site.posts.length %>
|
|
60
|
-
</span>
|
|
61
|
-
<span class="author-card__stat-label">文章</span>
|
|
62
|
-
</div>
|
|
63
|
-
<div class="author-card__stat">
|
|
64
|
-
<span class="author-card__stat-value">
|
|
65
|
-
<%= site.categories.length %>
|
|
66
|
-
</span>
|
|
67
|
-
<span class="author-card__stat-label">分类</span>
|
|
68
|
-
</div>
|
|
69
|
-
<div class="author-card__stat">
|
|
70
|
-
<span class="author-card__stat-value">
|
|
71
|
-
<%= site.tags.length %>
|
|
72
|
-
</span>
|
|
73
|
-
<span class="author-card__stat-label">标签</span>
|
|
74
|
-
</div>
|
|
17
|
+
<% }); %>
|
|
75
18
|
</div>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
title="<%= link.platform %>">
|
|
81
|
-
<%- link.icon %>
|
|
82
|
-
</a>
|
|
83
|
-
<% } %>
|
|
84
|
-
</div>
|
|
85
|
-
<% } %>
|
|
86
|
-
</div>
|
|
87
|
-
|
|
88
|
-
<div class="sidebar-widget material-card animate-fade-in-right animate-delay-1">
|
|
89
|
-
<h3 class="sidebar-widget__title">
|
|
90
|
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
91
|
-
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
|
92
|
-
</svg>
|
|
93
|
-
分类
|
|
94
|
-
</h3>
|
|
95
|
-
<div class="sidebar-widget__content">
|
|
96
|
-
<% site.categories.sort('name').forEach(function(category) { %>
|
|
97
|
-
<a href="<%= url_for(category.path) %>" class="sidebar-widget__item">
|
|
98
|
-
<span class="sidebar-widget__item-name">
|
|
99
|
-
<%= category.name %>
|
|
100
|
-
</span>
|
|
101
|
-
<span class="sidebar-widget__item-count">
|
|
102
|
-
<%= category.length %>
|
|
103
|
-
</span>
|
|
104
|
-
</a>
|
|
19
|
+
<div class="notification-banner__indicators">
|
|
20
|
+
<% theme.notifications.items.forEach(function(item, index) { %>
|
|
21
|
+
<span class="notification-banner__indicator<%= index === 0 ? ' is-active' : '' %>"
|
|
22
|
+
data-index="<%= index %>"></span>
|
|
105
23
|
<% }); %>
|
|
106
24
|
</div>
|
|
107
25
|
</div>
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
26
|
+
</div>
|
|
27
|
+
<% } %>
|
|
28
|
+
<div class="posts-page__content">
|
|
29
|
+
<div class="posts-list">
|
|
30
|
+
<% page.posts.each(function(post) { %>
|
|
31
|
+
<article class="post-card material-card animate-fade-in-up">
|
|
32
|
+
<a href="<%= url_for(post.path) %>" class="post-card__link">
|
|
33
|
+
<div class="post-card__cover">
|
|
34
|
+
<% if (post.cover) { %>
|
|
35
|
+
<img data-src="<%= post.cover %>" alt="<%= post.title %>">
|
|
36
|
+
<% } else { %>
|
|
37
|
+
<div class="post-card__cover-placeholder"></div>
|
|
38
|
+
<% } %>
|
|
39
|
+
<div class="post-card__overlay"></div>
|
|
40
|
+
<div class="post-card__info">
|
|
41
|
+
<div class="post-card__meta">
|
|
42
|
+
<span class="post-card__date">
|
|
43
|
+
<%= date(post.date, 'YYYY-MM-DD' ) %>
|
|
44
|
+
</span>
|
|
45
|
+
<% if (post.categories && post.categories.length> 0) { %>
|
|
46
|
+
<span class="post-card__category">
|
|
47
|
+
<%= post.categories.toArray()[0].name %>
|
|
48
|
+
</span>
|
|
49
|
+
<% } %>
|
|
50
|
+
</div>
|
|
51
|
+
<h2 class="post-card__title">
|
|
52
|
+
<%= post.title %>
|
|
53
|
+
</h2>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</a>
|
|
57
|
+
</article>
|
|
122
58
|
<% }); %>
|
|
59
|
+
|
|
60
|
+
<% if (page.total> 1) { %>
|
|
61
|
+
<nav class="pagination">
|
|
62
|
+
<%- paginator({
|
|
63
|
+
prev_text: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"></polyline></svg>'
|
|
64
|
+
,
|
|
65
|
+
next_text: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"></polyline></svg>'
|
|
66
|
+
, escape: false }) %>
|
|
67
|
+
</nav>
|
|
68
|
+
<% } %>
|
|
123
69
|
</div>
|
|
70
|
+
|
|
71
|
+
<aside class="sidebar">
|
|
72
|
+
<% if (theme.notifications && theme.notifications.enable && theme.notifications.items &&
|
|
73
|
+
theme.notifications.items.length> 0) { %>
|
|
74
|
+
<div class="notification-banner material-card animate-fade-in-right" id="notificationBanner"
|
|
75
|
+
data-interval="<%= theme.notifications.interval || 5000 %>">
|
|
76
|
+
<div class="notification-banner__inner">
|
|
77
|
+
<div class="notification-banner__content">
|
|
78
|
+
<% theme.notifications.items.forEach(function(item, index) { %>
|
|
79
|
+
<div class="notification-banner__item<%= index === 0 ? ' is-active' : '' %>">
|
|
80
|
+
<span class="notification-banner__message">
|
|
81
|
+
<%- markdown(item.message) %>
|
|
82
|
+
</span>
|
|
83
|
+
</div>
|
|
84
|
+
<% }); %>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="notification-banner__indicators">
|
|
87
|
+
<% theme.notifications.items.forEach(function(item, index) { %>
|
|
88
|
+
<span class="notification-banner__indicator<%= index === 0 ? ' is-active' : '' %>"
|
|
89
|
+
data-index="<%= index %>"></span>
|
|
90
|
+
<% }); %>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
<% } %>
|
|
95
|
+
<div class="author-card material-card animate-fade-in-right">
|
|
96
|
+
<div class="author-card__avatar">
|
|
97
|
+
<img data-src="<%= theme.avatar %>" alt="<%= theme.author %>">
|
|
98
|
+
</div>
|
|
99
|
+
<h3 class="author-card__name">
|
|
100
|
+
<%= theme.author %>
|
|
101
|
+
</h3>
|
|
102
|
+
<p class="author-card__bio">
|
|
103
|
+
<%= theme.bio %>
|
|
104
|
+
</p>
|
|
105
|
+
<div class="author-card__stats">
|
|
106
|
+
<div class="author-card__stat">
|
|
107
|
+
<span class="author-card__stat-value">
|
|
108
|
+
<%= site.posts.length %>
|
|
109
|
+
</span>
|
|
110
|
+
<span class="author-card__stat-label">文章</span>
|
|
111
|
+
</div>
|
|
112
|
+
<div class="author-card__stat">
|
|
113
|
+
<span class="author-card__stat-value">
|
|
114
|
+
<%= site.categories.length %>
|
|
115
|
+
</span>
|
|
116
|
+
<span class="author-card__stat-label">分类</span>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="author-card__stat">
|
|
119
|
+
<span class="author-card__stat-value">
|
|
120
|
+
<%= site.tags.length %>
|
|
121
|
+
</span>
|
|
122
|
+
<span class="author-card__stat-label">标签</span>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
<% if (theme.social && theme.social.length> 0) { %>
|
|
126
|
+
<div class="author-card__social">
|
|
127
|
+
<% for (var link of theme.social) { %>
|
|
128
|
+
<a href="<%= link.url %>" target="_blank" rel="noopener" class="author-card__social-link"
|
|
129
|
+
title="<%= link.platform %>">
|
|
130
|
+
<%- link.icon %>
|
|
131
|
+
</a>
|
|
132
|
+
<% } %>
|
|
133
|
+
</div>
|
|
134
|
+
<% } %>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<div class="sidebar-widget material-card animate-fade-in-right animate-delay-1">
|
|
138
|
+
<h3 class="sidebar-widget__title">
|
|
139
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
140
|
+
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
|
141
|
+
</svg>
|
|
142
|
+
分类
|
|
143
|
+
</h3>
|
|
144
|
+
<div class="sidebar-widget__content">
|
|
145
|
+
<% site.categories.sort('name').forEach(function(category) { %>
|
|
146
|
+
<a href="<%= url_for(category.path) %>" class="sidebar-widget__item">
|
|
147
|
+
<span class="sidebar-widget__item-name">
|
|
148
|
+
<%= category.name %>
|
|
149
|
+
</span>
|
|
150
|
+
<span class="sidebar-widget__item-count">
|
|
151
|
+
<%= category.length %>
|
|
152
|
+
</span>
|
|
153
|
+
</a>
|
|
154
|
+
<% }); %>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div class="sidebar-widget material-card animate-fade-in-right animate-delay-2">
|
|
159
|
+
<h3 class="sidebar-widget__title">
|
|
160
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
161
|
+
<path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path>
|
|
162
|
+
<line x1="7" y1="7" x2="7.01" y2="7"></line>
|
|
163
|
+
</svg>
|
|
164
|
+
标签云
|
|
165
|
+
</h3>
|
|
166
|
+
<div class="sidebar-widget__content sidebar-widget__content--tags">
|
|
167
|
+
<% site.tags.sort('name').forEach(function(tag) { %>
|
|
168
|
+
<a href="<%= url_for(tag.path) %>" class="tag-cloud__tag">
|
|
169
|
+
<%= tag.name %>
|
|
170
|
+
</a>
|
|
171
|
+
<% }); %>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</aside>
|
|
124
175
|
</div>
|
|
125
|
-
</aside>
|
|
126
|
-
</div>
|
|
127
176
|
</div>
|
package/layout/layout.ejs
CHANGED
|
@@ -11,38 +11,77 @@
|
|
|
11
11
|
<%= page.title %> | <% } %>
|
|
12
12
|
<%= config.title %>
|
|
13
13
|
</title>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
<% var primaryColor=theme.primary_color || '#FF7F78' ; function hexToRgb(hex) { var
|
|
15
|
+
result=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g:
|
|
16
|
+
parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } function rgbToHsl(r, g, b) { r /=255; g /=255; b
|
|
17
|
+
/=255; var max=Math.max(r, g, b), min=Math.min(r, g, b); var h, s, l=(max + min) / 2; if (max===min) { h=s=0; } else
|
|
18
|
+
{ var d=max - min; s=l> 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
19
|
+
switch (max) {
|
|
20
|
+
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break; case g: h=((b - r) / d + 2) / 6; break; case b: h=((r - g) /
|
|
21
|
+
d + 4) / 6; break; } } return { h: h * 360, s: s * 100, l: l * 100 }; } function hslToRgb(h, s, l) { h /=360; s
|
|
22
|
+
/=100; l /=100; var r, g, b; if (s===0) { r=g=b=l; } else { var hue2rgb=function(p, q, t) { if (t < 0) t +=1; if
|
|
23
|
+
(t> 1) t -= 1;
|
|
24
|
+
if (t < 1/6) return p + (q - p) * 6 * t; if (t < 1/2) return q; if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
|
25
|
+
return p; }; var q=l < 0.5 ? l * (1 + s) : l + s - l * s; var p=2 * l - q; r=hue2rgb(p, q, h + 1/3);
|
|
26
|
+
g=hue2rgb(p, q, h); b=hue2rgb(p, q, h - 1/3); } return { r: Math.round(r * 255), g: Math.round(g * 255), b:
|
|
27
|
+
Math.round(b * 255) }; } function rgbToHex(r, g, b) { return '#' + [r, g, b].map(function(x) { var
|
|
28
|
+
hex=x.toString(16); return hex.length===1 ? '0' + hex : hex; }).join(''); } function adjustLightness(hex,
|
|
29
|
+
amount) { var rgb=hexToRgb(hex); var hsl=rgbToHsl(rgb.r, rgb.g, rgb.b); hsl.l=Math.max(0, Math.min(100, hsl.l +
|
|
30
|
+
amount)); var newRgb=hslToRgb(hsl.h, hsl.s, hsl.l); return rgbToHex(newRgb.r, newRgb.g, newRgb.b); } function
|
|
31
|
+
adjustSaturation(hex, satAmount, lightAmount) { var rgb=hexToRgb(hex); var hsl=rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
32
|
+
hsl.s=Math.max(0, Math.min(100, hsl.s + satAmount)); hsl.l=Math.max(0, Math.min(100, hsl.l + lightAmount)); var
|
|
33
|
+
newRgb=hslToRgb(hsl.h, hsl.s, hsl.l); return rgbToHex(newRgb.r, newRgb.g, newRgb.b); } var
|
|
34
|
+
rgb=hexToRgb(primaryColor); var primaryLight=adjustLightness(primaryColor, 21); var
|
|
35
|
+
primaryDark=adjustSaturation(primaryColor, -39, -12); var btnPlainBgHover='rgba(' + rgb.r + ', ' + rgb.g + ', '
|
|
36
|
+
+ rgb.b + ', 0.5)' ; var darkPrimary=adjustLightness(primaryColor, 5); var
|
|
37
|
+
darkPrimaryLight=adjustSaturation(primaryColor, -56, -36); var darkPrimaryDark=adjustLightness(primaryColor,
|
|
38
|
+
21); %>
|
|
39
|
+
<style>
|
|
40
|
+
:root {
|
|
41
|
+
--primary-color: <%=primaryColor %>;
|
|
42
|
+
--primary-light: <%=primaryLight %>;
|
|
43
|
+
--primary-dark: <%=primaryDark %>;
|
|
44
|
+
--btn-plain-bg-hover: <%=btnPlainBgHover %>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[data-theme="dark"] {
|
|
48
|
+
--primary-color: <%=darkPrimary %>;
|
|
49
|
+
--primary-light: <%=darkPrimaryLight %>;
|
|
50
|
+
--primary-dark: <%=darkPrimaryDark %>;
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
53
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
54
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
55
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
56
|
+
<link
|
|
57
|
+
href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Noto+Sans+SC:wght@400;500;700&display=swap"
|
|
58
|
+
rel="stylesheet">
|
|
59
|
+
<link rel="stylesheet" href="<%= url_for('/css/main.css') %>">
|
|
60
|
+
<% if (theme.lazyload && theme.lazyload.enable) { %>
|
|
61
|
+
<link rel="stylesheet" href="<%= url_for('/css/lazyload.css') %>">
|
|
30
62
|
<% } %>
|
|
31
|
-
<%
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
63
|
+
<% if (is_post()) { %>
|
|
64
|
+
<link rel="stylesheet" href="<%= url_for('/css/markdown.css') %>">
|
|
65
|
+
<link rel="stylesheet" href="<%= url_for('/css/highlight.css') %>">
|
|
66
|
+
<link rel="stylesheet" href="<%= url_for('/css/admonition.css') %>">
|
|
67
|
+
<% if (theme.twikoo && theme.twikoo.enable) { %>
|
|
68
|
+
<link rel="stylesheet" href="<%= url_for('/css/twikoo.css') %>">
|
|
69
|
+
<% } %>
|
|
70
|
+
<% } %>
|
|
71
|
+
<%- partial('_partial/open-graph') %>
|
|
72
|
+
<% if (theme.canonical && theme.canonical.enable && typeof autoCanonical==='function' ) { %>
|
|
73
|
+
<%- autoCanonical(config, page) %>
|
|
74
|
+
<% } %>
|
|
75
|
+
<script>
|
|
76
|
+
(function () {
|
|
77
|
+
var savedTheme = localStorage.getItem('theme');
|
|
78
|
+
if (savedTheme === 'dark') {
|
|
79
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
80
|
+
} else if (savedTheme === null && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
81
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
82
|
+
}
|
|
83
|
+
})();
|
|
84
|
+
</script>
|
|
46
85
|
</head>
|
|
47
86
|
|
|
48
87
|
<body>
|
|
@@ -51,6 +90,14 @@
|
|
|
51
90
|
<div class="app__circle app__circle--1"></div>
|
|
52
91
|
<div class="app__circle app__circle--2"></div>
|
|
53
92
|
<div class="app__circle app__circle--3"></div>
|
|
93
|
+
<div class="app__particle app__particle--1"></div>
|
|
94
|
+
<div class="app__particle app__particle--2"></div>
|
|
95
|
+
<div class="app__particle app__particle--3"></div>
|
|
96
|
+
<div class="app__particle app__particle--4"></div>
|
|
97
|
+
<div class="app__particle app__particle--5"></div>
|
|
98
|
+
<div class="app__particle app__particle--6"></div>
|
|
99
|
+
<div class="app__particle app__particle--7"></div>
|
|
100
|
+
<div class="app__particle app__particle--8"></div>
|
|
54
101
|
</div>
|
|
55
102
|
<%- partial('_partial/header') %>
|
|
56
103
|
<main class="main" id="pjax-container">
|
package/package.json
CHANGED
package/scripts/helpers.js
CHANGED
|
@@ -3,38 +3,38 @@
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const themePkg = require('../package.json');
|
|
5
5
|
|
|
6
|
-
hexo.extend.helper.register('theme_version', function() {
|
|
6
|
+
hexo.extend.helper.register('theme_version', function () {
|
|
7
7
|
return 'v' + themePkg.version;
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
hexo.extend.filter.register('after_post_render', function(data) {
|
|
10
|
+
hexo.extend.filter.register('after_post_render', function (data) {
|
|
11
11
|
const lazyload = hexo.theme.config.lazyload;
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
if (!lazyload || !lazyload.enable) {
|
|
14
14
|
return data;
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
if (data.content) {
|
|
18
|
-
data.content = data.content.replace(/<img([^>]*)src=["']([^"']+)["']([^>]*)>/gi, function(match, before, src, after) {
|
|
18
|
+
data.content = data.content.replace(/<img([^>]*)src=["']([^"']+)["']([^>]*)>/gi, function (match, before, src, after) {
|
|
19
19
|
if (match.includes('data-src=')) {
|
|
20
20
|
return match;
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
let newAfter = after;
|
|
24
24
|
if (!newAfter.includes('class=')) {
|
|
25
25
|
newAfter = ' class=""' + newAfter;
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
const mediumZoom = hexo.theme.config.medium_zoom;
|
|
29
29
|
if (mediumZoom && mediumZoom.enable) {
|
|
30
30
|
if (!newAfter.includes('data-zoomable')) {
|
|
31
31
|
newAfter = newAfter.replace(/class=["']([^"']*)["']/, 'class="$1" data-zoomable');
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
return '<img' + before + 'data-src="' + src + '"' + newAfter + '>';
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
return data;
|
|
40
40
|
});
|
package/source/css/lazyload.css
CHANGED
package/source/css/main.css
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--primary-color: #FF7F78;
|
|
3
|
-
--primary-light: #FFE8E6;
|
|
4
|
-
--primary-dark: #D6665F;
|
|
5
2
|
--secondary-color: #625B71;
|
|
6
3
|
--surface-color: rgba(255, 255, 255, 0.45);
|
|
7
4
|
--surface-color-rgb: 255, 255, 255;
|
|
@@ -31,13 +28,21 @@
|
|
|
31
28
|
--sidebar-width: 280px;
|
|
32
29
|
--content-max-width: 1200px;
|
|
33
30
|
--border-color: rgba(0, 0, 0, 0.1);
|
|
34
|
-
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.sr-only {
|
|
34
|
+
position: absolute;
|
|
35
|
+
width: 1px;
|
|
36
|
+
height: 1px;
|
|
37
|
+
padding: 0;
|
|
38
|
+
margin: -1px;
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
clip: rect(0, 0, 0, 0);
|
|
41
|
+
white-space: nowrap;
|
|
42
|
+
border: 0;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
[data-theme="dark"] {
|
|
38
|
-
--primary-color: #FF9B95;
|
|
39
|
-
--primary-light: #8C3D37;
|
|
40
|
-
--primary-dark: #FFE8E6;
|
|
41
46
|
--surface-color: rgba(30, 30, 30, 0.45);
|
|
42
47
|
--surface-color-rgb: 30, 30, 30;
|
|
43
48
|
--background-color: #1C1B1F;
|
|
@@ -181,6 +186,7 @@ button {
|
|
|
181
186
|
bottom: 0;
|
|
182
187
|
z-index: 0;
|
|
183
188
|
pointer-events: none;
|
|
189
|
+
overflow: hidden;
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
.app__circle {
|
|
@@ -220,6 +226,70 @@ button {
|
|
|
220
226
|
animation-delay: -4s;
|
|
221
227
|
}
|
|
222
228
|
|
|
229
|
+
.app__particle {
|
|
230
|
+
position: absolute;
|
|
231
|
+
border-radius: 50%;
|
|
232
|
+
background: var(--primary-color);
|
|
233
|
+
opacity: 0;
|
|
234
|
+
animation: particleFloat 20s linear infinite;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.app__particle--1 {
|
|
238
|
+
width: 6px;
|
|
239
|
+
height: 6px;
|
|
240
|
+
left: 10%;
|
|
241
|
+
animation-delay: 0s;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.app__particle--2 {
|
|
245
|
+
width: 4px;
|
|
246
|
+
height: 4px;
|
|
247
|
+
left: 20%;
|
|
248
|
+
animation-delay: -5s;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.app__particle--3 {
|
|
252
|
+
width: 8px;
|
|
253
|
+
height: 8px;
|
|
254
|
+
left: 30%;
|
|
255
|
+
animation-delay: -10s;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.app__particle--4 {
|
|
259
|
+
width: 5px;
|
|
260
|
+
height: 5px;
|
|
261
|
+
left: 40%;
|
|
262
|
+
animation-delay: -15s;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.app__particle--5 {
|
|
266
|
+
width: 7px;
|
|
267
|
+
height: 7px;
|
|
268
|
+
left: 50%;
|
|
269
|
+
animation-delay: -7s;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.app__particle--6 {
|
|
273
|
+
width: 4px;
|
|
274
|
+
height: 4px;
|
|
275
|
+
left: 60%;
|
|
276
|
+
animation-delay: -12s;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.app__particle--7 {
|
|
280
|
+
width: 6px;
|
|
281
|
+
height: 6px;
|
|
282
|
+
left: 70%;
|
|
283
|
+
animation-delay: -3s;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.app__particle--8 {
|
|
287
|
+
width: 5px;
|
|
288
|
+
height: 5px;
|
|
289
|
+
left: 80%;
|
|
290
|
+
animation-delay: -18s;
|
|
291
|
+
}
|
|
292
|
+
|
|
223
293
|
@keyframes float {
|
|
224
294
|
|
|
225
295
|
0%,
|
|
@@ -240,6 +310,26 @@ button {
|
|
|
240
310
|
}
|
|
241
311
|
}
|
|
242
312
|
|
|
313
|
+
@keyframes particleFloat {
|
|
314
|
+
0% {
|
|
315
|
+
transform: translateY(100vh) rotate(0deg);
|
|
316
|
+
opacity: 0;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
10% {
|
|
320
|
+
opacity: 0.4;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
90% {
|
|
324
|
+
opacity: 0.4;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
100% {
|
|
328
|
+
transform: translateY(-100px) rotate(360deg);
|
|
329
|
+
opacity: 0;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
243
333
|
.main {
|
|
244
334
|
flex: 1;
|
|
245
335
|
padding-top: var(--header-height);
|
|
@@ -527,7 +617,7 @@ button {
|
|
|
527
617
|
display: grid;
|
|
528
618
|
grid-template-columns: 1fr var(--sidebar-width);
|
|
529
619
|
gap: 24px;
|
|
530
|
-
padding: 24px 0;
|
|
620
|
+
padding: 0 0 24px 0;
|
|
531
621
|
}
|
|
532
622
|
|
|
533
623
|
.tag-posts-page,
|
|
@@ -658,6 +748,97 @@ button {
|
|
|
658
748
|
gap: 20px;
|
|
659
749
|
}
|
|
660
750
|
|
|
751
|
+
.notification-banner {
|
|
752
|
+
padding: 0;
|
|
753
|
+
overflow: hidden;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
.notification-banner__inner {
|
|
757
|
+
position: relative;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
.notification-banner__content {
|
|
761
|
+
position: relative;
|
|
762
|
+
min-height: 44px;
|
|
763
|
+
cursor: grab;
|
|
764
|
+
user-select: none;
|
|
765
|
+
transition: height 0.3s ease;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
.notification-banner__content:active {
|
|
769
|
+
cursor: grabbing;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
.notification-banner__item {
|
|
773
|
+
position: absolute;
|
|
774
|
+
top: 0;
|
|
775
|
+
left: 0;
|
|
776
|
+
right: 0;
|
|
777
|
+
display: flex;
|
|
778
|
+
align-items: center;
|
|
779
|
+
justify-content: center;
|
|
780
|
+
padding: 12px 16px;
|
|
781
|
+
opacity: 0;
|
|
782
|
+
transform: translateX(20px);
|
|
783
|
+
transition: opacity var(--transition-normal), transform var(--transition-normal);
|
|
784
|
+
pointer-events: none;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
.notification-banner__item.is-active {
|
|
788
|
+
position: relative;
|
|
789
|
+
opacity: 1;
|
|
790
|
+
transform: translateX(0);
|
|
791
|
+
pointer-events: auto;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.notification-banner__message {
|
|
795
|
+
flex: 1;
|
|
796
|
+
font-size: 13px;
|
|
797
|
+
line-height: 1.5;
|
|
798
|
+
color: var(--text-primary);
|
|
799
|
+
text-align: center;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
.notification-banner__message a {
|
|
803
|
+
position: relative;
|
|
804
|
+
z-index: 1;
|
|
805
|
+
transition: color var(--transition-fast);
|
|
806
|
+
bottom: -0.55em;
|
|
807
|
+
right: 0.1em;
|
|
808
|
+
word-break: break-word;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
.notification-banner__indicators {
|
|
812
|
+
display: flex;
|
|
813
|
+
justify-content: center;
|
|
814
|
+
gap: 6px;
|
|
815
|
+
padding: 0 16px 12px;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
.notification-banner__indicator {
|
|
819
|
+
width: 6px;
|
|
820
|
+
height: 6px;
|
|
821
|
+
border-radius: 50%;
|
|
822
|
+
background: var(--border-color);
|
|
823
|
+
cursor: pointer;
|
|
824
|
+
transition: all var(--transition-fast);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
.notification-banner__indicator:hover {
|
|
828
|
+
background: var(--text-secondary);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.notification-banner__indicator.is-active {
|
|
832
|
+
background: var(--primary-color);
|
|
833
|
+
width: 16px;
|
|
834
|
+
border-radius: 3px;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.notification-banner--mobile {
|
|
838
|
+
display: none;
|
|
839
|
+
margin-bottom: 16px;
|
|
840
|
+
}
|
|
841
|
+
|
|
661
842
|
.author-card {
|
|
662
843
|
padding: 24px;
|
|
663
844
|
text-align: center;
|
|
@@ -1561,6 +1742,14 @@ button {
|
|
|
1561
1742
|
.sidebar {
|
|
1562
1743
|
display: none;
|
|
1563
1744
|
}
|
|
1745
|
+
|
|
1746
|
+
.notification-banner {
|
|
1747
|
+
display: none;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
.notification-banner--mobile {
|
|
1751
|
+
display: block;
|
|
1752
|
+
}
|
|
1564
1753
|
}
|
|
1565
1754
|
|
|
1566
1755
|
@media (max-width: 768px) {
|
|
@@ -1634,6 +1823,15 @@ button {
|
|
|
1634
1823
|
.categories-grid {
|
|
1635
1824
|
grid-template-columns: 1fr;
|
|
1636
1825
|
}
|
|
1826
|
+
|
|
1827
|
+
.friends-grid {
|
|
1828
|
+
grid-template-columns: repeat(1, 1fr);
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
.tag-posts-page .posts-list,
|
|
1832
|
+
.category-posts-page .posts-list {
|
|
1833
|
+
grid-template-columns: 1fr;
|
|
1834
|
+
}
|
|
1637
1835
|
}
|
|
1638
1836
|
|
|
1639
1837
|
::-webkit-scrollbar {
|
package/source/css/markdown.css
CHANGED
package/source/js/main.js
CHANGED
|
@@ -7,6 +7,174 @@
|
|
|
7
7
|
var menuBtn = document.getElementById('menuBtn');
|
|
8
8
|
var themeToggle = document.getElementById('themeToggle');
|
|
9
9
|
|
|
10
|
+
function initNotificationBanner(bannerId) {
|
|
11
|
+
const banner = document.getElementById(bannerId);
|
|
12
|
+
if (!banner) return;
|
|
13
|
+
|
|
14
|
+
const content = banner.querySelector('.notification-banner__content');
|
|
15
|
+
const items = banner.querySelectorAll('.notification-banner__item');
|
|
16
|
+
const indicatorsContainer = banner.querySelector('.notification-banner__indicators');
|
|
17
|
+
const indicators = banner.querySelectorAll('.notification-banner__indicator');
|
|
18
|
+
if (items.length <= 1) {
|
|
19
|
+
if (indicatorsContainer) indicatorsContainer.style.display = 'none';
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const interval = parseInt(banner.dataset.interval) || 5000;
|
|
24
|
+
let currentIndex = 0;
|
|
25
|
+
let autoPlayTimer = null;
|
|
26
|
+
|
|
27
|
+
let touchStartX = 0;
|
|
28
|
+
let touchEndX = 0;
|
|
29
|
+
let isSwiping = false;
|
|
30
|
+
|
|
31
|
+
function showItem(index, direction = 'next') {
|
|
32
|
+
const prevIndex = currentIndex;
|
|
33
|
+
items.forEach((item, i) => {
|
|
34
|
+
if (i === index) {
|
|
35
|
+
item.classList.add('is-active');
|
|
36
|
+
item.style.transform = 'translateX(0)';
|
|
37
|
+
item.style.opacity = '1';
|
|
38
|
+
} else if (i === prevIndex) {
|
|
39
|
+
item.classList.remove('is-active');
|
|
40
|
+
const translateDir = direction === 'next' ? '-20px' : '20px';
|
|
41
|
+
item.style.transform = `translateX(${translateDir})`;
|
|
42
|
+
item.style.opacity = '0';
|
|
43
|
+
} else {
|
|
44
|
+
item.classList.remove('is-active');
|
|
45
|
+
item.style.transform = 'translateX(20px)';
|
|
46
|
+
item.style.opacity = '0';
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const activeItem = items[index];
|
|
51
|
+
const height = activeItem.offsetHeight;
|
|
52
|
+
content.style.height = height + 'px';
|
|
53
|
+
|
|
54
|
+
indicators.forEach((indicator, i) => {
|
|
55
|
+
indicator.classList.toggle('is-active', i === index);
|
|
56
|
+
});
|
|
57
|
+
currentIndex = index;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function nextItem() {
|
|
61
|
+
const next = (currentIndex + 1) % items.length;
|
|
62
|
+
showItem(next, 'next');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function prevItem() {
|
|
66
|
+
const prev = (currentIndex - 1 + items.length) % items.length;
|
|
67
|
+
showItem(prev, 'prev');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function startAutoPlay() {
|
|
71
|
+
stopAutoPlay();
|
|
72
|
+
autoPlayTimer = setInterval(nextItem, interval);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function stopAutoPlay() {
|
|
76
|
+
if (autoPlayTimer) {
|
|
77
|
+
clearInterval(autoPlayTimer);
|
|
78
|
+
autoPlayTimer = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function handleTouchStart(e) {
|
|
83
|
+
touchStartX = e.touches[0].clientX;
|
|
84
|
+
isSwiping = true;
|
|
85
|
+
stopAutoPlay();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function handleTouchMove(e) {
|
|
89
|
+
if (!isSwiping) return;
|
|
90
|
+
touchEndX = e.touches[0].clientX;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handleTouchEnd() {
|
|
94
|
+
if (!isSwiping) return;
|
|
95
|
+
isSwiping = false;
|
|
96
|
+
|
|
97
|
+
const diff = touchStartX - touchEndX;
|
|
98
|
+
const threshold = 50;
|
|
99
|
+
|
|
100
|
+
if (Math.abs(diff) > threshold) {
|
|
101
|
+
if (diff > 0) {
|
|
102
|
+
nextItem();
|
|
103
|
+
} else {
|
|
104
|
+
prevItem();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
touchStartX = 0;
|
|
109
|
+
touchEndX = 0;
|
|
110
|
+
startAutoPlay();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function handleMouseDown(e) {
|
|
114
|
+
touchStartX = e.clientX;
|
|
115
|
+
isSwiping = true;
|
|
116
|
+
stopAutoPlay();
|
|
117
|
+
e.preventDefault();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function handleMouseMove(e) {
|
|
121
|
+
if (!isSwiping) return;
|
|
122
|
+
touchEndX = e.clientX;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function handleMouseUp() {
|
|
126
|
+
if (!isSwiping) return;
|
|
127
|
+
isSwiping = false;
|
|
128
|
+
|
|
129
|
+
const diff = touchStartX - touchEndX;
|
|
130
|
+
const threshold = 50;
|
|
131
|
+
|
|
132
|
+
if (Math.abs(diff) > threshold) {
|
|
133
|
+
if (diff > 0) {
|
|
134
|
+
nextItem();
|
|
135
|
+
} else {
|
|
136
|
+
prevItem();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
touchStartX = 0;
|
|
141
|
+
touchEndX = 0;
|
|
142
|
+
startAutoPlay();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
indicators.forEach((indicator, index) => {
|
|
146
|
+
indicator.addEventListener('click', () => {
|
|
147
|
+
const direction = index > currentIndex ? 'next' : 'prev';
|
|
148
|
+
showItem(index, direction);
|
|
149
|
+
startAutoPlay();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
content.addEventListener('touchstart', handleTouchStart, { passive: true });
|
|
154
|
+
content.addEventListener('touchmove', handleTouchMove, { passive: true });
|
|
155
|
+
content.addEventListener('touchend', handleTouchEnd);
|
|
156
|
+
|
|
157
|
+
content.addEventListener('mousedown', handleMouseDown);
|
|
158
|
+
content.addEventListener('mousemove', handleMouseMove);
|
|
159
|
+
content.addEventListener('mouseup', handleMouseUp);
|
|
160
|
+
content.addEventListener('mouseleave', handleMouseUp);
|
|
161
|
+
|
|
162
|
+
banner.addEventListener('mouseenter', stopAutoPlay);
|
|
163
|
+
banner.addEventListener('mouseleave', startAutoPlay);
|
|
164
|
+
|
|
165
|
+
const firstItem = items[0];
|
|
166
|
+
if (firstItem) {
|
|
167
|
+
content.style.height = firstItem.offsetHeight + 'px';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
startAutoPlay();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function initNotifications() {
|
|
174
|
+
initNotificationBanner('notificationBanner');
|
|
175
|
+
initNotificationBanner('notificationBannerMobile');
|
|
176
|
+
}
|
|
177
|
+
|
|
10
178
|
function initTheme() {
|
|
11
179
|
const savedTheme = localStorage.getItem(themeKey);
|
|
12
180
|
if (savedTheme === 'dark') {
|
|
@@ -244,9 +412,7 @@
|
|
|
244
412
|
listItemClass: 'toc-list-item',
|
|
245
413
|
activeListItemClass: 'is-active-li',
|
|
246
414
|
collapseDepth: 0,
|
|
247
|
-
scrollSmooth:
|
|
248
|
-
scrollSmoothDuration: 420,
|
|
249
|
-
scrollSmoothOffset: -80,
|
|
415
|
+
scrollSmooth: false,
|
|
250
416
|
headingsOffset: 80,
|
|
251
417
|
throttleTimeout: 50,
|
|
252
418
|
disableTocScrollSync: false
|
|
@@ -254,6 +420,45 @@
|
|
|
254
420
|
|
|
255
421
|
initTocBoundaryDetection(toc, postBody);
|
|
256
422
|
initTocToggle(toc, tocToggle);
|
|
423
|
+
initTocSmoothScroll(tocContent);
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function initTocSmoothScroll(tocContent) {
|
|
428
|
+
if (!tocContent) return;
|
|
429
|
+
|
|
430
|
+
tocContent.addEventListener('click', function (e) {
|
|
431
|
+
const link = e.target.closest('a[href^="#"]');
|
|
432
|
+
if (!link) return;
|
|
433
|
+
|
|
434
|
+
e.preventDefault();
|
|
435
|
+
const targetId = link.getAttribute('href').slice(1);
|
|
436
|
+
const targetElement = document.getElementById(targetId);
|
|
437
|
+
|
|
438
|
+
if (targetElement) {
|
|
439
|
+
const offset = 80;
|
|
440
|
+
const targetPosition = targetElement.getBoundingClientRect().top + window.scrollY - offset;
|
|
441
|
+
const startPosition = window.scrollY;
|
|
442
|
+
const distance = targetPosition - startPosition;
|
|
443
|
+
const duration = 400;
|
|
444
|
+
let startTime = null;
|
|
445
|
+
|
|
446
|
+
function linearScroll(currentTime) {
|
|
447
|
+
if (!startTime) startTime = currentTime;
|
|
448
|
+
const elapsed = currentTime - startTime;
|
|
449
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
450
|
+
|
|
451
|
+
window.scrollTo(0, startPosition + distance * progress);
|
|
452
|
+
|
|
453
|
+
if (progress < 1) {
|
|
454
|
+
requestAnimationFrame(linearScroll);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
requestAnimationFrame(linearScroll);
|
|
459
|
+
|
|
460
|
+
history.pushState(null, null, '#' + targetId);
|
|
461
|
+
}
|
|
257
462
|
});
|
|
258
463
|
}
|
|
259
464
|
|
|
@@ -353,7 +558,7 @@
|
|
|
353
558
|
img.classList.add('medium-zoom-image');
|
|
354
559
|
});
|
|
355
560
|
|
|
356
|
-
document.querySelectorAll('[data-zoomable]').forEach(function(img) {
|
|
561
|
+
document.querySelectorAll('[data-zoomable]').forEach(function (img) {
|
|
357
562
|
if (!img.classList.contains('medium-zoom-image')) {
|
|
358
563
|
img.classList.add('medium-zoom-image');
|
|
359
564
|
}
|
|
@@ -385,6 +590,7 @@
|
|
|
385
590
|
initCodeBlocks();
|
|
386
591
|
initToc();
|
|
387
592
|
initMediumZoom();
|
|
593
|
+
initNotifications();
|
|
388
594
|
|
|
389
595
|
window.scrollTo(0, 0);
|
|
390
596
|
}
|
|
@@ -420,6 +626,7 @@
|
|
|
420
626
|
|
|
421
627
|
initCodeBlocks();
|
|
422
628
|
initToc();
|
|
629
|
+
initNotifications();
|
|
423
630
|
}
|
|
424
631
|
|
|
425
632
|
function handleOutsideClick(e) {
|