hexo-theme-gnix 6.2.0 → 8.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.
Files changed (59) hide show
  1. package/README.md +6 -2
  2. package/include/hexo/encrypt.js +42 -0
  3. package/include/hexo/feed.js +329 -0
  4. package/include/util/common.js +7 -9
  5. package/languages/en.yml +6 -3
  6. package/languages/zh-CN.yml +6 -3
  7. package/layout/archive.jsx +86 -65
  8. package/layout/comment/twikoo.jsx +2 -11
  9. package/layout/comment/waline.jsx +2 -2
  10. package/layout/common/article.jsx +5 -8
  11. package/layout/common/article_cover.jsx +11 -1
  12. package/layout/common/article_media.jsx +2 -4
  13. package/layout/common/footer.jsx +11 -31
  14. package/layout/common/head.jsx +6 -14
  15. package/layout/common/navbar.jsx +4 -4
  16. package/layout/common/scripts.jsx +6 -6
  17. package/layout/common/theme_selector.jsx +5 -6
  18. package/layout/common/toc.jsx +8 -14
  19. package/layout/index.jsx +2 -4
  20. package/layout/misc/article_licensing.jsx +4 -2
  21. package/layout/misc/open_graph.jsx +4 -4
  22. package/layout/misc/paginator.jsx +10 -4
  23. package/layout/misc/structured_data.jsx +3 -4
  24. package/layout/plugin/busuanzi.jsx +1 -1
  25. package/layout/plugin/cookie_consent.jsx +40 -31
  26. package/layout/plugin/swup.jsx +2 -22
  27. package/layout/search/insight.jsx +16 -3
  28. package/package.json +12 -8
  29. package/scripts/hot-reload.js +92 -0
  30. package/scripts/index.js +2 -0
  31. package/source/css/archive.css +251 -0
  32. package/source/css/default.css +250 -284
  33. package/source/css/encrypt.css +55 -0
  34. package/source/css/responsive/desktop.css +0 -119
  35. package/source/css/responsive/mobile.css +7 -23
  36. package/source/css/responsive/touch.css +9 -103
  37. package/source/css/shiki/shiki.css +7 -22
  38. package/source/css/twikoo.css +290 -830
  39. package/source/img/og_image.webp +0 -0
  40. package/source/js/archive-breadcrumb.js +132 -0
  41. package/source/js/busuanzi.js +1 -12
  42. package/source/js/components/accordion.js +192 -0
  43. package/source/js/components/chat.js +239 -0
  44. package/source/js/components/device-carousel.js +260 -0
  45. package/source/js/components/image-carousel.js +410 -0
  46. package/source/js/components/text-image-section.js +180 -0
  47. package/source/js/components/theme-stacked.js +526 -0
  48. package/source/js/components/tree.js +437 -0
  49. package/source/js/decrypt.js +112 -0
  50. package/source/js/insight.js +75 -65
  51. package/source/js/main.js +192 -99
  52. package/source/js/mdit/mermaid.js +12 -4
  53. package/source/js/swup.bundle.js +1 -0
  54. package/source/js/theme-selector.js +94 -113
  55. package/source/img/og_image.png +0 -0
  56. package/source/js/host/swup/Swup.umd.min.js +0 -1
  57. package/source/js/host/swup/head-plugin.umd.min.js +0 -1
  58. package/source/js/host/swup/scripts-plugin.umd.min.js +0 -2
  59. package/source/js/mdit/shiki.js +0 -158
@@ -0,0 +1,92 @@
1
+ const LIVE_RELOAD_PATH = "/__hexo_live_reload";
2
+ const clients = new Set();
3
+ const reloadDebounceMs = 150;
4
+ const reloadCooldownMs = 500;
5
+
6
+ function isHexoServerCommand(ctx) {
7
+ const command = ctx.env?.cmd;
8
+ const aliases = ctx.extend?.console?.alias ?? {};
9
+
10
+ return command === "server" || aliases[command] === "server";
11
+ }
12
+
13
+ function broadcastReload() {
14
+ const payload = `data: ${JSON.stringify({ type: "reload", at: Date.now() })}\n\n`;
15
+
16
+ for (const client of clients) {
17
+ client.write(payload);
18
+ }
19
+ }
20
+
21
+ if (isHexoServerCommand(hexo)) {
22
+ let reloadTimer = null;
23
+ let lastBroadcastAt = 0;
24
+
25
+ function scheduleReload() {
26
+ if (reloadTimer) {
27
+ clearTimeout(reloadTimer);
28
+ }
29
+
30
+ reloadTimer = setTimeout(() => {
31
+ reloadTimer = null;
32
+
33
+ const now = Date.now();
34
+ if (now - lastBroadcastAt < reloadCooldownMs) {
35
+ return;
36
+ }
37
+
38
+ lastBroadcastAt = now;
39
+ broadcastReload();
40
+ }, reloadDebounceMs);
41
+ }
42
+
43
+ hexo.on("generateAfter", () => {
44
+ scheduleReload();
45
+ });
46
+
47
+ hexo.extend.filter.register("server_middleware", (app) => {
48
+ app.use((req, res, next) => {
49
+ if (req.url !== LIVE_RELOAD_PATH) {
50
+ next();
51
+ return;
52
+ }
53
+
54
+ res.writeHead(200, {
55
+ "Cache-Control": "no-cache, no-transform",
56
+ Connection: "keep-alive",
57
+ "Content-Type": "text/event-stream",
58
+ "X-Accel-Buffering": "no",
59
+ });
60
+
61
+ res.write("retry: 1000\n\n");
62
+ clients.add(res);
63
+
64
+ req.on("close", () => {
65
+ clients.delete(res);
66
+ res.end();
67
+ });
68
+ });
69
+ });
70
+
71
+ hexo.extend.injector.register(
72
+ "body_end",
73
+ `
74
+ <script>
75
+ (() => {
76
+ if (!window.EventSource) return;
77
+
78
+ const source = new EventSource('${LIVE_RELOAD_PATH}');
79
+ source.addEventListener('message', (event) => {
80
+ try {
81
+ const data = JSON.parse(event.data);
82
+ if (data.type === 'reload') {
83
+ window.location.reload();
84
+ }
85
+ } catch (_) {
86
+ window.location.reload();
87
+ }
88
+ });
89
+ })();
90
+ </script>`,
91
+ );
92
+ }
package/scripts/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  require("../include/hexo/filter")(hexo);
2
2
  require("../include/hexo/generator")(hexo);
3
+ require("../include/hexo/feed")(hexo);
4
+ require("../include/hexo/encrypt")(hexo);
3
5
  require("../include/hexo/view").init(hexo);
4
6
  require("../include/hexo/helper")(hexo);
5
7
  require("../include/hexo/renderer")(hexo);
@@ -0,0 +1,251 @@
1
+ @keyframes blink {
2
+ 0%,
3
+ 100% {
4
+ opacity: 1;
5
+ }
6
+ 50% {
7
+ opacity: 0;
8
+ }
9
+ }
10
+
11
+ .article-meta {
12
+ font-size: 0.8rem;
13
+ color: var(--subtext1);
14
+ font-family: var(--font-handwriting);
15
+ white-space: nowrap;
16
+ }
17
+
18
+ a.archive-title {
19
+ font-family: var(--font-sans-serif);
20
+ font-weight: 400;
21
+ color: var(--text);
22
+ }
23
+
24
+ a.archive-title:hover {
25
+ color: var(--accent);
26
+ }
27
+
28
+ /* Breadcrumb navigation */
29
+ .archive-breadcrumb {
30
+ color: var(--blue);
31
+ font-family: var(--font-mono);
32
+ margin: 0 0 1rem 0;
33
+ padding-left: 1em;
34
+ display: flex;
35
+ flex-wrap: wrap;
36
+ align-items: center;
37
+ gap: 0;
38
+ }
39
+
40
+ .archive-breadcrumb .prompt {
41
+ color: var(--green);
42
+ user-select: none;
43
+ margin-right: 0.25em;
44
+ }
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
+
55
+ .archive-breadcrumb__cmd {
56
+ color: var(--yellow);
57
+ user-select: none;
58
+ padding-right: 0.5em;
59
+ }
60
+
61
+ .archive-breadcrumb__picker {
62
+ position: relative;
63
+ display: inline-flex;
64
+ align-items: center;
65
+ }
66
+
67
+ .archive-breadcrumb__trigger {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ border: none;
71
+ background: transparent;
72
+ color: var(--yellow);
73
+ font-family: var(--font-mono);
74
+ padding: 0.05em 0.15em;
75
+ border-radius: 4px;
76
+ text-decoration: underline;
77
+ text-decoration-color: hsl(from var(--yellow) h s l / 0.6);
78
+ text-decoration-thickness: 1px;
79
+ text-underline-offset: 0.22em;
80
+ cursor: pointer;
81
+ transition:
82
+ transform 120ms ease,
83
+ color 120ms ease,
84
+ background 120ms ease,
85
+ text-decoration-color 120ms ease;
86
+ }
87
+
88
+ .archive-breadcrumb__trigger:hover {
89
+ color: var(--mauve);
90
+ background: hsl(from var(--base) h s l / 0.35);
91
+ text-decoration-color: hsl(from var(--mauve) h s l / 0.75);
92
+ }
93
+
94
+ .archive-breadcrumb__trigger:focus-visible {
95
+ outline: 2px solid hsl(from var(--mauve) h s l / 0.7);
96
+ outline-offset: 2px;
97
+ background: hsl(from var(--base) h s l / 0.35);
98
+ }
99
+
100
+ .archive-breadcrumb__trigger[aria-expanded="true"] {
101
+ transform: translateY(-1px);
102
+ color: var(--mauve);
103
+ text-decoration-color: hsl(from var(--mauve) h s l / 0.9);
104
+ }
105
+
106
+ .archive-breadcrumb__trigger[disabled] {
107
+ opacity: 0.45;
108
+ cursor: not-allowed;
109
+ text-decoration-color: hsl(from var(--subtext1) h s l / 0.4);
110
+ }
111
+
112
+ .archive-breadcrumb__menu {
113
+ position: absolute;
114
+ top: calc(100% + 6px);
115
+ left: 0;
116
+ min-width: 12rem;
117
+ max-height: 15rem;
118
+ overflow: auto;
119
+ background: hsl(from var(--base) h s l / 0.9);
120
+ border: 1px solid hsl(from var(--surface1) h s l / 0.9);
121
+ border-radius: 10px;
122
+ padding: 0.35rem;
123
+ box-shadow: 0 18px 50px hsl(from var(--crust) h s l / 0.45);
124
+ opacity: 0;
125
+ transform: translateY(-6px);
126
+ visibility: hidden;
127
+ pointer-events: none;
128
+ transition:
129
+ opacity 160ms ease,
130
+ transform 160ms ease,
131
+ visibility 0s linear 160ms;
132
+ z-index: 20;
133
+ }
134
+
135
+ .archive-breadcrumb__trigger[aria-expanded="true"] + .archive-breadcrumb__menu {
136
+ opacity: 1;
137
+ transform: translateY(0);
138
+ visibility: visible;
139
+ pointer-events: auto;
140
+ transition:
141
+ opacity 160ms ease,
142
+ transform 160ms ease,
143
+ visibility 0s;
144
+ }
145
+
146
+ .archive-breadcrumb__option {
147
+ width: 100%;
148
+ display: flex;
149
+ justify-content: space-between;
150
+ align-items: center;
151
+ gap: 0.5rem;
152
+ padding: 0.35rem 0.5rem;
153
+ border-radius: 8px;
154
+ border: none;
155
+ background: transparent;
156
+ color: var(--text);
157
+ font-family: var(--font-mono);
158
+ font-size: 0.9rem;
159
+ cursor: pointer;
160
+ transition:
161
+ background 120ms ease,
162
+ color 120ms ease;
163
+ text-align: left;
164
+ }
165
+
166
+ .archive-breadcrumb__option:hover,
167
+ .archive-breadcrumb__option:focus-visible {
168
+ background: hsl(from var(--surface1) h s l / 0.55);
169
+ color: var(--yellow);
170
+ outline: none;
171
+ }
172
+
173
+ .archive-breadcrumb__option[aria-selected="true"] {
174
+ background: hsl(from var(--surface1) h s l / 0.75);
175
+ color: var(--mauve);
176
+ }
177
+
178
+ /* Card with year overlay */
179
+ .card-content {
180
+ position: relative;
181
+ overflow: hidden;
182
+ }
183
+
184
+ span.year {
185
+ position: absolute;
186
+ top: 1.5rem;
187
+ right: 1.5rem;
188
+ z-index: 0;
189
+ pointer-events: none;
190
+ font-weight: bolder;
191
+ font-family: var(--font-handwriting);
192
+ font-size: 4em;
193
+ font-style: italic;
194
+ color: hsl(from var(--accent, var(--lavender)) h s l / 0.3);
195
+ line-height: 1;
196
+ user-select: none;
197
+ }
198
+
199
+ /* Season colors */
200
+ .winter {
201
+ --accent: var(--blue);
202
+ }
203
+
204
+ .autumn {
205
+ --accent: var(--red);
206
+ }
207
+
208
+ .summer {
209
+ --accent: var(--green);
210
+ }
211
+
212
+ .spring {
213
+ --accent: var(--peach);
214
+ }
215
+
216
+ /* Archive item */
217
+ .archive-item {
218
+ position: relative;
219
+ display: flex;
220
+ text-align: left;
221
+ align-items: flex-start;
222
+ }
223
+
224
+ .archive-item > div {
225
+ display: flex;
226
+ align-items: baseline;
227
+ gap: 0.75rem;
228
+ }
229
+
230
+ .archive-item + .archive-item {
231
+ border: none;
232
+ margin-top: 0;
233
+ padding-top: 1em;
234
+ }
235
+
236
+ /* Responsive */
237
+ @media (max-width: 480px) {
238
+ .archive-breadcrumb {
239
+ padding-left: 0.5em;
240
+ }
241
+
242
+ .archive-breadcrumb__menu {
243
+ min-width: 8rem;
244
+ max-width: calc(100vw - 2rem);
245
+ }
246
+
247
+ span.year {
248
+ font-size: 2.5em;
249
+ right: 0.5rem;
250
+ }
251
+ }