hexo-theme-particlex 2.4.10 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +15 -4
- package/_config.yml +6 -4
- package/layout/archives.ejs +42 -35
- package/layout/card.ejs +4 -2
- package/layout/categories.ejs +7 -1
- package/layout/{script.ejs → comment.ejs} +0 -10
- package/layout/footer.ejs +6 -3
- package/layout/import.ejs +44 -0
- package/layout/index.ejs +3 -3
- package/layout/layout.ejs +25 -28
- package/layout/menu.ejs +5 -5
- package/layout/post.ejs +23 -7
- package/layout/posts.ejs +7 -1
- package/layout/tags.ejs +7 -1
- package/package.json +5 -1
- package/source/css/{particlex.css → main.css} +128 -98
- package/source/js/lib/crypto.js +41 -0
- package/source/js/lib/highlight.js +32 -0
- package/source/js/lib/math.js +15 -0
- package/source/js/lib/preview.js +26 -0
- package/source/js/lib/search.js +28 -0
- package/source/js/main.js +47 -0
- package/layout/loading.ejs +0 -9
- package/source/js/functions.js +0 -71
- package/source/js/particlex.js +0 -98
package/README.md
CHANGED
@@ -69,7 +69,6 @@ theme: particlex
|
|
69
69
|
avatar: # Avatar image
|
70
70
|
headBlockEnable: true # Home page info block
|
71
71
|
background: # Home page background image
|
72
|
-
highlightStyle: github # Highlight style
|
73
72
|
```
|
74
73
|
|
75
74
|
- 导航栏
|
@@ -170,9 +169,21 @@ highlightStyle: github # Highlight style
|
|
170
169
|
- default
|
171
170
|
```
|
172
171
|
|
173
|
-
-
|
172
|
+
- 代码高亮
|
174
173
|
|
175
|
-
使用
|
174
|
+
使用 Highlight.js 代码高亮
|
175
|
+
|
176
|
+
样式可以在[这里](https://highlightjs.org/static/demo)选择,默认为 GitHub
|
177
|
+
|
178
|
+
```yaml
|
179
|
+
highlight:
|
180
|
+
enable: false
|
181
|
+
style: github
|
182
|
+
```
|
183
|
+
|
184
|
+
- 数学渲染
|
185
|
+
|
186
|
+
使用 KaTeX 渲染数学公式
|
176
187
|
|
177
188
|
```yaml
|
178
189
|
math:
|
@@ -194,7 +205,7 @@ highlightStyle: github # Highlight style
|
|
194
205
|
|
195
206
|
- 搜索
|
196
207
|
|
197
|
-
嵌入到 Archives
|
208
|
+
嵌入到 Archives 中的搜索
|
198
209
|
|
199
210
|
目前只支持搜索文档标题(我太弱了)
|
200
211
|
|
package/_config.yml
CHANGED
@@ -10,10 +10,6 @@ headBlockEnable: true
|
|
10
10
|
# Home page background image
|
11
11
|
background:
|
12
12
|
|
13
|
-
# Highlight style
|
14
|
-
# https://highlightjs.org
|
15
|
-
highlightStyle: github
|
16
|
-
|
17
13
|
# ParticleX theme icon is adopts the Font Awesome 6
|
18
14
|
# https://fontawesome.com/search
|
19
15
|
|
@@ -76,6 +72,12 @@ polyfill:
|
|
76
72
|
features:
|
77
73
|
- default
|
78
74
|
|
75
|
+
# Highlight.js
|
76
|
+
# https://highlightjs.org
|
77
|
+
highlight:
|
78
|
+
enable: true
|
79
|
+
style: github
|
80
|
+
|
79
81
|
# Rendering math with KaTeX
|
80
82
|
math:
|
81
83
|
enable: false
|
package/layout/archives.ejs
CHANGED
@@ -4,46 +4,53 @@
|
|
4
4
|
%>
|
5
5
|
<div id="archives">
|
6
6
|
<% if (theme.search.enable) { %>
|
7
|
-
<
|
8
|
-
<input id="search-bar" class="input" placeholder="搜索" style="z-index: <%- posts.length + 2 %>">
|
7
|
+
<input id="search-bar" class="input" placeholder="搜索" v-model="rawSearch" />
|
9
8
|
<% } %>
|
10
|
-
|
11
|
-
|
12
|
-
<div class="timeline-
|
13
|
-
|
14
|
-
<div class="
|
15
|
-
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
<
|
9
|
+
<div id="timeline-wrap" ref="timeline">
|
10
|
+
<% posts.reverse().forEach((post, id) => { %>
|
11
|
+
<div class="timeline" data-title="<%- post.title.toLowerCase().replace(/\s+/gm, "") %>">
|
12
|
+
<div class="timeline-tail"></div>
|
13
|
+
<div class="timeline-content">
|
14
|
+
<div class="item-time"><%= date(post.date, "YYYY/M/D") %></div>
|
15
|
+
<a href="<%- url_for(post.path) %>">
|
16
|
+
<h3><%= post.title %></h3>
|
17
|
+
</a>
|
18
|
+
<div class="info">
|
19
|
+
<% if (post.categories && post.categories.data.length !== 0) { %>
|
20
|
+
<span class="category">
|
21
|
+
<a href="<%- url_for(post.categories.data[0].path) %>">
|
22
|
+
<span class="icon">
|
23
|
+
<i class="fa-solid fa-bookmark fa-fw"></i>
|
24
|
+
</span>
|
25
|
+
<%= post.categories.data[0].name %>
|
26
|
+
</a>
|
27
|
+
</span>
|
28
|
+
<% } %>
|
29
|
+
<% if (post.tags && post.tags.data.length !== 0) { %>
|
30
|
+
<span class="tags">
|
22
31
|
<span class="icon">
|
23
|
-
<i class="fa-solid fa-
|
32
|
+
<i class="fa-solid fa-tags fa-fw"></i>
|
24
33
|
</span>
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
%>
|
40
|
-
<a href="<%- url_for(data.path) %>" style="<%- color[num] %>"><%= data.name %></a>
|
34
|
+
<% post.tags.data.forEach(data => { %>
|
35
|
+
<span class="tag">
|
36
|
+
<%
|
37
|
+
const color = [
|
38
|
+
"color: #ffa2c4",
|
39
|
+
"color: #00bcd4",
|
40
|
+
"color: #03a9f4",
|
41
|
+
"color: #00a596",
|
42
|
+
"color: #ff7d73",
|
43
|
+
];
|
44
|
+
let num = Math.floor(Math.random() * color.length);
|
45
|
+
%>
|
46
|
+
<a href="<%- url_for(data.path) %>" style="<%- color[num] %>"><%= data.name %></a>
|
47
|
+
</span>
|
48
|
+
<% }); %>
|
41
49
|
</span>
|
42
|
-
<% }
|
43
|
-
</
|
44
|
-
<% } %>
|
50
|
+
<% } %>
|
51
|
+
</div>
|
45
52
|
</div>
|
46
53
|
</div>
|
54
|
+
<% }); %>
|
47
55
|
</div>
|
48
|
-
<% }); %>
|
49
56
|
</div>
|
package/layout/card.ejs
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
<div id="card-div">
|
2
2
|
<div class="card-style" style="width: 300px">
|
3
3
|
<div class="avatar">
|
4
|
-
<img src="<%- url_for(theme.avatar) %>" alt="avatar"
|
4
|
+
<img src="<%- url_for(theme.avatar) %>" alt="avatar" />
|
5
5
|
</div>
|
6
6
|
<div class="name"><%= config.author %></div>
|
7
7
|
<div class="description">
|
@@ -12,7 +12,9 @@
|
|
12
12
|
<% Object.keys(theme.card.iconLinks).forEach(key => { %>
|
13
13
|
<span class="icon-link">
|
14
14
|
<a href="<%- url_for(theme.card.iconLinks[key].link) %>">
|
15
|
-
<i
|
15
|
+
<i
|
16
|
+
class="fa-<%- theme.card.iconLinks[key].theme %> fa-<%- theme.card.iconLinks[key].name %> fa-fw"
|
17
|
+
></i>
|
16
18
|
</a>
|
17
19
|
</span>
|
18
20
|
<% }); %>
|
package/layout/categories.ejs
CHANGED
@@ -51,7 +51,13 @@
|
|
51
51
|
<% post.tags.data.forEach(data => { %>
|
52
52
|
<span class="tag">
|
53
53
|
<%
|
54
|
-
const color = [
|
54
|
+
const color = [
|
55
|
+
"color: #ffa2c4",
|
56
|
+
"color: #00bcd4",
|
57
|
+
"color: #03a9f4",
|
58
|
+
"color: #00a596",
|
59
|
+
"color: #ff7d73",
|
60
|
+
];
|
55
61
|
let num = Math.floor(Math.random() * color.length);
|
56
62
|
%>
|
57
63
|
<a href="<%- url_for(data.path) %>" style="<%- color[num] %>"><%= data.name %></a>
|
@@ -1,9 +1,4 @@
|
|
1
|
-
<script src="<%- url_for("/js/functions.js") %>"></script>
|
2
|
-
<script src="<%- url_for("/js/particlex.js") %>"></script>
|
3
|
-
<% if (type === "post" && page.comments) { %>
|
4
1
|
<% if (theme.gitalk.enable) { %>
|
5
|
-
<script src="https://cdn.staticfile.org/gitalk/1.8.0/gitalk.min.js"></script>
|
6
|
-
<link rel="stylesheet" href="https://cdn.staticfile.org/gitalk/1.8.0/gitalk.min.css">
|
7
2
|
<script>
|
8
3
|
let clientID = "<%- theme.gitalk.clientID %>",
|
9
4
|
clientSecret = "<%- theme.gitalk.clientSecret %>";
|
@@ -48,9 +43,6 @@
|
|
48
43
|
></script>
|
49
44
|
<% } %>
|
50
45
|
<% if (theme.waline.enable) { %>
|
51
|
-
<script src="https://cdn.staticfile.org/waline/2.14.7/waline.min.js"></script>
|
52
|
-
<link rel="stylesheet" href="https://cdn.staticfile.org/waline/2.14.7/waline.min.css">
|
53
|
-
<link rel="stylesheet" href="https://cdn.staticfile.org/waline/2.14.7/waline-meta.min.css">
|
54
46
|
<script>
|
55
47
|
Waline.init({
|
56
48
|
el: "#waline-container",
|
@@ -69,7 +61,6 @@
|
|
69
61
|
</script>
|
70
62
|
<% } %>
|
71
63
|
<% if (theme.twikoo.enable) { %>
|
72
|
-
<script src="https://cdn.staticfile.org/twikoo/1.6.8/twikoo.all.min.js"></script>
|
73
64
|
<script>
|
74
65
|
twikoo.init({
|
75
66
|
el: "#twikoo-container",
|
@@ -80,4 +71,3 @@
|
|
80
71
|
})
|
81
72
|
</script>
|
82
73
|
<% } %>
|
83
|
-
<% } %>
|
package/layout/footer.ejs
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
<footer id="footer">
|
2
|
-
<div
|
2
|
+
<div id="footer-wrap">
|
3
3
|
<div>
|
4
4
|
©
|
5
5
|
<%= theme.footer.since %> - <%= date(Date.now(), "YYYY") %> <%= config.title %>
|
6
|
-
<span
|
6
|
+
<span id="footer-icon">
|
7
7
|
<i class="fa-solid fa-font-awesome fa-fw"></i>
|
8
8
|
</span>
|
9
9
|
@<%= config.author %>
|
10
10
|
</div>
|
11
|
-
<div>
|
11
|
+
<div>
|
12
|
+
Based on the <a href="https://hexo.io">Hexo Engine</a> &
|
13
|
+
<a href="https://github.com/argvchs/hexo-theme-particlex">ParticleX Theme</a>
|
14
|
+
</div>
|
12
15
|
<% if (theme.footer.ICP.enable) { %>
|
13
16
|
<div>
|
14
17
|
备案号:
|
@@ -0,0 +1,44 @@
|
|
1
|
+
<script src="https://cdn.staticfile.org/vue/3.2.45/vue.global.prod.min.js"></script>
|
2
|
+
<link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.2.1/css/all.min.css" />
|
3
|
+
<link rel="stylesheet" href="<%- url_for("/css/fonts.min.css") %>" />
|
4
|
+
<script>const mixins = [];</script>
|
5
|
+
<% if (theme.highlight.enable) { %>
|
6
|
+
<script src="https://cdn.staticfile.org/highlight.js/11.7.0/highlight.min.js"></script>
|
7
|
+
<link
|
8
|
+
rel="stylesheet"
|
9
|
+
href="https://cdn.staticfile.org/highlight.js/11.7.0/styles/<%- theme.highlight.style %>.min.css"
|
10
|
+
/>
|
11
|
+
<script src="<%- url_for("/js/lib/highlight.js") %>"></script>
|
12
|
+
<% } %>
|
13
|
+
<% if (theme.polyfill.enable) { %>
|
14
|
+
<script src="https://polyfill.io/v3/polyfill.min.js?features=<%- theme.polyfill.features.join(",") %>"></script>
|
15
|
+
<% } %>
|
16
|
+
<% if (theme.math.enable) { %>
|
17
|
+
<script src="https://cdn.staticfile.org/KaTeX/0.16.4/katex.min.js"></script>
|
18
|
+
<script src="https://cdn.staticfile.org/KaTeX/0.16.4/contrib/auto-render.min.js"></script>
|
19
|
+
<link rel="stylesheet" href="https://cdn.staticfile.org/KaTeX/0.16.4/katex.min.css" />
|
20
|
+
<script src="<%- url_for("/js/lib/math.js") %>"></script>
|
21
|
+
<% } %>
|
22
|
+
<% if (theme.crypto.enable && typeof page.secret !== "undefined") { %>
|
23
|
+
<script src="https://cdn.staticfile.org/crypto-js/4.1.1/crypto-js.min.js"></script>
|
24
|
+
<script src="<%- url_for("/js/lib/crypto.js") %>"></script>
|
25
|
+
<% } %>
|
26
|
+
<% if (theme.search.enable && type === "archives") { %>
|
27
|
+
<script src="<%- url_for("/js/lib/search.js") %>"></script>
|
28
|
+
<% } %>
|
29
|
+
<% if (page.comments && type === "post") { %>
|
30
|
+
<% if (theme.gitalk.enable) { %>
|
31
|
+
<script src="https://cdn.staticfile.org/gitalk/1.8.0/gitalk.min.js"></script>
|
32
|
+
<link rel="stylesheet" href="https://cdn.staticfile.org/gitalk/1.8.0/gitalk.min.css" />
|
33
|
+
<% } %>
|
34
|
+
<% if (theme.waline.enable) { %>
|
35
|
+
<script src="https://cdn.staticfile.org/waline/2.14.7/waline.min.js"></script>
|
36
|
+
<link rel="stylesheet" href="https://cdn.staticfile.org/waline/2.14.7/waline.min.css" />
|
37
|
+
<link rel="stylesheet" href="https://cdn.staticfile.org/waline/2.14.7/waline-meta.min.css" />
|
38
|
+
<% } %>
|
39
|
+
<% if (theme.twikoo.enable) { %>
|
40
|
+
<script src="https://cdn.staticfile.org/twikoo/1.6.8/twikoo.all.min.js"></script>
|
41
|
+
<% } %>
|
42
|
+
<% } %>
|
43
|
+
<script src="<%- url_for("/js/lib/preview.js") %>"></script>
|
44
|
+
<link rel="stylesheet" href="<%- url_for("/css/main.css") %>" />
|
package/layout/index.ejs
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
<div id="home-head">
|
1
|
+
<div id="home-head" ref="head">
|
2
2
|
<div id="home-background" style="background-image: url(<%- theme.background %>)"></div>
|
3
3
|
<% if (theme.headBlockEnable) { %>
|
4
|
-
<div id="home-info" @click="
|
4
|
+
<div id="home-info" @click="homeClick">
|
5
5
|
<span class="loop"></span>
|
6
6
|
<span class="loop"></span>
|
7
7
|
<span class="loop"></span>
|
@@ -16,7 +16,7 @@
|
|
16
16
|
</div>
|
17
17
|
<% } %>
|
18
18
|
</div>
|
19
|
-
<div id="home-posts-wrap"
|
19
|
+
<div id="home-posts-wrap" <%- theme.card.enable ? "" : 'class="home-posts-wrap-no-card"' %> ref="wrap">
|
20
20
|
<div id="home-posts">
|
21
21
|
<div id="posts">
|
22
22
|
<%- partial("posts") %>
|
package/layout/layout.ejs
CHANGED
@@ -24,45 +24,42 @@
|
|
24
24
|
<!DOCTYPE html>
|
25
25
|
<html lang="<%- config.language %>">
|
26
26
|
<head>
|
27
|
-
<meta charset="UTF-8"
|
27
|
+
<meta charset="UTF-8" />
|
28
28
|
<title><%= title %></title>
|
29
|
-
<meta name="author" content="<%- config.author %>"
|
30
|
-
<meta name="description" content="<%- config.description %>"
|
31
|
-
<meta name="keywords" content="<%- config.keywords %>"
|
32
|
-
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
33
|
-
<link rel="icon" href="<%- url_for(theme.avatar) %>"
|
34
|
-
|
35
|
-
<script src="https://cdn.staticfile.org/highlight.js/11.7.0/highlight.min.js"></script>
|
36
|
-
<link rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/11.7.0/styles/<%- theme.highlightStyle %>.min.css">
|
37
|
-
<link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.2.1/css/all.min.css">
|
38
|
-
<% if (theme.polyfill.enable) { %>
|
39
|
-
<script src="https://polyfill.io/v3/polyfill.min.js?features=<%- theme.polyfill.features.join(",") %>"></script>
|
40
|
-
<% } %>
|
41
|
-
<% if (theme.math.enable) { %>
|
42
|
-
<script src="https://cdn.staticfile.org/KaTeX/0.16.4/katex.min.js"></script>
|
43
|
-
<script src="https://cdn.staticfile.org/KaTeX/0.16.4/contrib/auto-render.min.js"></script>
|
44
|
-
<link rel="stylesheet" href="https://cdn.staticfile.org/KaTeX/0.16.4/katex.min.css">
|
45
|
-
<% } %>
|
46
|
-
<% if (theme.crypto.enable && typeof page.secret !== "undefined") { %>
|
47
|
-
<script src="https://cdn.staticfile.org/crypto-js/4.1.1/crypto-js.min.js"></script>
|
48
|
-
<% } %>
|
49
|
-
<link rel="stylesheet" href="<%- url_for("/css/fonts.min.css") %>">
|
50
|
-
<link rel="stylesheet" href="<%- url_for("/css/particlex.css") %>">
|
29
|
+
<meta name="author" content="<%- config.author %>" />
|
30
|
+
<meta name="description" content="<%- config.description %>" />
|
31
|
+
<meta name="keywords" content="<%- config.keywords %>" />
|
32
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
|
33
|
+
<link rel="icon" href="<%- url_for(theme.avatar) %>" />
|
34
|
+
<%- partial("import", { type }) %>
|
51
35
|
</head>
|
52
36
|
<body>
|
53
|
-
<%- partial("loading") %>
|
54
37
|
<div id="layout">
|
38
|
+
<transition name="fade">
|
39
|
+
<div id="loading" v-show="loading">
|
40
|
+
<div id="loading-circle">
|
41
|
+
<h2>LOADING</h2>
|
42
|
+
<p>加载过慢请开启缓存 浏览器默认开启</p>
|
43
|
+
<img src="<%- url_for("/images/loading.gif") %>" />
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
</transition>
|
55
47
|
<transition name="into">
|
56
|
-
<div id="main" v-show="
|
48
|
+
<div id="main" v-show="!loading">
|
57
49
|
<%- partial("menu") %>
|
58
50
|
<%- partial(type) %>
|
59
51
|
<%- partial("footer") %>
|
60
52
|
</div>
|
61
53
|
</transition>
|
62
|
-
<
|
63
|
-
|
54
|
+
<transition name="fade">
|
55
|
+
<div id="preview" ref="preview" v-show="previewShow">
|
56
|
+
<img id="preview-content" ref="previewContent" />
|
64
57
|
</div>
|
58
|
+
</transition>
|
65
59
|
</div>
|
66
|
-
<%-
|
60
|
+
<script src="<%- url_for("/js/main.js") %>"></script>
|
61
|
+
<% if (type === "post" && page.comments) { %>
|
62
|
+
<%- partial("comment") %>
|
63
|
+
<% } %>
|
67
64
|
</body>
|
68
65
|
</html>
|
package/layout/menu.ejs
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<nav id="menu">
|
1
|
+
<nav id="menu" ref="menu">
|
2
2
|
<div class="desktop-menu">
|
3
3
|
<a class="title" href="<%- config.root %>">
|
4
4
|
<span><%= config.title.toUpperCase() %></span>
|
@@ -10,14 +10,14 @@
|
|
10
10
|
</a>
|
11
11
|
<% }); %>
|
12
12
|
</div>
|
13
|
-
<div
|
14
|
-
<div class="curtain" @click="
|
15
|
-
<div class="title" @click="
|
13
|
+
<div id="mobile-menu">
|
14
|
+
<div class="curtain" v-show="showMenu" @click="showMenu = !showMenu"></div>
|
15
|
+
<div class="title" @click="showMenu = !showMenu">
|
16
16
|
<i class="fa-solid fa-bars fa-fw"></i>
|
17
17
|
<span> <%= config.title.toUpperCase() %></span>
|
18
18
|
</div>
|
19
19
|
<transition name="slide">
|
20
|
-
<div class="items" v-show="
|
20
|
+
<div class="items" v-show="showMenu">
|
21
21
|
<% Object.keys(theme.menu).forEach(key => { %>
|
22
22
|
<a href="<%- url_for(theme.menu[key].src) %>">
|
23
23
|
<div class="item">
|
package/layout/post.ejs
CHANGED
@@ -27,7 +27,13 @@
|
|
27
27
|
<% page.tags.data.forEach(data => { %>
|
28
28
|
<span class="tag">
|
29
29
|
<%
|
30
|
-
const color = [
|
30
|
+
const color = [
|
31
|
+
"color: #ffa2c4",
|
32
|
+
"color: #00bcd4",
|
33
|
+
"color: #03a9f4",
|
34
|
+
"color: #00a596",
|
35
|
+
"color: #ff7d73",
|
36
|
+
];
|
31
37
|
let num = Math.floor(Math.random() * color.length);
|
32
38
|
%>
|
33
39
|
<a href="<%- url_for(data.path) %>" style="<%- color[num] %>"><%= data.name %></a>
|
@@ -39,15 +45,25 @@
|
|
39
45
|
<% if (theme.crypto.enable && typeof page.secret !== "undefined") { %>
|
40
46
|
<%
|
41
47
|
const CryptoJS = crypto();
|
42
|
-
function
|
43
|
-
return CryptoJS.SHA256(
|
48
|
+
function SHA(word) {
|
49
|
+
return CryptoJS.SHA256(word).toString();
|
44
50
|
}
|
45
|
-
function encrypt(
|
46
|
-
return CryptoJS.AES.encrypt(
|
51
|
+
function encrypt(word, secret) {
|
52
|
+
return CryptoJS.AES.encrypt(word, secret).toString();
|
47
53
|
}
|
48
54
|
%>
|
49
|
-
<input
|
50
|
-
|
55
|
+
<input
|
56
|
+
id="crypto"
|
57
|
+
class="input"
|
58
|
+
ref="crypto"
|
59
|
+
placeholder="文章被加密,请输入密码"
|
60
|
+
data-encrypted="<%- encrypt(page.content, page.secret) %>"
|
61
|
+
data-shasum="<%- SHA(page.content) %>"
|
62
|
+
v-model="crypto"
|
63
|
+
/>
|
64
|
+
<transition name="fade">
|
65
|
+
<div class="content" ref="content" v-show="check"></div>
|
66
|
+
</transition>
|
51
67
|
<% } else { %>
|
52
68
|
<div class="content" v-pre>
|
53
69
|
<%- page.content %>
|
package/layout/posts.ejs
CHANGED
@@ -61,7 +61,13 @@
|
|
61
61
|
<% post.tags.data.forEach(data => { %>
|
62
62
|
<span class="tag">
|
63
63
|
<%
|
64
|
-
const color = [
|
64
|
+
const color = [
|
65
|
+
"color: #ffa2c4",
|
66
|
+
"color: #00bcd4",
|
67
|
+
"color: #03a9f4",
|
68
|
+
"color: #00a596",
|
69
|
+
"color: #ff7d73",
|
70
|
+
];
|
65
71
|
let num = Math.floor(Math.random() * color.length);
|
66
72
|
%>
|
67
73
|
<a href="<%- url_for(data.path) %>" style="<%- color[num] %>">
|
package/layout/tags.ejs
CHANGED
@@ -51,7 +51,13 @@
|
|
51
51
|
<% post.tags.data.forEach(data => { %>
|
52
52
|
<span class="tag">
|
53
53
|
<%
|
54
|
-
const color = [
|
54
|
+
const color = [
|
55
|
+
"color: #ffa2c4",
|
56
|
+
"color: #00bcd4",
|
57
|
+
"color: #03a9f4",
|
58
|
+
"color: #00a596",
|
59
|
+
"color: #ff7d73",
|
60
|
+
];
|
55
61
|
let num = Math.floor(Math.random() * color.length);
|
56
62
|
%>
|
57
63
|
<a href="<%- url_for(data.path) %>" style="<%- color[num] %>"><%= data.name %></a>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "hexo-theme-particlex",
|
3
|
-
"version": "2.
|
3
|
+
"version": "2.5.0",
|
4
4
|
"description": "A concise Hexo theme, based on Particle.",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -20,6 +20,10 @@
|
|
20
20
|
"url": "https://github.com/argvchs/hexo-theme-particlex/issues"
|
21
21
|
},
|
22
22
|
"homepage": "https://github.com/argvchs/hexo-theme-particlex#readme",
|
23
|
+
"dependencies": {
|
24
|
+
"hexo-helper-crypto": "^1.1.0",
|
25
|
+
"hexo-renderer-ejs": "^2.0.0"
|
26
|
+
},
|
23
27
|
"scripts": {
|
24
28
|
"test": "echo \"Error: no test specified\" && exit 1"
|
25
29
|
}
|
@@ -1,53 +1,3 @@
|
|
1
|
-
@keyframes into {
|
2
|
-
from {
|
3
|
-
opacity: 0;
|
4
|
-
transform: scale(1.1);
|
5
|
-
}
|
6
|
-
to {
|
7
|
-
opacity: 1;
|
8
|
-
transform: scale(1);
|
9
|
-
}
|
10
|
-
}
|
11
|
-
@keyframes loading {
|
12
|
-
from {
|
13
|
-
opacity: 0;
|
14
|
-
}
|
15
|
-
to {
|
16
|
-
opacity: 1;
|
17
|
-
}
|
18
|
-
}
|
19
|
-
@keyframes loop1 {
|
20
|
-
from {
|
21
|
-
transform: rotate(30deg);
|
22
|
-
}
|
23
|
-
to {
|
24
|
-
transform: rotate(390deg);
|
25
|
-
}
|
26
|
-
}
|
27
|
-
@keyframes loop2 {
|
28
|
-
from {
|
29
|
-
transform: rotate(60deg);
|
30
|
-
}
|
31
|
-
to {
|
32
|
-
transform: rotate(420deg);
|
33
|
-
}
|
34
|
-
}
|
35
|
-
@keyframes loop3 {
|
36
|
-
from {
|
37
|
-
transform: rotate(90deg);
|
38
|
-
}
|
39
|
-
to {
|
40
|
-
transform: rotate(450deg);
|
41
|
-
}
|
42
|
-
}
|
43
|
-
@keyframes loop4 {
|
44
|
-
from {
|
45
|
-
transform: rotate(120deg);
|
46
|
-
}
|
47
|
-
to {
|
48
|
-
transform: rotate(480deg);
|
49
|
-
}
|
50
|
-
}
|
51
1
|
#archives {
|
52
2
|
margin: auto;
|
53
3
|
margin-top: 100px;
|
@@ -117,19 +67,19 @@
|
|
117
67
|
text-align: center;
|
118
68
|
width: 100%;
|
119
69
|
}
|
120
|
-
#footer
|
70
|
+
#footer #footer-icon {
|
121
71
|
color: #66afef;
|
122
72
|
display: inline-block;
|
123
73
|
font-size: 18px;
|
124
74
|
margin: 0 10px;
|
125
75
|
}
|
126
|
-
#footer
|
76
|
+
#footer #footer-wrap {
|
127
77
|
border-top: 1px solid #aaa;
|
128
78
|
color: #5c6b72;
|
129
79
|
margin: auto;
|
130
80
|
width: 900px;
|
131
81
|
}
|
132
|
-
#footer
|
82
|
+
#footer #footer-wrap div {
|
133
83
|
margin: 15px;
|
134
84
|
}
|
135
85
|
#home-card {
|
@@ -376,9 +326,42 @@
|
|
376
326
|
#home-posts-wrap,
|
377
327
|
#archives,
|
378
328
|
.article,
|
379
|
-
#footer
|
329
|
+
#footer #footer-wrap {
|
380
330
|
box-sizing: border-box;
|
381
331
|
}
|
332
|
+
#loading {
|
333
|
+
align-items: center;
|
334
|
+
background: #fff;
|
335
|
+
display: flex;
|
336
|
+
flex-direction: column;
|
337
|
+
height: 100vh;
|
338
|
+
justify-content: center;
|
339
|
+
left: 0;
|
340
|
+
position: fixed;
|
341
|
+
top: 0;
|
342
|
+
width: 100vw;
|
343
|
+
z-index: 2147483647;
|
344
|
+
}
|
345
|
+
#loading h2,
|
346
|
+
#loading p,
|
347
|
+
#loading img {
|
348
|
+
margin: 10px;
|
349
|
+
}
|
350
|
+
#loading img {
|
351
|
+
border-radius: 0;
|
352
|
+
height: 50px;
|
353
|
+
}
|
354
|
+
#loading-circle {
|
355
|
+
align-items: center;
|
356
|
+
border: 10px solid #a3ddfb;
|
357
|
+
border-radius: 50%;
|
358
|
+
display: flex;
|
359
|
+
flex-direction: column;
|
360
|
+
height: 50vmin;
|
361
|
+
justify-content: center;
|
362
|
+
padding: 50px;
|
363
|
+
width: 50vmin;
|
364
|
+
}
|
382
365
|
#main {
|
383
366
|
margin-right: calc(100% - 100vw);
|
384
367
|
overflow: auto;
|
@@ -391,8 +374,8 @@
|
|
391
374
|
position: fixed;
|
392
375
|
top: 0;
|
393
376
|
transition: background 0.25s ease-out, top 0.25s ease-out;
|
394
|
-
width:
|
395
|
-
z-index:
|
377
|
+
width: 100vw;
|
378
|
+
z-index: 10004;
|
396
379
|
}
|
397
380
|
#menu .desktop-menu {
|
398
381
|
height: 50px;
|
@@ -408,11 +391,11 @@
|
|
408
391
|
display: inline-block;
|
409
392
|
margin-left: 30px;
|
410
393
|
}
|
411
|
-
#menu
|
394
|
+
#menu #mobile-menu {
|
412
395
|
min-height: 50px;
|
413
396
|
text-align: center;
|
414
397
|
}
|
415
|
-
#menu
|
398
|
+
#menu #mobile-menu .curtain {
|
416
399
|
height: 100%;
|
417
400
|
left: 0;
|
418
401
|
position: fixed;
|
@@ -420,26 +403,26 @@
|
|
420
403
|
width: 100%;
|
421
404
|
z-index: -1;
|
422
405
|
}
|
423
|
-
#menu
|
406
|
+
#menu #mobile-menu .items {
|
424
407
|
padding: 10px 0 20px;
|
425
|
-
z-index:
|
408
|
+
z-index: 10002;
|
426
409
|
}
|
427
|
-
#menu
|
410
|
+
#menu #mobile-menu .items .item {
|
428
411
|
display: flex;
|
429
412
|
justify-content: center;
|
430
413
|
margin: auto;
|
431
414
|
min-width: 200px;
|
432
415
|
width: 80%;
|
433
416
|
}
|
434
|
-
#menu
|
417
|
+
#menu #mobile-menu .items a {
|
435
418
|
color: #555;
|
436
419
|
}
|
437
|
-
#menu
|
420
|
+
#menu #mobile-menu .title {
|
438
421
|
color: #555;
|
439
422
|
cursor: pointer;
|
440
|
-
z-index:
|
423
|
+
z-index: 10003;
|
441
424
|
}
|
442
|
-
#menu.hidden
|
425
|
+
#menu.hidden {
|
443
426
|
top: -70px !important;
|
444
427
|
}
|
445
428
|
#menu.menu-color {
|
@@ -450,38 +433,32 @@
|
|
450
433
|
#menu.menu-color a {
|
451
434
|
color: #fff !important;
|
452
435
|
}
|
453
|
-
#
|
454
|
-
margin: 0 auto 50px;
|
455
|
-
}
|
456
|
-
#search-mask {
|
457
|
-
background: #f6f8fa;
|
458
|
-
height: 150px;
|
459
|
-
margin: auto;
|
460
|
-
margin-bottom: -25px;
|
461
|
-
margin-top: -125px;
|
462
|
-
width: 100%;
|
463
|
-
}
|
464
|
-
#showimg {
|
436
|
+
#preview {
|
465
437
|
align-items: center;
|
466
438
|
background-color: #fffc;
|
467
439
|
display: flex;
|
468
440
|
height: 100vh;
|
469
441
|
justify-content: center;
|
470
442
|
left: 0;
|
471
|
-
opacity: 0;
|
472
443
|
position: fixed;
|
473
444
|
top: 0;
|
474
|
-
transition: opacity 0.25s, visibility 0.25s;
|
475
|
-
visibility: hidden;
|
476
445
|
width: 100vw;
|
477
|
-
z-index:
|
446
|
+
z-index: 10005;
|
478
447
|
}
|
479
|
-
#
|
448
|
+
#preview-content {
|
480
449
|
box-shadow: 0 0 50px 10px #d9d9d980;
|
481
450
|
margin: auto;
|
482
451
|
max-height: 95%;
|
483
452
|
max-width: 95%;
|
484
453
|
}
|
454
|
+
#search-bar {
|
455
|
+
margin: 0 auto 50px;
|
456
|
+
z-index: 10001;
|
457
|
+
}
|
458
|
+
#timeline-wrap {
|
459
|
+
display: flex;
|
460
|
+
flex-direction: column-reverse;
|
461
|
+
}
|
485
462
|
* {
|
486
463
|
margin: 0;
|
487
464
|
padding: 0;
|
@@ -547,6 +524,14 @@ body::-webkit-scrollbar-track {
|
|
547
524
|
.copycode:not(.copied) i:last-child {
|
548
525
|
opacity: 0;
|
549
526
|
}
|
527
|
+
.fade-enter-active,
|
528
|
+
.fade-leave-active {
|
529
|
+
transition: opacity 0.3s;
|
530
|
+
}
|
531
|
+
.fade-enter-from,
|
532
|
+
.fade-leave-to {
|
533
|
+
opacity: 0;
|
534
|
+
}
|
550
535
|
.icon {
|
551
536
|
color: #5c6b72;
|
552
537
|
margin-right: 5px;
|
@@ -575,7 +560,15 @@ body::-webkit-scrollbar-track {
|
|
575
560
|
}
|
576
561
|
.into-enter-active,
|
577
562
|
.into-leave-active {
|
578
|
-
|
563
|
+
transition: opacity 0.5s, transform 0.5s;
|
564
|
+
}
|
565
|
+
.into-enter-from,
|
566
|
+
.into-leave-to {
|
567
|
+
opacity: 0;
|
568
|
+
transform: scale(1.1);
|
569
|
+
}
|
570
|
+
.katex {
|
571
|
+
overflow: auto;
|
579
572
|
}
|
580
573
|
.language {
|
581
574
|
background: linear-gradient(to right, #ed6ea0 0%, #ec8c69 100%);
|
@@ -589,14 +582,18 @@ body::-webkit-scrollbar-track {
|
|
589
582
|
position: absolute;
|
590
583
|
top: 0;
|
591
584
|
}
|
592
|
-
.katex {
|
593
|
-
overflow: auto;
|
594
|
-
}
|
595
585
|
.page-num,
|
596
586
|
.icon-link a,
|
597
587
|
.friend-link a {
|
598
588
|
transition: background 0.25s, color 0.25s;
|
599
589
|
}
|
590
|
+
.page-num:hover,
|
591
|
+
.icon-link a:hover,
|
592
|
+
.friend-link a:hover,
|
593
|
+
.categories-tags a:hover,
|
594
|
+
.go-post:hover {
|
595
|
+
opacity: 1;
|
596
|
+
}
|
600
597
|
.slide-enter-active,
|
601
598
|
.slide-leave-active {
|
602
599
|
transition: margin-top 0.3s, opacity 0.3s;
|
@@ -608,7 +605,7 @@ body::-webkit-scrollbar-track {
|
|
608
605
|
}
|
609
606
|
.timeline {
|
610
607
|
margin-bottom: 30px;
|
611
|
-
transition: margin-top 0.5s, opacity 0.
|
608
|
+
transition: margin-top 0.5s, opacity 0.3s, visibility 0.3s;
|
612
609
|
}
|
613
610
|
.timeline-content {
|
614
611
|
background: #fff;
|
@@ -690,6 +687,7 @@ audio,
|
|
690
687
|
iframe,
|
691
688
|
#home-head,
|
692
689
|
#menu,
|
690
|
+
#loading,
|
693
691
|
.katex,
|
694
692
|
.go-post,
|
695
693
|
.page-current,
|
@@ -720,13 +718,6 @@ h6 {
|
|
720
718
|
font-weight: bold;
|
721
719
|
margin: 15px 0;
|
722
720
|
}
|
723
|
-
.page-num:hover,
|
724
|
-
.icon-link a:hover,
|
725
|
-
.friend-link a:hover,
|
726
|
-
.categories-tags a:hover,
|
727
|
-
.go-post:hover {
|
728
|
-
opacity: 1;
|
729
|
-
}
|
730
721
|
h2 {
|
731
722
|
font-size: 27px;
|
732
723
|
}
|
@@ -752,6 +743,13 @@ audio,
|
|
752
743
|
iframe {
|
753
744
|
border-radius: 10px;
|
754
745
|
}
|
746
|
+
mark {
|
747
|
+
background: #fff13360;
|
748
|
+
border-radius: 4px;
|
749
|
+
color: unset;
|
750
|
+
line-height: 2.5;
|
751
|
+
padding: 4px 8px;
|
752
|
+
}
|
755
753
|
p,
|
756
754
|
ul,
|
757
755
|
ol {
|
@@ -794,6 +792,38 @@ ul li,
|
|
794
792
|
ol li {
|
795
793
|
margin: 8px 0;
|
796
794
|
}
|
795
|
+
@keyframes loop1 {
|
796
|
+
from {
|
797
|
+
transform: rotate(30deg);
|
798
|
+
}
|
799
|
+
to {
|
800
|
+
transform: rotate(390deg);
|
801
|
+
}
|
802
|
+
}
|
803
|
+
@keyframes loop2 {
|
804
|
+
from {
|
805
|
+
transform: rotate(60deg);
|
806
|
+
}
|
807
|
+
to {
|
808
|
+
transform: rotate(420deg);
|
809
|
+
}
|
810
|
+
}
|
811
|
+
@keyframes loop3 {
|
812
|
+
from {
|
813
|
+
transform: rotate(90deg);
|
814
|
+
}
|
815
|
+
to {
|
816
|
+
transform: rotate(450deg);
|
817
|
+
}
|
818
|
+
}
|
819
|
+
@keyframes loop4 {
|
820
|
+
from {
|
821
|
+
transform: rotate(120deg);
|
822
|
+
}
|
823
|
+
to {
|
824
|
+
transform: rotate(480deg);
|
825
|
+
}
|
826
|
+
}
|
797
827
|
@media (min-width: 900px) {
|
798
828
|
#home-card {
|
799
829
|
margin-right: auto;
|
@@ -844,12 +874,12 @@ ol li {
|
|
844
874
|
#menu .desktop-menu {
|
845
875
|
display: block;
|
846
876
|
}
|
847
|
-
#menu
|
877
|
+
#menu #mobile-menu {
|
848
878
|
display: none;
|
849
879
|
}
|
850
880
|
.article,
|
851
881
|
#archives,
|
852
|
-
#footer
|
882
|
+
#footer #footer-wrap {
|
853
883
|
width: 900px;
|
854
884
|
}
|
855
885
|
.home-posts-wrap-no-card #home-posts {
|
@@ -925,14 +955,14 @@ ol li {
|
|
925
955
|
#home-posts-wrap,
|
926
956
|
.article,
|
927
957
|
#archives,
|
928
|
-
#footer
|
958
|
+
#footer #footer-wrap {
|
929
959
|
width: 100%;
|
930
960
|
}
|
931
961
|
#menu .desktop-menu,
|
932
962
|
#home-card {
|
933
963
|
display: none;
|
934
964
|
}
|
935
|
-
#menu
|
965
|
+
#menu #mobile-menu {
|
936
966
|
display: block;
|
937
967
|
}
|
938
968
|
ul,
|
@@ -0,0 +1,41 @@
|
|
1
|
+
const cryptoMixin = {
|
2
|
+
data() {
|
3
|
+
return {
|
4
|
+
crypto: "",
|
5
|
+
check: false,
|
6
|
+
};
|
7
|
+
},
|
8
|
+
methods: {
|
9
|
+
SHA(word) {
|
10
|
+
return CryptoJS.SHA256(word).toString();
|
11
|
+
},
|
12
|
+
decrypt(word, secret, shasum) {
|
13
|
+
try {
|
14
|
+
let res = CryptoJS.AES.decrypt(word, secret).toString(CryptoJS.enc.Utf8);
|
15
|
+
return { check: this.SHA(res) === shasum, decrypted: res };
|
16
|
+
} catch {
|
17
|
+
return { check: false };
|
18
|
+
}
|
19
|
+
},
|
20
|
+
},
|
21
|
+
watch: {
|
22
|
+
crypto(value) {
|
23
|
+
let input = this.$refs.crypto,
|
24
|
+
content = this.$refs.content;
|
25
|
+
let { decrypted, check } = this.decrypt(
|
26
|
+
input.dataset.encrypted,
|
27
|
+
value,
|
28
|
+
input.dataset.shasum
|
29
|
+
);
|
30
|
+
this.check = check;
|
31
|
+
if (check) {
|
32
|
+
input.classList.remove("fail");
|
33
|
+
input.classList.add("success");
|
34
|
+
input.disabled = true;
|
35
|
+
content.innerHTML = decrypted;
|
36
|
+
this.render();
|
37
|
+
} else input.classList.add("fail");
|
38
|
+
},
|
39
|
+
},
|
40
|
+
};
|
41
|
+
mixins.push(cryptoMixin);
|
@@ -0,0 +1,32 @@
|
|
1
|
+
const highlightMixin = {
|
2
|
+
data() {
|
3
|
+
return { copying: false };
|
4
|
+
},
|
5
|
+
mounted() {
|
6
|
+
hljs.configure({ ignoreUnescapedHTML: true });
|
7
|
+
},
|
8
|
+
methods: {
|
9
|
+
highlight() {
|
10
|
+
let that = this;
|
11
|
+
let codes = document.getElementsByTagName("pre");
|
12
|
+
for (let i of codes) {
|
13
|
+
let lang = [...i.classList, ...i.firstChild.classList][0] || "plaintext";
|
14
|
+
let code = i.innerText;
|
15
|
+
i.innerHTML = `<div class="code-content">${code}</div><div class="language">${lang}</div><div class="copycode"><i class="fa-solid fa-copy fa-fw"></i><i class="fa-solid fa-clone fa-fw"></i></div>`;
|
16
|
+
let copycode = i.getElementsByClassName("copycode")[0];
|
17
|
+
copycode.addEventListener("click", async function () {
|
18
|
+
if (that.copying) return;
|
19
|
+
that.copying = true;
|
20
|
+
this.classList.add("copied");
|
21
|
+
await navigator.clipboard.writeText(code);
|
22
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
23
|
+
this.classList.remove("copied");
|
24
|
+
that.copying = false;
|
25
|
+
});
|
26
|
+
let content = i.getElementsByClassName("code-content")[0];
|
27
|
+
hljs.highlightElement(content);
|
28
|
+
}
|
29
|
+
},
|
30
|
+
},
|
31
|
+
};
|
32
|
+
mixins.push(highlightMixin);
|
@@ -0,0 +1,15 @@
|
|
1
|
+
const mathMixin = {
|
2
|
+
methods: {
|
3
|
+
math() {
|
4
|
+
renderMathInElement(document.body, {
|
5
|
+
delimiters: [
|
6
|
+
{ left: "$$", right: "$$", display: true },
|
7
|
+
{ left: "$", right: "$", display: false },
|
8
|
+
{ left: "\\(", right: "\\)", display: false },
|
9
|
+
{ left: "\\[", right: "\\]", display: true },
|
10
|
+
],
|
11
|
+
});
|
12
|
+
},
|
13
|
+
},
|
14
|
+
};
|
15
|
+
mixins.push(mathMixin);
|
@@ -0,0 +1,26 @@
|
|
1
|
+
const previewMixin = {
|
2
|
+
data() {
|
3
|
+
return { previewShow: false };
|
4
|
+
},
|
5
|
+
methods: {
|
6
|
+
preview() {
|
7
|
+
let that = this;
|
8
|
+
let preview = this.$refs.preview,
|
9
|
+
content = this.$refs.previewContent,
|
10
|
+
images = document.getElementsByTagName("img");
|
11
|
+
for (let i of images)
|
12
|
+
i.addEventListener("click", function () {
|
13
|
+
content.alt = this.alt;
|
14
|
+
content.src = this.src;
|
15
|
+
that.previewShow = true;
|
16
|
+
});
|
17
|
+
preview.addEventListener("click", () => {
|
18
|
+
this.previewShow = false;
|
19
|
+
});
|
20
|
+
window.addEventListener("resize", () => {
|
21
|
+
this.previewShow = false;
|
22
|
+
});
|
23
|
+
},
|
24
|
+
},
|
25
|
+
};
|
26
|
+
mixins.push(previewMixin);
|
@@ -0,0 +1,28 @@
|
|
1
|
+
const searchMixin = {
|
2
|
+
data() {
|
3
|
+
return {
|
4
|
+
rawSearch: "",
|
5
|
+
};
|
6
|
+
},
|
7
|
+
watch: {
|
8
|
+
search(value) {
|
9
|
+
let timeline = this.$refs.timeline.childNodes;
|
10
|
+
for (let i of timeline)
|
11
|
+
if (!value || i.dataset.title.includes(value)) {
|
12
|
+
i.style.opacity = 1;
|
13
|
+
i.style.visibility = "visible";
|
14
|
+
i.style.marginTop = 0;
|
15
|
+
} else {
|
16
|
+
i.style.opacity = 0;
|
17
|
+
i.style.visibility = "hidden";
|
18
|
+
i.style.marginTop = -i.offsetHeight - 30 + "px";
|
19
|
+
}
|
20
|
+
},
|
21
|
+
},
|
22
|
+
computed: {
|
23
|
+
search() {
|
24
|
+
return this.rawSearch.toLowerCase().replace(/s+/gm, "");
|
25
|
+
},
|
26
|
+
},
|
27
|
+
};
|
28
|
+
mixins.push(searchMixin);
|
@@ -0,0 +1,47 @@
|
|
1
|
+
const app = Vue.createApp({
|
2
|
+
mixins,
|
3
|
+
data() {
|
4
|
+
return {
|
5
|
+
loading: true,
|
6
|
+
showMenu: false,
|
7
|
+
barLocal: 0,
|
8
|
+
};
|
9
|
+
},
|
10
|
+
created() {
|
11
|
+
window.addEventListener("load", () => {
|
12
|
+
this.loading = false;
|
13
|
+
});
|
14
|
+
},
|
15
|
+
mounted() {
|
16
|
+
if (this.$refs.head) this.$refs.menu.classList.add("menu-color");
|
17
|
+
window.addEventListener("scroll", this.handleScroll, true);
|
18
|
+
this.render();
|
19
|
+
},
|
20
|
+
methods: {
|
21
|
+
homeClick() {
|
22
|
+
window.scrollTo({ top: window.innerHeight, behavior: "smooth" });
|
23
|
+
},
|
24
|
+
handleScroll() {
|
25
|
+
let menu = this.$refs.menu,
|
26
|
+
wrap = this.$refs.wrap;
|
27
|
+
let newlocal = document.documentElement.scrollTop;
|
28
|
+
if (this.barLocal < newlocal) {
|
29
|
+
this.showMenu = false;
|
30
|
+
menu.classList.add("hidden");
|
31
|
+
} else menu.classList.remove("hidden");
|
32
|
+
if (wrap) {
|
33
|
+
if (newlocal <= window.innerHeight - 100) menu.classList.add("menu-color");
|
34
|
+
else menu.classList.remove("menu-color");
|
35
|
+
if (newlocal <= 400) wrap.style.marginTop = -newlocal / 5 + "px";
|
36
|
+
else wrap.style.marginTop = "-80px";
|
37
|
+
}
|
38
|
+
this.barLocal = newlocal;
|
39
|
+
},
|
40
|
+
render() {
|
41
|
+
if (typeof this.highlight !== "undefined") this.highlight();
|
42
|
+
if (typeof this.math !== "undefined") this.math();
|
43
|
+
this.preview();
|
44
|
+
},
|
45
|
+
},
|
46
|
+
});
|
47
|
+
app.mount("#layout");
|
package/layout/loading.ejs
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
<div id="loading" style="height: 100vh; width: 100vw; left: 0; top: 0; position: fixed; display: flex; z-index: 2147483647; background: #fff; transition: opacity 0.3s ease-out; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; pointer-events: none">
|
2
|
-
<div style="width: 50vmin; height: 50vmin; margin: auto; padding: 50px; border-radius: 50%; display: flex; border: solid 10px #a3ddfb">
|
3
|
-
<div style="margin: auto; text-align: center">
|
4
|
-
<h2>LOADING</h2>
|
5
|
-
<p>加载过慢请开启缓存,浏览器默认开启</p>
|
6
|
-
<img src="<%- url_for("/images/loading.gif") %>" style="height: 50px; border-radius: 0">
|
7
|
-
</div>
|
8
|
-
</div>
|
9
|
-
</div>
|
package/source/js/functions.js
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
function sleep(ms) {
|
2
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
3
|
-
}
|
4
|
-
let copying = false;
|
5
|
-
function highlight() {
|
6
|
-
hljs.configure({ ignoreUnescapedHTML: true });
|
7
|
-
let codes = document.getElementsByTagName("pre");
|
8
|
-
for (let i of codes) {
|
9
|
-
let lang = [...i.classList, ...i.firstChild.classList][0] || "plaintext";
|
10
|
-
i.innerHTML = `<div class="code-content">${i.innerHTML}</div><div class="language">${lang}</div><div class="copycode"><i class="fa-solid fa-copy fa-fw"></i><i class="fa-solid fa-clone fa-fw"></i></div>`;
|
11
|
-
let copycode = i.getElementsByClassName("copycode")[0];
|
12
|
-
copycode.addEventListener("click", async function () {
|
13
|
-
if (copying) return;
|
14
|
-
copying = true;
|
15
|
-
this.classList.add("copied");
|
16
|
-
await navigator.clipboard.writeText(this.parentElement.firstChild.innerText);
|
17
|
-
await sleep(1000);
|
18
|
-
this.classList.remove("copied");
|
19
|
-
copying = false;
|
20
|
-
});
|
21
|
-
hljs.highlightElement(i.getElementsByClassName("code-content")[0]);
|
22
|
-
}
|
23
|
-
}
|
24
|
-
function showimg() {
|
25
|
-
let wrap = document.getElementById("showimg"),
|
26
|
-
content = document.getElementById("showimg-content"),
|
27
|
-
images = document.querySelectorAll(".article .content img");
|
28
|
-
function show(image) {
|
29
|
-
content.alt = image.alt;
|
30
|
-
content.src = image.src;
|
31
|
-
wrap.style.opacity = 1;
|
32
|
-
wrap.style.visibility = "visible";
|
33
|
-
}
|
34
|
-
function hide() {
|
35
|
-
wrap.style.opacity = 0;
|
36
|
-
wrap.style.visibility = "hidden";
|
37
|
-
}
|
38
|
-
for (let i of images)
|
39
|
-
i.addEventListener("click", function () {
|
40
|
-
show(this);
|
41
|
-
});
|
42
|
-
wrap.addEventListener("click", hide);
|
43
|
-
window.addEventListener("resize", hide);
|
44
|
-
}
|
45
|
-
function rendermath() {
|
46
|
-
if (typeof renderMathInElement !== "undefined")
|
47
|
-
renderMathInElement(document.body, {
|
48
|
-
delimiters: [
|
49
|
-
{ left: "$$", right: "$$", display: true },
|
50
|
-
{ left: "$", right: "$", display: false },
|
51
|
-
{ left: "\\(", right: "\\)", display: false },
|
52
|
-
{ left: "\\[", right: "\\]", display: true },
|
53
|
-
],
|
54
|
-
});
|
55
|
-
}
|
56
|
-
function renderall() {
|
57
|
-
highlight();
|
58
|
-
showimg();
|
59
|
-
rendermath();
|
60
|
-
}
|
61
|
-
function sha(str) {
|
62
|
-
return CryptoJS.SHA256(str).toString();
|
63
|
-
}
|
64
|
-
function decrypt(str, key, shasum) {
|
65
|
-
try {
|
66
|
-
let res = CryptoJS.AES.decrypt(str, key).toString(CryptoJS.enc.Utf8);
|
67
|
-
return { decrypt: res, check: sha(res) === shasum };
|
68
|
-
} catch {
|
69
|
-
return { check: false };
|
70
|
-
}
|
71
|
-
}
|
package/source/js/particlex.js
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
const app = Vue.createApp({
|
2
|
-
data() {
|
3
|
-
return {
|
4
|
-
showpage: false,
|
5
|
-
menushow: false,
|
6
|
-
cardtop: 100,
|
7
|
-
barlocal: 0,
|
8
|
-
composition: false,
|
9
|
-
};
|
10
|
-
},
|
11
|
-
created() {
|
12
|
-
window.addEventListener("load", () => {
|
13
|
-
this.showpage = true;
|
14
|
-
document.getElementById("loading").style.opacity = 0;
|
15
|
-
});
|
16
|
-
},
|
17
|
-
mounted() {
|
18
|
-
if (document.getElementById("home-head"))
|
19
|
-
document.getElementById("menu").className += " menu-color";
|
20
|
-
if (document.getElementById("crypto")) {
|
21
|
-
let input = document.getElementById("crypto");
|
22
|
-
input.addEventListener("input", () => {
|
23
|
-
if (!this.composition) this.handlecrypto();
|
24
|
-
});
|
25
|
-
input.addEventListener("compositionstart", () => {
|
26
|
-
this.composition = true;
|
27
|
-
});
|
28
|
-
input.addEventListener("compositionend", () => {
|
29
|
-
this.handlecrypto();
|
30
|
-
this.composition = false;
|
31
|
-
});
|
32
|
-
}
|
33
|
-
if (document.getElementById("search-bar")) {
|
34
|
-
let input = document.getElementById("search-bar");
|
35
|
-
input.addEventListener("input", () => {
|
36
|
-
if (!this.composition) this.handlesearch();
|
37
|
-
});
|
38
|
-
input.addEventListener("compositionstart", () => {
|
39
|
-
this.composition = true;
|
40
|
-
});
|
41
|
-
input.addEventListener("compositionend", () => {
|
42
|
-
this.handlesearch();
|
43
|
-
this.composition = false;
|
44
|
-
});
|
45
|
-
}
|
46
|
-
window.addEventListener("scroll", this.handlescroll, true);
|
47
|
-
renderall();
|
48
|
-
},
|
49
|
-
methods: {
|
50
|
-
homeclick() {
|
51
|
-
window.scrollTo({ top: window.innerHeight, behavior: "smooth" });
|
52
|
-
},
|
53
|
-
handlescroll() {
|
54
|
-
let newlocal = document.documentElement.scrollTop;
|
55
|
-
let menu = document.getElementById("menu");
|
56
|
-
let wrap = document.getElementById("home-posts-wrap");
|
57
|
-
if (this.barlocal < newlocal) {
|
58
|
-
menu.className = "hidden-menu";
|
59
|
-
this.menushow = false;
|
60
|
-
} else menu.className = "show-menu";
|
61
|
-
if (wrap) {
|
62
|
-
if (newlocal <= window.innerHeight - 100) menu.className += " menu-color";
|
63
|
-
if (newlocal <= 400) wrap.style.marginTop = newlocal / -5 + "px";
|
64
|
-
else wrap.style.marginTop = "-80px";
|
65
|
-
}
|
66
|
-
this.barlocal = newlocal;
|
67
|
-
},
|
68
|
-
handlecrypto() {
|
69
|
-
let input = document.getElementById("crypto"),
|
70
|
-
content = document.getElementsByClassName("content")[0];
|
71
|
-
let res = decrypt(input.dataset.encrypt, input.value, input.dataset.shasum);
|
72
|
-
if (res.check) {
|
73
|
-
input.disabled = true;
|
74
|
-
input.classList.remove("fail");
|
75
|
-
input.classList.add("success");
|
76
|
-
content.innerHTML = res.decrypt;
|
77
|
-
content.style.opacity = 1;
|
78
|
-
renderall();
|
79
|
-
} else input.classList.add("fail");
|
80
|
-
},
|
81
|
-
handlesearch() {
|
82
|
-
let input = document.getElementById("search-bar"),
|
83
|
-
timeline = document.getElementsByClassName("timeline"),
|
84
|
-
key = input.value.toLowerCase().replace(/s+/gm, "");
|
85
|
-
for (let i of timeline)
|
86
|
-
if (!key || i.dataset.title.includes(key)) {
|
87
|
-
i.style.opacity = 1;
|
88
|
-
i.style.pointerEvents = "";
|
89
|
-
i.style.marginTop = "";
|
90
|
-
} else {
|
91
|
-
i.style.opacity = 0;
|
92
|
-
i.style.pointerEvents = "none";
|
93
|
-
i.style.marginTop = -i.offsetHeight - 30 + "px";
|
94
|
-
}
|
95
|
-
},
|
96
|
-
},
|
97
|
-
});
|
98
|
-
app.mount("#layout");
|