@xingwangzhe/stalux 1.27.1 → 1.28.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 (37) hide show
  1. package/README.md +5 -5
  2. package/package.json +3 -2
  3. package/src/components/stalux/archives/archivesList.astro +34 -42
  4. package/src/components/stalux/categories/categoriesList.astro +4 -4
  5. package/src/components/stalux/common/textType.astro +1 -3
  6. package/src/components/stalux/footer/FooterBadges.astro +28 -24
  7. package/src/components/stalux/footer/FooterBeian.astro +22 -26
  8. package/src/components/stalux/footer/FooterStats.astro +28 -27
  9. package/src/components/stalux/footer/FooterThemeInfo.astro +24 -28
  10. package/src/components/stalux/layout/footer.astro +5 -14
  11. package/src/components/stalux/layout/head.astro +5 -9
  12. package/src/components/stalux/layout/navs.astro +16 -20
  13. package/src/components/stalux/links/linkList.astro +4 -4
  14. package/src/components/stalux/links/socialMedia.astro +34 -34
  15. package/src/components/stalux/posts/PostTaxonomy.astro +14 -14
  16. package/src/components/stalux/posts/WalineComment.astro +20 -464
  17. package/src/components/stalux/posts/postCC.astro +7 -7
  18. package/src/components/stalux/posts/postCard.astro +41 -41
  19. package/src/components/stalux/posts/postContent.astro +46 -41
  20. package/src/components/stalux/posts/postList.astro +4 -4
  21. package/src/components/stalux/posts/postNavigation.astro +107 -119
  22. package/src/components/stalux/posts/postToc.astro +20 -20
  23. package/src/components/stalux/tags/tagsCloud.astro +15 -15
  24. package/src/components/stalux/words/wordCard.astro +27 -32
  25. package/src/components/stalux/words/wordList.astro +18 -18
  26. package/src/index.ts +82 -34
  27. package/src/internal/font-slices.ts +151 -136
  28. package/src/layouts/PostLayout.astro +6 -6
  29. package/src/layouts/Stalux.astro +4 -8
  30. package/src/pages/about.astro +6 -6
  31. package/src/pages/categories/[category].astro +5 -1
  32. package/src/pages/posts/[post].astro +2 -2
  33. package/src/plugins/feature-flags.ts +60 -8
  34. package/src/scripts/waline.ts +32 -11
  35. package/src/styles/base/init.css +2 -1
  36. package/src/styles/base/math.css +1 -1
  37. package/src/styles/components/posts/waline.css +440 -0
@@ -46,18 +46,18 @@ const cfg = {
46
46
  <nav class={style.container} transition:name={cfg.containerName} aria-label={title ?? cfg.heading}>
47
47
  {items.length > 0 && <h3 class={style.title}>{title ?? cfg.heading}</h3>}
48
48
  {items.length > 0 ? (
49
- <div
50
- class={cfg.listClass}
51
- transition:name={cfg.contentName}
52
- transition:animate={fade({ duration: "0.3s" })}
53
- >
54
- {items.map((item) => (
55
- <a href={`${cfg.prefix}${item}/`} class={`${cfg.itemClass} a-none`} data-astro-prefetch>
56
- {item}
57
- </a>
58
- ))}
59
- </div>
60
- ) : (
61
- <div class={style.empty}>{cfg.empty}</div>
62
- )}
49
+ <div
50
+ class={cfg.listClass}
51
+ transition:name={cfg.contentName}
52
+ transition:animate={fade({ duration: "0.3s" })}
53
+ >
54
+ {items.map((item) => (
55
+ <a href={`${cfg.prefix}${item}/`} class={`${cfg.itemClass} a-none`} data-astro-prefetch>
56
+ {item}
57
+ </a>
58
+ ))}
59
+ </div>
60
+ ) : (
61
+ <div class={style.empty}>{cfg.empty}</div>
62
+ )}
63
63
  </nav>
@@ -1,5 +1,4 @@
1
1
  ---
2
- import "@waline/client/style";
3
2
  import { getCollection } from "astro:content";
4
3
  import { getSiteData } from "@utils/config-utils";
5
4
  import { createTranslator } from "@utils/i18n";
@@ -43,468 +42,25 @@ const walineConfig = {
43
42
  ---
44
43
 
45
44
  {walineConfig.serverURL && (
46
- <section
47
- id="waline-container"
48
- class="waline-comment-container"
49
- aria-label={t("comment.title")}
50
- data-waline-config={
51
- // base64 可逆混淆(非加密,仅避免 SSR 注入/转义问题)
52
- btoa(
53
- Array.from(new TextEncoder().encode(JSON.stringify(walineConfig)), (byte) =>
54
- String.fromCharCode(byte),
55
- ).join(""),
56
- )
57
- }
58
- >
59
- <h2 class="waline-comment-title">{t("comment.title")}</h2>
60
- <div id="waline-comment" class="waline-comment" data-nosnippet />
61
- <div class="comments-seo-notice" style="display:none">
62
- {t("comment.disclaimer")}
63
- </div>
64
- </section>
65
- )}
45
+ <section
46
+ id="waline-container"
47
+ class="waline-comment-container"
48
+ aria-label={t("comment.title")}
49
+ data-waline-config={
50
+ // base64 可逆混淆(非加密,仅避免 SSR 注入/转义问题)
51
+ btoa(
52
+ Array.from(new TextEncoder().encode(JSON.stringify(walineConfig)), (byte) =>
53
+ String.fromCharCode(byte),
54
+ ).join(""),
55
+ )
56
+ }
57
+ >
58
+ <h2 class="waline-comment-title">{t("comment.title")}</h2>
59
+ <div id="waline-comment" class="waline-comment" data-nosnippet />
60
+ <div class="comments-seo-notice" style="display:none">
61
+ {t("comment.disclaimer")}
62
+ </div>
63
+ </section>
64
+ )}
66
65
 
67
66
  <script src="../../../scripts/waline.ts"></script>
68
-
69
- <style is:global>
70
- :root {
71
- --waline-accent-rgb: 100, 255, 218;
72
- }
73
-
74
- /* 评论区容器与博客风格一致 */
75
- .waline-comment-container {
76
- margin-top: 3rem;
77
- margin-bottom: 1rem;
78
- padding: 2rem;
79
- border-radius: 12px;
80
- animation: fadeInUpComment 0.8s ease-in-out forwards;
81
- opacity: 0;
82
- animation-delay: 0.3s;
83
- }
84
-
85
- /* 评论区标题样式与博客风格一致 */
86
- .waline-comment-title {
87
- margin: 0 0 1.5rem 0;
88
- font-size: 2rem;
89
- text-align: center;
90
- background: linear-gradient(90deg, var(--white-90p), rgba(var(--waline-accent-rgb), 0.9));
91
- -webkit-background-clip: text;
92
- -webkit-text-fill-color: transparent;
93
- background-clip: text;
94
- }
95
-
96
- /* Waline根元素自定义 */
97
- .wl-panel {
98
- background-color: rgba(17, 17, 17, 0.3);
99
- border-radius: 12px;
100
- padding: 1rem;
101
- border: 1px solid rgba(255, 255, 255, 0.1);
102
- margin-bottom: 1.5rem;
103
- }
104
-
105
- /* 修改输入框样式 */
106
- .wl-editor,
107
- .wl-input {
108
- background-color: rgba(17, 17, 17, 0.5) !important;
109
- color: var(--white-90p) !important;
110
- border: 1px solid rgba(100, 100, 100, 0.3) !important;
111
- border-radius: 8px;
112
- transition: all 0.3s ease;
113
- }
114
-
115
- /* 输入框焦点状态 */
116
- .wl-editor:focus,
117
- .wl-input:focus {
118
- border-color: rgba(var(--waline-accent-rgb), 0.5) !important;
119
- box-shadow: 0 0 5px rgba(var(--waline-accent-rgb), 0.3) !important;
120
- outline: none;
121
- }
122
-
123
- /* 修复登录后头像向下偏移 — 全局 a::after 下划线动画撑高了 wl-login-nick */
124
- .wl-login-nick {
125
- display: block !important;
126
- height: var(--waline-avatar-size, 52px);
127
- overflow: hidden;
128
- }
129
- .wl-login-nick::after {
130
- display: none;
131
- }
132
-
133
- /* 修复 markdown 全局 img margin 误伤 Waline 头像 */
134
- .waline-comment-container img {
135
- margin: 0 !important;
136
- }
137
- .wl-btn {
138
- background: rgba(var(--waline-accent-rgb), 0.6) !important;
139
- color: var(--white-full) !important;
140
- border: none !important;
141
- border-radius: 6px;
142
- transition: all 0.2s ease;
143
- font-weight: 500;
144
- padding: 8px 15px;
145
- cursor: pointer;
146
- }
147
-
148
- .wl-btn:hover {
149
- background: rgba(var(--waline-accent-rgb), 0.7) !important;
150
- transform: none;
151
- box-shadow: none !important;
152
- }
153
-
154
- .wl-btn.primary {
155
- background: rgba(var(--waline-accent-rgb), 0.6) !important;
156
- }
157
-
158
- .wl-btn.primary:hover {
159
- background: rgba(var(--waline-accent-rgb), 0.7) !important;
160
- transform: none;
161
- box-shadow: none !important;
162
- }
163
-
164
- /* 标签文字颜色 */
165
- .wl-header label {
166
- color: var(--white-85p);
167
- font-weight: 500;
168
- }
169
-
170
- /* 评论卡片样式 */
171
- .wl-card {
172
- background-color: rgba(17, 17, 17, 0.3) !important;
173
- border-radius: 12px;
174
- padding: 1.2rem;
175
- margin-top: 1.2rem;
176
- border: 1px solid rgba(70, 70, 70, 0.2) !important;
177
- transition: all 0.3s ease;
178
- }
179
-
180
- .wl-card:hover {
181
- transform: translateY(-3px);
182
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
183
- border-color: rgba(var(--waline-accent-rgb), 0.3) !important;
184
- }
185
-
186
- /* 修改用户名样式 */
187
- .wl-nick {
188
- color: rgba(var(--waline-accent-rgb), 0.95) !important;
189
- font-weight: 600;
190
- transition: all 0.2s ease;
191
- }
192
-
193
- .wl-nick:hover {
194
- color: rgba(var(--waline-accent-rgb), 1) !important;
195
- }
196
-
197
- /* 评论内容样式 */
198
- .wl-content {
199
- color: var(--white-90p);
200
- line-height: 1.7;
201
- margin: 0.8rem 0;
202
- word-break: break-word;
203
- }
204
-
205
- /* 回复按钮样式 */
206
- .wl-reply {
207
- opacity: 0.8;
208
- transition: all 0.2s ease;
209
- }
210
-
211
- .wl-reply:hover {
212
- opacity: 1;
213
- text-decoration: none;
214
- }
215
-
216
- /* 表情面板样式 */
217
- .wl-emoji-popup,
218
- .wl-gif-popup {
219
- background-color: rgba(25, 25, 25, 0.95) !important;
220
- border: 1px solid rgba(70, 70, 70, 0.3) !important;
221
- border-radius: 10px;
222
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
223
- backdrop-filter: blur(10px);
224
- }
225
-
226
- /* 表情按钮样式 */
227
- .wl-emoji-popup button {
228
- border-radius: 6px;
229
- transition: all 0.2s ease;
230
- }
231
-
232
- .wl-emoji-popup button:hover {
233
- background-color: rgba(var(--waline-accent-rgb), 0.2);
234
- transform: scale(1.05);
235
- }
236
-
237
- /* 文章评价反应区域 */
238
- .wl-reaction {
239
- background-color: rgba(17, 17, 17, 0.3);
240
- border-radius: 12px;
241
- padding: 1rem;
242
- margin-bottom: 1.5rem;
243
- border: 1px solid rgba(70, 70, 70, 0.2);
244
- text-align: center;
245
- }
246
-
247
- .wl-reaction-title {
248
- font-size: 1.1rem;
249
- margin-bottom: 1rem;
250
- color: var(--white-90p);
251
- }
252
-
253
- .wl-reaction-list {
254
- display: flex;
255
- justify-content: center;
256
- flex-wrap: wrap;
257
- }
258
-
259
- .wl-reaction-item {
260
- background-color: rgba(30, 30, 30, 0.5) !important;
261
- border-radius: 8px;
262
- margin: 5px;
263
- transition: all 0.3s ease;
264
- cursor: pointer;
265
- border: 1px solid rgba(70, 70, 70, 0.2) !important;
266
- }
267
-
268
- .wl-reaction-item:hover {
269
- transform: translateY(-3px);
270
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
271
- background-color: rgba(40, 40, 40, 0.8) !important;
272
- border-color: rgba(var(--waline-accent-rgb), 0.3) !important;
273
- }
274
-
275
- .wl-reaction-img {
276
- padding: 6px;
277
- }
278
-
279
- .wl-reaction-img img {
280
- transition: transform 0.3s ease;
281
- }
282
-
283
- .wl-reaction-item:hover .wl-reaction-img img {
284
- transform: scale(1.15);
285
- }
286
-
287
- .wl-reaction-votes {
288
- font-size: 0.8rem;
289
- padding: 5px 0;
290
- background-color: rgba(var(--waline-accent-rgb), 0.7);
291
- color: var(--white-full);
292
- }
293
-
294
- /* 评论计数和排序 */
295
- .wl-meta-head {
296
- margin-bottom: 1.2rem;
297
- border-bottom: 1px solid rgba(70, 70, 70, 0.3);
298
- padding-bottom: 0.8rem;
299
- display: flex;
300
- justify-content: space-between;
301
- align-items: center;
302
- }
303
-
304
- .wl-count {
305
- font-size: 1.1rem;
306
- font-weight: 500;
307
- color: var(--white-90p);
308
- }
309
-
310
- .wl-sort {
311
- display: flex;
312
- gap: 1rem;
313
- }
314
-
315
- .wl-sort li {
316
- cursor: pointer;
317
- transition: all 0.2s ease;
318
- color: var(--white-70p);
319
- }
320
-
321
- .wl-sort li:hover {
322
- color: var(--white-90p);
323
- }
324
-
325
- .wl-sort li.active {
326
- color: rgba(var(--waline-accent-rgb), 1);
327
- font-weight: 500;
328
- }
329
-
330
- /* 页码导航 */
331
- .wl-page {
332
- margin-top: 1.2rem;
333
- text-align: center;
334
- }
335
-
336
- .wl-page button {
337
- background: rgba(30, 30, 30, 0.5) !important;
338
- color: var(--white-80p) !important;
339
- border: 1px solid rgba(70, 70, 70, 0.3) !important;
340
- border-radius: 6px;
341
- margin: 0 5px;
342
- padding: 5px 10px;
343
- transition: all 0.2s ease;
344
- }
345
-
346
- .wl-page button:hover:not(:disabled) {
347
- background: rgba(var(--waline-accent-rgb), 0.7) !important;
348
- color: var(--white-full) !important;
349
- transform: translateY(-2px);
350
- }
351
-
352
- .wl-page button.active {
353
- background: rgba(var(--waline-accent-rgb), 0.8) !important;
354
- color: var(--white-full) !important;
355
- }
356
-
357
- /* Waline底部版权信息 */
358
- .wl-power {
359
- opacity: 0.6;
360
- font-size: 0.85rem;
361
- margin-top: 2rem;
362
- text-align: center;
363
- }
364
-
365
- .wl-power a {
366
- color: rgba(var(--waline-accent-rgb), 0.9);
367
- text-decoration: none;
368
- transition: all 0.2s ease;
369
- }
370
-
371
- .wl-power a:hover {
372
- color: rgba(var(--waline-accent-rgb), 1);
373
- text-decoration: underline;
374
- }
375
-
376
- /* 评论为空状态 */
377
- .wl-empty {
378
- text-align: center;
379
- padding: 2rem 0;
380
- color: var(--white-60p);
381
- font-size: 1.1rem;
382
- }
383
-
384
- /* 支持文字数量统计 */
385
- .wl-text-number {
386
- font-size: 0.9rem;
387
- color: var(--white-60p);
388
- }
389
-
390
- /* 添加动画效果 */
391
- @keyframes fadeInUpComment {
392
- from {
393
- opacity: 0;
394
- transform: translateY(30px);
395
- }
396
- to {
397
- opacity: 1;
398
- transform: translateY(0);
399
- }
400
- }
401
-
402
- /* 降低选中文本高亮程度,移除外边框 */
403
- .waline-comment-container *::selection {
404
- background: rgba(var(--waline-accent-rgb), 0.25);
405
- color: inherit;
406
- border: none;
407
- outline: none;
408
- }
409
-
410
- .waline-comment-container *::-moz-selection {
411
- background: rgba(var(--waline-accent-rgb), 0.25);
412
- color: inherit;
413
- border: none;
414
- outline: none;
415
- }
416
-
417
- /* 响应式调整 */
418
- @media (max-width: 768px) {
419
- .waline-comment-container {
420
- padding: 1.5rem;
421
- margin-top: 2rem;
422
- }
423
-
424
- .waline-comment-title {
425
- font-size: 1.8rem;
426
- }
427
-
428
- .wl-panel {
429
- padding: 0.8rem;
430
- }
431
-
432
- .wl-header {
433
- flex-direction: column;
434
- }
435
-
436
- .wl-header-item {
437
- width: 100%;
438
- margin-bottom: 0.5rem;
439
- }
440
-
441
- /* 平板设备上的嵌套评论处理 */
442
- .wl-card {
443
- padding: 0.8rem;
444
- margin-left: 0;
445
- }
446
-
447
- .wl-children {
448
- margin-left: 0;
449
- padding-left: 0;
450
- }
451
-
452
- .wl-children .wl-card {
453
- margin-left: 0;
454
- border-left: 3px solid rgba(var(--waline-accent-rgb), 0.4);
455
- padding-left: 0.8rem;
456
- }
457
- }
458
-
459
- @media (max-width: 480px) {
460
- .waline-comment-container {
461
- padding: 1rem;
462
- margin-top: 1.5rem;
463
- }
464
-
465
- .waline-comment-title {
466
- font-size: 1.6rem;
467
- }
468
-
469
- .wl-panel {
470
- padding: 0.8rem;
471
- }
472
-
473
- .wl-reaction-list {
474
- gap: 5px;
475
- }
476
-
477
- .wl-card {
478
- padding: 0.75rem;
479
- margin-left: 0;
480
- width: 100%;
481
- box-sizing: border-box;
482
- }
483
-
484
- /* 小屏幕上的嵌套评论处理 */
485
- .wl-children {
486
- margin-left: 0;
487
- padding-left: 0;
488
- width: 100%;
489
- box-sizing: border-box;
490
- }
491
-
492
- .wl-children .wl-card {
493
- margin-left: 0;
494
- border-left: 3px solid rgba(var(--waline-accent-rgb), 0.4);
495
- padding-left: 0.6rem;
496
- width: 100%;
497
- }
498
-
499
- .wl-children .wl-children .wl-card {
500
- border-left: 3px solid rgba(var(--waline-accent-rgb), 0.3);
501
- padding-left: 0.6rem;
502
- }
503
-
504
- .wl-meta-head {
505
- flex-direction: column;
506
- gap: 0.5rem;
507
- align-items: flex-start;
508
- }
509
- }
510
- </style>
@@ -29,13 +29,13 @@ const licenseName = buildCCName(cc, t);
29
29
  <p class={style.ccTitle}>{title}</p>
30
30
  <p class={style.ccAuthor}>{t("post.author")}{author}</p>
31
31
  {url && (
32
- <p class={style.ccUrl}>
33
- {t("post.articleLink")}
34
- <a href={url} target="_blank" rel="noopener noreferrer">
35
- {url}
36
- </a>
37
- </p>
38
- )}
32
+ <p class={style.ccUrl}>
33
+ {t("post.articleLink")}
34
+ <a href={url} target="_blank" rel="noopener noreferrer">
35
+ {url}
36
+ </a>
37
+ </p>
38
+ )}
39
39
  <p class={style.ccLicense}>
40
40
  {t("post.licensedUnder")}
41
41
  <a href={licenseLink} target="_blank" rel="noopener noreferrer">
@@ -22,25 +22,25 @@ const description = post.data.desc || "";
22
22
  <article class={style.post}>
23
23
  <div class={style.postContainer}>
24
24
  {post.data.cover && (
25
- <a
26
- href={`/posts/${post.data.abbrlink}/`}
27
- class="a-none"
28
- data-astro-prefetch="viewport"
29
- aria-label={post.data.title}
30
- >
31
- <div class={style.postCover}>
32
- <img
33
- src={post.data.cover}
34
- alt={post.data.title}
35
- loading={priority ? "eager" : "lazy"}
36
- decoding="async"
37
- fetchpriority={priority ? "high" : "auto"}
38
- width="640"
39
- height="360"
40
- />
41
- </div>
42
- </a>
43
- )}
25
+ <a
26
+ href={`/posts/${post.data.abbrlink}/`}
27
+ class="a-none"
28
+ data-astro-prefetch="viewport"
29
+ aria-label={post.data.title}
30
+ >
31
+ <div class={style.postCover}>
32
+ <img
33
+ src={post.data.cover}
34
+ alt={post.data.title}
35
+ loading={priority ? "eager" : "lazy"}
36
+ decoding="async"
37
+ fetchpriority={priority ? "high" : "auto"}
38
+ width="640"
39
+ height="360"
40
+ />
41
+ </div>
42
+ </a>
43
+ )}
44
44
  <h2 class={style.postTitle}>
45
45
  <a href={`/posts/${post.data.abbrlink}/`} class="a-none" data-astro-prefetch="viewport">
46
46
  {post.data.title}
@@ -48,37 +48,37 @@ const description = post.data.desc || "";
48
48
  </h2>
49
49
  <div class={style.time}>
50
50
  {post.data.date && (
51
- <time
52
- class={style.postDate}
53
- datetime={timezone ? toMachineDateTime(post.data.date, timezone) : post.data.date}
54
- >
55
- {post.data.date}
56
- </time>
57
- )}
51
+ <time
52
+ class={style.postDate}
53
+ datetime={timezone ? toMachineDateTime(post.data.date, timezone) : post.data.date}
54
+ >
55
+ {post.data.date}
56
+ </time>
57
+ )}
58
58
  {post.data.updated && (
59
- <time
60
- class={style.postUpdated}
61
- datetime={timezone ? toMachineDateTime(post.data.updated, timezone) : post.data.updated}
62
- >
63
- {post.data.updated}
64
- </time>
65
- )}
59
+ <time
60
+ class={style.postUpdated}
61
+ datetime={timezone ? toMachineDateTime(post.data.updated, timezone) : post.data.updated}
62
+ >
63
+ {post.data.updated}
64
+ </time>
65
+ )}
66
66
  </div>
67
67
  <div class={style.postDescription}>{description}</div>
68
68
  <div class={style.postMeta}>
69
69
  <div class={style.postTags}>
70
70
  {post.data.tags?.map((tag) => (
71
- <a class="a-none" href={`/tags/${tag}`} data-astro-prefetch>
72
- <span class={style.postTag}>{tag}</span>
73
- </a>
74
- ))}
71
+ <a class="a-none" href={`/tags/${tag}`} data-astro-prefetch>
72
+ <span class={style.postTag}>{tag}</span>
73
+ </a>
74
+ ))}
75
75
  </div>
76
76
  <div class={style.postCategories}>
77
77
  {post.data.categories?.map((category) => (
78
- <a class="a-none" href={`/categories/${category}`} data-astro-prefetch>
79
- <span class={style.postCategory}>{category}</span>
80
- </a>
81
- ))}
78
+ <a class="a-none" href={`/categories/${category}`} data-astro-prefetch>
79
+ <span class={style.postCategory}>{category}</span>
80
+ </a>
81
+ ))}
82
82
  </div>
83
83
  </div>
84
84
  <a