hexo-theme-gnix 7.0.0 → 9.0.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/README.md +6 -2
- package/include/hexo/encrypt.js +42 -0
- package/include/hexo/feed.js +330 -0
- package/include/util/common.js +7 -16
- package/languages/en.yml +5 -2
- package/languages/zh-CN.yml +5 -2
- package/layout/archive.jsx +8 -204
- package/layout/comment/twikoo.jsx +2 -11
- package/layout/common/article.jsx +45 -32
- package/layout/common/article_cover.jsx +11 -1
- package/layout/common/article_media.jsx +2 -4
- package/layout/common/footer.jsx +10 -14
- package/layout/common/head.jsx +7 -15
- package/layout/common/navbar.jsx +3 -18
- package/layout/common/scripts.jsx +6 -5
- package/layout/common/theme_selector.jsx +5 -6
- package/layout/common/toc.jsx +8 -14
- package/layout/index.jsx +2 -4
- package/layout/misc/open_graph.jsx +4 -4
- package/layout/misc/paginator.jsx +10 -4
- package/layout/misc/structured_data.jsx +3 -4
- package/layout/plugin/busuanzi.jsx +1 -1
- package/layout/plugin/cookie_consent.jsx +40 -31
- package/layout/plugin/swup.jsx +2 -22
- package/layout/search/insight.jsx +16 -3
- package/package.json +12 -8
- package/scripts/hot-reload.js +92 -0
- package/scripts/index.js +2 -0
- package/source/css/archive.css +251 -0
- package/source/css/default.css +300 -309
- package/source/css/encrypt.css +55 -0
- package/source/css/responsive/desktop.css +0 -119
- package/source/css/responsive/mobile.css +2 -22
- package/source/css/responsive/touch.css +9 -103
- package/source/css/twikoo.css +265 -249
- package/source/img/og_image.webp +0 -0
- package/source/js/archive-breadcrumb.js +1 -5
- package/source/js/busuanzi.js +1 -12
- package/source/js/components/chat.js +239 -0
- package/source/js/components/image-carousel.js +410 -0
- package/source/js/components/text-image-section.js +180 -0
- package/source/js/components/theme-stacked.js +165 -246
- package/source/js/components/tree.js +437 -0
- package/source/js/decrypt.js +112 -0
- package/source/js/insight.js +75 -65
- package/source/js/main.js +48 -31
- package/source/js/mdit/mermaid.js +12 -4
- package/source/js/swup.bundle.js +1 -0
- package/source/js/theme-selector.js +94 -113
- package/source/img/og_image.png +0 -0
- package/source/js/host/swup/Swup.umd.min.js +0 -1
- package/source/js/host/swup/head-plugin.umd.min.js +0 -1
- package/source/js/host/swup/scripts-plugin.umd.min.js +0 -2
package/layout/archive.jsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const {
|
|
2
|
-
const { Component, Fragment } = require("../include/util/common");
|
|
1
|
+
const { Component, Fragment, isValidDate, parseISO, dateFormatters } = require("../include/util/common");
|
|
3
2
|
const ArticleMedia = require("./common/article_media");
|
|
4
3
|
|
|
5
4
|
module.exports = class extends Component {
|
|
@@ -7,201 +6,6 @@ module.exports = class extends Component {
|
|
|
7
6
|
const { page, helper, site, config } = this.props;
|
|
8
7
|
const { url_for, date_xml, date } = helper;
|
|
9
8
|
|
|
10
|
-
const inlineCSS = `
|
|
11
|
-
@keyframes blink {
|
|
12
|
-
0%, 100% { opacity: 1; }
|
|
13
|
-
50% { opacity: 0; }
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.article-meta {
|
|
17
|
-
font-size: 0.8rem;
|
|
18
|
-
color: var(--subtext1);
|
|
19
|
-
font-family: var(--font-handwriting);
|
|
20
|
-
}
|
|
21
|
-
a.archive-title {
|
|
22
|
-
font-family: var(--font-sans-serif);
|
|
23
|
-
font-weight: 400;
|
|
24
|
-
color: var(--text);
|
|
25
|
-
|
|
26
|
-
&:hover {
|
|
27
|
-
color: var(--accent);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.archive-breadcrumb {
|
|
32
|
-
color: var(--blue);
|
|
33
|
-
font-family: var(--font-mono);
|
|
34
|
-
margin: 0 0 1rem 0;
|
|
35
|
-
padding-left: 1em;
|
|
36
|
-
display: flex;
|
|
37
|
-
flex-wrap: wrap;
|
|
38
|
-
align-items: center;
|
|
39
|
-
gap: 0;
|
|
40
|
-
}
|
|
41
|
-
.archive-breadcrumb .prompt {
|
|
42
|
-
color: var(--green);
|
|
43
|
-
user-select: none;
|
|
44
|
-
margin-right: 0.25em;
|
|
45
|
-
}
|
|
46
|
-
.archive-breadcrumb .cursor {
|
|
47
|
-
display: inline-block;
|
|
48
|
-
color: var(--mauve);
|
|
49
|
-
font-weight: bold;
|
|
50
|
-
margin-left: 2px;
|
|
51
|
-
animation: blink 1s step-end infinite;
|
|
52
|
-
user-select: none;
|
|
53
|
-
}
|
|
54
|
-
.archive-breadcrumb__cmd {
|
|
55
|
-
color: var(--yellow);
|
|
56
|
-
user-select: none;
|
|
57
|
-
padding-right: 0.5em;
|
|
58
|
-
}
|
|
59
|
-
.archive-breadcrumb__picker {
|
|
60
|
-
position: relative;
|
|
61
|
-
display: inline-flex;
|
|
62
|
-
align-items: center;
|
|
63
|
-
}
|
|
64
|
-
.archive-breadcrumb__trigger {
|
|
65
|
-
display: inline-flex;
|
|
66
|
-
align-items: center;
|
|
67
|
-
border: none;
|
|
68
|
-
background: transparent;
|
|
69
|
-
color: var(--yellow);
|
|
70
|
-
font-family: var(--font-mono);
|
|
71
|
-
padding: 0.05em 0.15em;
|
|
72
|
-
border-radius: 4px;
|
|
73
|
-
text-decoration: underline;
|
|
74
|
-
text-decoration-color: hsl(from var(--yellow) h s l / 0.6);
|
|
75
|
-
text-decoration-thickness: 1px;
|
|
76
|
-
text-underline-offset: 0.22em;
|
|
77
|
-
cursor: pointer;
|
|
78
|
-
transition: transform 120ms ease, color 120ms ease, background 120ms ease, text-decoration-color 120ms ease;
|
|
79
|
-
}
|
|
80
|
-
.archive-breadcrumb__trigger:hover {
|
|
81
|
-
color: var(--mauve);
|
|
82
|
-
background: hsl(from var(--base) h s l / 0.35);
|
|
83
|
-
text-decoration-color: hsl(from var(--mauve) h s l / 0.75);
|
|
84
|
-
}
|
|
85
|
-
.archive-breadcrumb__trigger:focus-visible {
|
|
86
|
-
outline: 2px solid hsl(from var(--mauve) h s l / 0.7);
|
|
87
|
-
outline-offset: 2px;
|
|
88
|
-
background: hsl(from var(--base) h s l / 0.35);
|
|
89
|
-
}
|
|
90
|
-
.archive-breadcrumb__trigger[aria-expanded="true"] {
|
|
91
|
-
transform: translateY(-1px);
|
|
92
|
-
color: var(--mauve);
|
|
93
|
-
text-decoration-color: hsl(from var(--mauve) h s l / 0.9);
|
|
94
|
-
}
|
|
95
|
-
.archive-breadcrumb__trigger[disabled] {
|
|
96
|
-
opacity: 0.45;
|
|
97
|
-
cursor: not-allowed;
|
|
98
|
-
text-decoration-color: hsl(from var(--subtext1) h s l / 0.4);
|
|
99
|
-
}
|
|
100
|
-
.archive-breadcrumb__menu {
|
|
101
|
-
position: absolute;
|
|
102
|
-
top: calc(100% + 6px);
|
|
103
|
-
left: 0;
|
|
104
|
-
min-width: 12rem;
|
|
105
|
-
max-height: 15rem;
|
|
106
|
-
overflow: auto;
|
|
107
|
-
background: hsl(from var(--base) h s l / 0.9);
|
|
108
|
-
border: 1px solid hsl(from var(--surface1) h s l / 0.9);
|
|
109
|
-
border-radius: 10px;
|
|
110
|
-
padding: 0.35rem;
|
|
111
|
-
box-shadow: 0 18px 50px hsl(from var(--crust) h s l / 0.45);
|
|
112
|
-
opacity: 0;
|
|
113
|
-
transform: translateY(-6px);
|
|
114
|
-
visibility: hidden;
|
|
115
|
-
pointer-events: none;
|
|
116
|
-
transition: opacity 160ms ease, transform 160ms ease, visibility 0s linear 160ms;
|
|
117
|
-
z-index: 20;
|
|
118
|
-
}
|
|
119
|
-
.archive-breadcrumb__trigger[aria-expanded="true"] + .archive-breadcrumb__menu {
|
|
120
|
-
opacity: 1;
|
|
121
|
-
transform: translateY(0);
|
|
122
|
-
visibility: visible;
|
|
123
|
-
pointer-events: auto;
|
|
124
|
-
transition: opacity 160ms ease, transform 160ms ease, visibility 0s;
|
|
125
|
-
}
|
|
126
|
-
.archive-breadcrumb__option {
|
|
127
|
-
width: 100%;
|
|
128
|
-
display: flex;
|
|
129
|
-
justify-content: space-between;
|
|
130
|
-
align-items: center;
|
|
131
|
-
gap: 0.5rem;
|
|
132
|
-
padding: 0.35rem 0.5rem;
|
|
133
|
-
border-radius: 8px;
|
|
134
|
-
border: none;
|
|
135
|
-
background: transparent;
|
|
136
|
-
color: var(--text);
|
|
137
|
-
font-family: var(--font-mono);
|
|
138
|
-
font-size: 0.9rem;
|
|
139
|
-
cursor: pointer;
|
|
140
|
-
transition: background 120ms ease, color 120ms ease;
|
|
141
|
-
text-align: left;
|
|
142
|
-
}
|
|
143
|
-
.archive-breadcrumb__option:hover,
|
|
144
|
-
.archive-breadcrumb__option:focus-visible {
|
|
145
|
-
background: hsl(from var(--surface1) h s l / 0.55);
|
|
146
|
-
color: var(--yellow);
|
|
147
|
-
outline: none;
|
|
148
|
-
}
|
|
149
|
-
.archive-breadcrumb__option[aria-selected="true"] {
|
|
150
|
-
background: hsl(from var(--surface1) h s l / 0.75);
|
|
151
|
-
color: var(--mauve);
|
|
152
|
-
}
|
|
153
|
-
@media (max-width: 480px) {
|
|
154
|
-
.archive-breadcrumb {
|
|
155
|
-
padding-left: 0.5em;
|
|
156
|
-
}
|
|
157
|
-
.archive-breadcrumb__menu {
|
|
158
|
-
min-width: 8rem;
|
|
159
|
-
max-width: calc(100vw - 2rem);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
span.year {
|
|
164
|
-
position: absolute;
|
|
165
|
-
top: 1.5rem;
|
|
166
|
-
right: 1.5rem;
|
|
167
|
-
z-index: 0;
|
|
168
|
-
font-weight: bolder;
|
|
169
|
-
font-family: var(--font-handwriting);
|
|
170
|
-
font-size: 4em;
|
|
171
|
-
font-style: italic;
|
|
172
|
-
color: hsl(from var(--accent, var(--lavender)) h s l / 0.3);
|
|
173
|
-
line-height: 1;
|
|
174
|
-
user-select: none;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
.winter {
|
|
178
|
-
--accent: var(--blue);
|
|
179
|
-
}
|
|
180
|
-
.autumn {
|
|
181
|
-
--accent: var(--red);
|
|
182
|
-
}
|
|
183
|
-
.summer {
|
|
184
|
-
--accent: var(--green);
|
|
185
|
-
}
|
|
186
|
-
.spring {
|
|
187
|
-
--accent: var(--peach);
|
|
188
|
-
}
|
|
189
|
-
.archive-item {
|
|
190
|
-
display: flex;
|
|
191
|
-
text-align: left;
|
|
192
|
-
align-items: flex-start;
|
|
193
|
-
}
|
|
194
|
-
.archive-item > div {
|
|
195
|
-
display: flex;
|
|
196
|
-
align-items: baseline; /* 时间和标题的文字基线对齐 */
|
|
197
|
-
gap: 0.75rem;
|
|
198
|
-
}
|
|
199
|
-
.archive-item + .archive-item {
|
|
200
|
-
border: none;
|
|
201
|
-
margin-top: 0;
|
|
202
|
-
padding-top: 1em;
|
|
203
|
-
}
|
|
204
|
-
`;
|
|
205
9
|
function getSeason(month) {
|
|
206
10
|
if (month >= 2 && month <= 4) return "Spring";
|
|
207
11
|
if (month >= 5 && month <= 7) return "Summer";
|
|
@@ -219,8 +23,8 @@ module.exports = class extends Component {
|
|
|
219
23
|
let title = `'${String(year).slice(-2)}`;
|
|
220
24
|
if (sectionTitle) {
|
|
221
25
|
title = sectionTitle;
|
|
222
|
-
} else if (month !== null &&
|
|
223
|
-
title = format(time
|
|
26
|
+
} else if (month !== null && isValidDate(time)) {
|
|
27
|
+
title = dateFormatters.longMonth.format(time);
|
|
224
28
|
}
|
|
225
29
|
|
|
226
30
|
return (
|
|
@@ -266,14 +70,14 @@ module.exports = class extends Component {
|
|
|
266
70
|
articleList = renderArticleList(page.posts, page.year, page.month, null, season);
|
|
267
71
|
}
|
|
268
72
|
|
|
269
|
-
const archiveDir =
|
|
73
|
+
const archiveDir = config?.archive_dir || "archives";
|
|
270
74
|
const archiveBasePath = url_for(`/${archiveDir}/`);
|
|
271
75
|
const currentYear = page.year ? Number(page.year) : null;
|
|
272
76
|
const currentMonth = page.month ? Number(page.month) : null;
|
|
273
77
|
|
|
274
78
|
const yearToMonths = new Map();
|
|
275
|
-
const allPosts = site
|
|
276
|
-
if (allPosts
|
|
79
|
+
const allPosts = site?.posts ? site.posts.sort("date", -1) : page.posts;
|
|
80
|
+
if (allPosts?.each) {
|
|
277
81
|
allPosts.each((p) => {
|
|
278
82
|
const y = p.date.year();
|
|
279
83
|
const m = p.date.month() + 1;
|
|
@@ -290,8 +94,8 @@ module.exports = class extends Component {
|
|
|
290
94
|
|
|
291
95
|
return (
|
|
292
96
|
<Fragment>
|
|
293
|
-
<script data-swup-
|
|
294
|
-
<
|
|
97
|
+
<script data-swup-reload-script defer src="/js/archive-breadcrumb.js"></script>
|
|
98
|
+
<link rel="stylesheet" href="/css/archive.css" />
|
|
295
99
|
<nav class="archive-breadcrumb" aria-label="archive breadcrumb" data-archive-breadcrumb data-archive-dir={archiveDir}>
|
|
296
100
|
<span class="prompt">$</span>{" "}
|
|
297
101
|
<span class="archive-breadcrumb__cmd" style="color: var(--blue)">
|
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
const { Component,
|
|
1
|
+
const { Component, cacheComponent } = require("../../include/util/common");
|
|
2
2
|
|
|
3
3
|
class Twikoo extends Component {
|
|
4
4
|
render() {
|
|
5
5
|
const { envId, region, lang, jsUrl } = this.props;
|
|
6
|
-
|
|
7
|
-
const lazy_load_css_script = lazy_load_css("/css/twikoo.css");
|
|
8
|
-
return (
|
|
9
|
-
<Fragment>
|
|
10
|
-
<div id="tko" class="content twikoo"></div>
|
|
11
|
-
<script dangerouslySetInnerHTML={{ __html: lazy_load_css_script }}></script>
|
|
12
|
-
<script dangerouslySetInnerHTML={{ __html: configJs }}></script>
|
|
13
|
-
<script defer src={jsUrl}></script>
|
|
14
|
-
</Fragment>
|
|
15
|
-
);
|
|
6
|
+
return <div id="tko" class="content twikoo" data-env-id={envId} data-region={JSON.stringify(region)} data-lang={JSON.stringify(lang)} data-js-url={jsUrl} data-css-url="/css/twikoo.css"></div>;
|
|
16
7
|
}
|
|
17
8
|
}
|
|
18
9
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { Component, Fragment } = require("../../include/util/common");
|
|
1
|
+
const { Component, Fragment, dateFormatters } = require("../../include/util/common");
|
|
4
2
|
const Comment = require("./comment");
|
|
5
3
|
const ArticleLicensing = require("../misc/article_licensing");
|
|
6
4
|
const ArticleCover = require("./article_cover");
|
|
@@ -36,28 +34,20 @@ module.exports = class extends Component {
|
|
|
36
34
|
{/* Cover image */}
|
|
37
35
|
{cover ? <ArticleCover page={page} cover={cover} index={index} helper={helper} /> : null}
|
|
38
36
|
<article class={`card-content article${"direction" in page ? ` ${page.direction}` : ""}`}>
|
|
39
|
-
{/* Title */}
|
|
40
|
-
{page.title !== "" && index ? (
|
|
41
|
-
<h2 class="article-title">
|
|
42
|
-
<a href={url_for(page.link || page.path)}>{page.title}</a>
|
|
43
|
-
</h2>
|
|
44
|
-
) : null}
|
|
45
|
-
{page.title !== "" && !index ? <h1 class="article-title">{page.title}</h1> : null}
|
|
46
|
-
|
|
47
37
|
{/* Metadata - Medium style */}
|
|
48
38
|
{page.layout !== "page" ? (
|
|
49
39
|
<div class="article-header-meta">
|
|
50
40
|
<div class="article-meta-info">
|
|
51
41
|
{page.date && (
|
|
52
42
|
<time class="article-date" datetime={page.date.toISOString()}>
|
|
53
|
-
{format(page.date
|
|
43
|
+
{dateFormatters.shortDay.format(page.date)}
|
|
54
44
|
</time>
|
|
55
45
|
)}
|
|
56
|
-
{page.date && (wordCount > 0 || !index) && <span class="meta-separator"
|
|
46
|
+
{page.date && (wordCount > 0 || !index) && <span class="meta-separator">·</span>}
|
|
57
47
|
{wordCount > 0 && <span class="article-reading-time">{readTime} min</span>}
|
|
58
48
|
{!index && (
|
|
59
49
|
<Fragment>
|
|
60
|
-
<span class="meta-separator"
|
|
50
|
+
<span class="meta-separator">·</span>
|
|
61
51
|
<span
|
|
62
52
|
class="article-visit-count"
|
|
63
53
|
data-flag-title={page.title}
|
|
@@ -68,27 +58,50 @@ module.exports = class extends Component {
|
|
|
68
58
|
</Fragment>
|
|
69
59
|
)}
|
|
70
60
|
</div>
|
|
71
|
-
{page.tags?.length ? (
|
|
72
|
-
<div class="article-tags-inline">
|
|
73
|
-
{page.tags.map((tag) => (
|
|
74
|
-
<Fragment>
|
|
75
|
-
<a class="article-tag" rel="tag" href={url_for(tag.path)}>
|
|
76
|
-
{tag.name}
|
|
77
|
-
</a>
|
|
78
|
-
</Fragment>
|
|
79
|
-
))}
|
|
80
|
-
</div>
|
|
81
|
-
) : null}
|
|
82
61
|
</div>
|
|
83
62
|
) : null}
|
|
84
63
|
|
|
85
|
-
{/*
|
|
86
|
-
|
|
87
|
-
class="
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
64
|
+
{/* Title */}
|
|
65
|
+
{page.title !== "" && index ? (
|
|
66
|
+
<h2 class="article-title">
|
|
67
|
+
<a href={url_for(page.link || page.path)}>{page.title}</a>
|
|
68
|
+
</h2>
|
|
69
|
+
) : null}
|
|
70
|
+
{page.title !== "" && !index ? <h1 class="article-title">{page.title}</h1> : null}
|
|
71
|
+
|
|
72
|
+
{!index && page.excerpt && <div class="content article-excerpt" dangerouslySetInnerHTML={{ __html: page.excerpt }}></div>}
|
|
73
|
+
|
|
74
|
+
{(index || !page.excerpt) && (
|
|
75
|
+
<div
|
|
76
|
+
class={index && page.excerpt ? "content article-excerpt" : "content"}
|
|
77
|
+
dangerouslySetInnerHTML={{
|
|
78
|
+
__html: index && page.excerpt ? page.excerpt : page.content,
|
|
79
|
+
}}
|
|
80
|
+
></div>
|
|
81
|
+
)}
|
|
82
|
+
|
|
83
|
+
{page.tags?.length && (
|
|
84
|
+
<div class="article-footer">
|
|
85
|
+
<div class="article-tags">
|
|
86
|
+
{page.tags.map((tag, i) => (
|
|
87
|
+
<Fragment>
|
|
88
|
+
{i > 0 && <span class="meta-separator">·</span>}
|
|
89
|
+
<a class="article-tag" rel="tag" href={url_for(tag.path)}>
|
|
90
|
+
{tag.name}
|
|
91
|
+
</a>
|
|
92
|
+
</Fragment>
|
|
93
|
+
))}
|
|
94
|
+
</div>
|
|
95
|
+
{index && (
|
|
96
|
+
<a class="article-read-more" href={url_for(page.link || page.path)}>
|
|
97
|
+
Read More →
|
|
98
|
+
</a>
|
|
99
|
+
)}
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
{!index && page.excerpt && <div class="content" dangerouslySetInnerHTML={{ __html: page.content }}></div>}
|
|
104
|
+
|
|
92
105
|
{/* Licensing block */}
|
|
93
106
|
{!index && article && article.licenses && Object.keys(article.licenses) ? <ArticleLicensing.Cacheable page={page} config={config} helper={helper} /> : null}
|
|
94
107
|
</article>
|
|
@@ -11,7 +11,17 @@ module.exports = class extends Component {
|
|
|
11
11
|
return (
|
|
12
12
|
<a href={url_for(page.link || page.path)} class="cover-image">
|
|
13
13
|
<img class="cover-lqip" src={lqip_src} alt="placeholder" />
|
|
14
|
-
<img
|
|
14
|
+
<img
|
|
15
|
+
class="cover-origin"
|
|
16
|
+
src={cover}
|
|
17
|
+
alt={page.title || cover}
|
|
18
|
+
srcset={imageSrcset}
|
|
19
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 100vw, 960px"
|
|
20
|
+
referrerpolicy="no-referrer"
|
|
21
|
+
decoding="async"
|
|
22
|
+
loading={index ? "lazy" : "eager"}
|
|
23
|
+
fetchpriority={index ? undefined : "high"}
|
|
24
|
+
/>
|
|
15
25
|
</a>
|
|
16
26
|
);
|
|
17
27
|
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Article media component, used in article lists such as archive page and recent posts widget
|
|
3
3
|
*/
|
|
4
|
-
const { Component } = require("
|
|
5
|
-
const { format, parseISO } = require("date-fns");
|
|
4
|
+
const { Component, dateFormatters, parseISO } = require("../../include/util/common");
|
|
6
5
|
|
|
7
6
|
module.exports = class extends Component {
|
|
8
7
|
render() {
|
|
9
8
|
const { url, title, date } = this.props;
|
|
10
|
-
|
|
11
|
-
const formattedDate = format(parseISO(date), "MMM dd");
|
|
9
|
+
const formattedDate = dateFormatters.shortDay.format(parseISO(date));
|
|
12
10
|
|
|
13
11
|
return (
|
|
14
12
|
<article class="archive-item">
|
package/layout/common/footer.jsx
CHANGED
|
@@ -25,10 +25,10 @@ class Footer extends Component {
|
|
|
25
25
|
<p class="footer-meta">
|
|
26
26
|
<span
|
|
27
27
|
dangerouslySetInnerHTML={{
|
|
28
|
-
__html: `© ${siteYear}
|
|
28
|
+
__html: `© 2022 - ${siteYear}`,
|
|
29
29
|
}}
|
|
30
30
|
></span>
|
|
31
|
-
Powered by Hexo
|
|
31
|
+
Powered by Hexo
|
|
32
32
|
{showVisitorCounter ? (
|
|
33
33
|
<>
|
|
34
34
|
<br />
|
|
@@ -72,7 +72,7 @@ class Footer extends Component {
|
|
|
72
72
|
? Object.keys(subdomains).map((name) => {
|
|
73
73
|
const link = subdomains[name];
|
|
74
74
|
return (
|
|
75
|
-
<a class="footer-link" target="
|
|
75
|
+
<a class="footer-link" target="_self" rel="noopener" title={name} href={link.url}>
|
|
76
76
|
{name}
|
|
77
77
|
</a>
|
|
78
78
|
);
|
|
@@ -83,17 +83,13 @@ class Footer extends Component {
|
|
|
83
83
|
);
|
|
84
84
|
|
|
85
85
|
return (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
{footer_social}
|
|
94
|
-
</div>
|
|
95
|
-
</footer>
|
|
96
|
-
</>
|
|
86
|
+
<footer class="footer">
|
|
87
|
+
<div class="footer-grid">
|
|
88
|
+
{footer_brand}
|
|
89
|
+
{footer_subdomains}
|
|
90
|
+
{footer_social}
|
|
91
|
+
</div>
|
|
92
|
+
</footer>
|
|
97
93
|
);
|
|
98
94
|
}
|
|
99
95
|
}
|
package/layout/common/head.jsx
CHANGED
|
@@ -28,7 +28,7 @@ module.exports = class extends Component {
|
|
|
28
28
|
const { site, config, helper, page } = this.props;
|
|
29
29
|
const { url_for, is_post } = helper;
|
|
30
30
|
const { url, head = {}, article } = config;
|
|
31
|
-
const { meta = [], open_graph = {}, structured_data = {}, canonical_url = page.permalink,
|
|
31
|
+
const { meta = [], open_graph = {}, structured_data = {}, canonical_url = page.permalink, favicon } = head;
|
|
32
32
|
|
|
33
33
|
const noIndex = helper.is_archive() || helper.is_tag();
|
|
34
34
|
|
|
@@ -51,15 +51,7 @@ module.exports = class extends Component {
|
|
|
51
51
|
images.push(img[1]);
|
|
52
52
|
}
|
|
53
53
|
} else {
|
|
54
|
-
images = [url_for("/img/og_image.
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
let adsenseClientId = null;
|
|
58
|
-
if (Array.isArray(config.widgets)) {
|
|
59
|
-
const widget = config.widgets.find((widget) => widget.type === "adsense");
|
|
60
|
-
if (widget) {
|
|
61
|
-
adsenseClientId = widget.client_id;
|
|
62
|
-
}
|
|
54
|
+
images = [url_for("/img/og_image.webp")];
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
let openGraphImages = images;
|
|
@@ -100,7 +92,7 @@ module.exports = class extends Component {
|
|
|
100
92
|
|
|
101
93
|
return (
|
|
102
94
|
<head>
|
|
103
|
-
<script
|
|
95
|
+
<script dangerouslySetInnerHTML={{ __html: themeInitScript }}></script>
|
|
104
96
|
<meta charset="utf-8" />
|
|
105
97
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
106
98
|
{noIndex ? <meta name="robots" content="noindex" /> : null}
|
|
@@ -141,7 +133,6 @@ module.exports = class extends Component {
|
|
|
141
133
|
/>
|
|
142
134
|
) : null}
|
|
143
135
|
{canonical_url ? <link rel="canonical" href={canonical_url} /> : null}
|
|
144
|
-
{rss ? <link rel="alternate" href={url_for(rss)} title={config.title} type="application/atom+xml" /> : null}
|
|
145
136
|
{favicon ? <link rel="icon" href={url_for(favicon)} /> : null}
|
|
146
137
|
<link rel="stylesheet" href={url_for("/css/default.css")} />
|
|
147
138
|
<link rel="stylesheet" href={url_for("/css/responsive/mobile.css")} media="screen and (max-width:768px)" />
|
|
@@ -149,12 +140,13 @@ module.exports = class extends Component {
|
|
|
149
140
|
<link rel="stylesheet" href={url_for("/css/responsive/touch.css")} media="screen and (max-width:1023px)" />
|
|
150
141
|
<link rel="stylesheet" href={url_for("/css/responsive/desktop.css")} media="screen and (min-width:1024px)" />
|
|
151
142
|
<link rel="preload" as="style" href={url_for("/css/callout_blocks.css")} onload="this.onload=null;this.rel='stylesheet'" />
|
|
152
|
-
{
|
|
143
|
+
<link rel="preload" href={url_for("/css/font/woff2/HomemadeApple.woff2")} as="font" type="font/woff2" crossorigin />
|
|
153
144
|
<link rel="preconnect" href="https://fontsapi.zeoseven.com" />
|
|
145
|
+
<link rel="preload" as="style" href="https://fontsapi.zeoseven.com/285/main/result.css" onload="this.onload=null;this.rel='stylesheet'" />
|
|
154
146
|
<link rel="preload" as="style" href="https://fontsapi.zeoseven.com/442/main/result.css" onload="this.onload=null;this.rel='stylesheet'" />
|
|
155
|
-
<link rel="
|
|
147
|
+
<link rel="preload" as="style" href="/css/shiki/shiki.css" onload="this.onload=null;this.rel='stylesheet'" />
|
|
148
|
+
{page.encrypt ? <link rel="stylesheet" href={url_for("/css/encrypt.css")} /> : null}
|
|
156
149
|
<Plugins site={site} config={config} helper={helper} page={page} head={true} />
|
|
157
|
-
{adsenseClientId ? <script data-swup-ignore-script data-ad-client={adsenseClientId} src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async></script> : null}
|
|
158
150
|
</head>
|
|
159
151
|
);
|
|
160
152
|
}
|
package/layout/common/navbar.jsx
CHANGED
|
@@ -36,22 +36,7 @@ class Navbar extends Component {
|
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
38
|
<nav class="navbar navbar-main">
|
|
39
|
-
<div
|
|
40
|
-
class="navbar-container"
|
|
41
|
-
onclick="
|
|
42
|
-
const burger = this.querySelector('.navbar-burger');
|
|
43
|
-
const menu = this.querySelector('.navbar-menu');
|
|
44
|
-
const target = event.target;
|
|
45
|
-
|
|
46
|
-
if (target.closest('.navbar-burger')) {
|
|
47
|
-
burger.classList.toggle('is-active');
|
|
48
|
-
menu.classList.toggle('is-active');
|
|
49
|
-
} else if (target.closest('.navbar-item')) { // 点击菜单项:自动关闭菜单
|
|
50
|
-
burger.classList.remove('is-active');
|
|
51
|
-
menu.classList.remove('is-active');
|
|
52
|
-
}
|
|
53
|
-
"
|
|
54
|
-
>
|
|
39
|
+
<div class="navbar-container" onclick="toggleNav(event)">
|
|
55
40
|
<a href={siteUrl} style={"font-family: homemade-apple; color: var(--text); display: flex; align-items: center; padding: 0 1em;"}>
|
|
56
41
|
GnixAij
|
|
57
42
|
</a>
|
|
@@ -82,7 +67,7 @@ class Navbar extends Component {
|
|
|
82
67
|
})}
|
|
83
68
|
</Fragment>
|
|
84
69
|
) : null}
|
|
85
|
-
<button type="button" class="navbar-item"
|
|
70
|
+
<button type="button" class="navbar-item" title="Choose Theme" popovertarget="theme-selector-popover">
|
|
86
71
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
87
72
|
<title>brightness_fill</title>
|
|
88
73
|
<g id="brightness_fill" fill="currentColor">
|
|
@@ -90,7 +75,7 @@ class Navbar extends Component {
|
|
|
90
75
|
</g>
|
|
91
76
|
</svg>
|
|
92
77
|
</button>
|
|
93
|
-
<button type="button" class="navbar-item search" title={searchTitle}>
|
|
78
|
+
<button type="button" class="navbar-item search" popovertarget="searchbox" title={searchTitle}>
|
|
94
79
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
95
80
|
<title>search_line</title>
|
|
96
81
|
<g id="search_line" fill="currentColor">
|
|
@@ -10,11 +10,12 @@ module.exports = class extends Component {
|
|
|
10
10
|
<Fragment>
|
|
11
11
|
<Plugins site={site} config={config} page={page} helper={helper} head={false} />
|
|
12
12
|
<Swup head={false} />
|
|
13
|
-
<script
|
|
14
|
-
<script
|
|
15
|
-
<script
|
|
16
|
-
<script
|
|
17
|
-
<script
|
|
13
|
+
<script defer src="/js/host/iconify-icon/3.0.2/iconify-icon.min.js"></script>
|
|
14
|
+
<script defer src="/js/theme-selector.js"></script>
|
|
15
|
+
<script defer src="/js/host/medium-zoom/dist/medium-zoom.min.js"></script>
|
|
16
|
+
<script defer src="/js/main.js"></script>
|
|
17
|
+
{page.encrypt ? <script src="/js/decrypt.js" type="module"></script> : null}
|
|
18
|
+
<script async src="/js/instant-page.min.js" type="module"></script>
|
|
18
19
|
</Fragment>
|
|
19
20
|
);
|
|
20
21
|
}
|
|
@@ -13,13 +13,12 @@ const themes = [
|
|
|
13
13
|
class ThemeSelector extends Component {
|
|
14
14
|
render() {
|
|
15
15
|
return (
|
|
16
|
-
<div id="theme-selector-
|
|
17
|
-
<div class="theme-selector-
|
|
18
|
-
<div class="theme-selector-list">
|
|
16
|
+
<div id="theme-selector-popover" popover="auto" tabindex="-1">
|
|
17
|
+
<div class="theme-selector-list" role="listbox" aria-label="Select theme">
|
|
19
18
|
{themes.map((theme, index) => (
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
</
|
|
19
|
+
<button class="theme-option" type="submit" data-theme-option={theme.value} data-index={index} onclick={`window.selectThemeOption?.(${index})`}>
|
|
20
|
+
{theme.name}
|
|
21
|
+
</button>
|
|
23
22
|
))}
|
|
24
23
|
</div>
|
|
25
24
|
</div>
|
package/layout/common/toc.jsx
CHANGED
|
@@ -8,25 +8,19 @@ class FloatingToc extends Component {
|
|
|
8
8
|
list_number: false,
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
if (!tocContent) {
|
|
11
|
+
if (!tocContent && !page.encrypt) {
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
|
-
<div class="toc-container" id="icarus-toc-container">
|
|
17
|
-
<button class="toc-button" type="button"
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<line x1="8" y1="12" x2="21" y2="12"></line>
|
|
22
|
-
<line x1="8" y1="18" x2="21" y2="18"></line>
|
|
23
|
-
<line x1="3" y1="6" x2="3.01" y2="6"></line>
|
|
24
|
-
<line x1="3" y1="12" x2="3.01" y2="12"></line>
|
|
25
|
-
<line x1="3" y1="18" x2="3.01" y2="18"></line>
|
|
26
|
-
</svg>
|
|
16
|
+
<div class="toc-container" id="icarus-toc-container" style={page.encrypt ? "display:none" : null}>
|
|
17
|
+
<button class="toc-button" type="button" popovertarget="toc-body" aria-label="Table of Contents">
|
|
18
|
+
<span aria-hidden="true"></span>
|
|
19
|
+
<span aria-hidden="true"></span>
|
|
20
|
+
<span aria-hidden="true"></span>
|
|
27
21
|
</button>
|
|
28
|
-
<div class="toc-body" onclick="if(event.target
|
|
29
|
-
<div dangerouslySetInnerHTML={{ __html: tocContent }} />
|
|
22
|
+
<div id="toc-body" popover="auto" class="toc-body" onclick="if(event.target===this||event.target.closest('.toc-link'))this.hidePopover();">
|
|
23
|
+
<div id="toc-insert" dangerouslySetInnerHTML={{ __html: tocContent || "" }} />
|
|
30
24
|
</div>
|
|
31
25
|
</div>
|
|
32
26
|
);
|