@anglefeint/astro-theme 0.1.8 → 0.1.9
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/package.json +1 -1
- package/public/scripts/about-effects.js +35 -9
- package/public/scripts/blogpost-effects.js +39 -13
- package/public/styles/blog-list.css +35 -0
- package/src/components/FormattedDate.astro +3 -2
- package/src/components/shared/CommonFooter.astro +2 -30
- package/src/components/shared/CommonHeader.astro +4 -49
- package/src/components/shared/Icon.astro +39 -0
- package/src/components/shared/LangSwitcher.astro +35 -0
- package/src/components/shared/SocialMenu.astro +20 -0
- package/src/i18n/messages.ts +1 -1
- package/src/layouts/BlogPost.astro +1 -1
- package/src/layouts/HomePage.astro +1 -1
package/package.json
CHANGED
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
runtimeConfig = {};
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
+
var prefersReducedMotion = false;
|
|
13
|
+
try {
|
|
14
|
+
prefersReducedMotion = !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);
|
|
15
|
+
} catch (_e) {
|
|
16
|
+
prefersReducedMotion = false;
|
|
17
|
+
}
|
|
12
18
|
// ── Terminal background: dir + 可输入 (点击背景聚焦,回车仅换行) ──
|
|
13
19
|
var bgCanvas = document.querySelector('.hacker-bg-canvas');
|
|
14
20
|
if (bgCanvas) {
|
|
@@ -107,14 +113,19 @@
|
|
|
107
113
|
cancelAnimationFrame(bgAnimationId);
|
|
108
114
|
bgAnimationId = 0;
|
|
109
115
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (document.hidden) {
|
|
116
|
+
if (prefersReducedMotion) {
|
|
117
|
+
renderBg(performance.now());
|
|
113
118
|
stopBackgroundLoop();
|
|
114
|
-
|
|
119
|
+
} else {
|
|
120
|
+
startBackgroundLoop();
|
|
121
|
+
document.addEventListener('visibilitychange', function() {
|
|
122
|
+
if (document.hidden) {
|
|
123
|
+
stopBackgroundLoop();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
startBackgroundLoop();
|
|
127
|
+
});
|
|
115
128
|
}
|
|
116
|
-
startBackgroundLoop();
|
|
117
|
-
});
|
|
118
129
|
|
|
119
130
|
// 点击背景聚焦,点击内容失焦
|
|
120
131
|
document.addEventListener('click', function(e) {
|
|
@@ -207,7 +218,7 @@
|
|
|
207
218
|
var backTop = document.querySelector('.hacker-back-to-top');
|
|
208
219
|
if (backTop) {
|
|
209
220
|
backTop.addEventListener('click', function() {
|
|
210
|
-
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
221
|
+
window.scrollTo({ top: 0, behavior: prefersReducedMotion ? 'auto' : 'smooth' });
|
|
211
222
|
});
|
|
212
223
|
}
|
|
213
224
|
|
|
@@ -235,6 +246,7 @@
|
|
|
235
246
|
return s;
|
|
236
247
|
}
|
|
237
248
|
function startDecryptorFlash() {
|
|
249
|
+
if (prefersReducedMotion) return;
|
|
238
250
|
if (decryptorInterval) clearInterval(decryptorInterval);
|
|
239
251
|
var keys = 0, sec = 1;
|
|
240
252
|
decryptorInterval = setInterval(function() {
|
|
@@ -444,7 +456,7 @@
|
|
|
444
456
|
|
|
445
457
|
// ── Mouse glow ──
|
|
446
458
|
var glow = document.querySelector('.hacker-mouse-glow');
|
|
447
|
-
if (glow) {
|
|
459
|
+
if (glow && !prefersReducedMotion) {
|
|
448
460
|
var glowRaf;
|
|
449
461
|
var mx = 0, my = 0;
|
|
450
462
|
document.addEventListener('mousemove', function(e) {
|
|
@@ -476,7 +488,14 @@
|
|
|
476
488
|
|
|
477
489
|
// ── Typewriter section titles ──
|
|
478
490
|
var titles = document.querySelectorAll('.about-section-title');
|
|
479
|
-
if (
|
|
491
|
+
if (prefersReducedMotion && titles.length) {
|
|
492
|
+
titles.forEach(function(el) {
|
|
493
|
+
var fullText = el.textContent || '';
|
|
494
|
+
el.setAttribute('data-full-text', fullText);
|
|
495
|
+
el.textContent = fullText;
|
|
496
|
+
el.style.minHeight = '1.2em';
|
|
497
|
+
});
|
|
498
|
+
} else if (window.IntersectionObserver && titles.length) {
|
|
480
499
|
titles.forEach(function(el) {
|
|
481
500
|
var fullText = el.textContent || '';
|
|
482
501
|
el.setAttribute('data-full-text', fullText);
|
|
@@ -510,6 +529,13 @@
|
|
|
510
529
|
var scan = document.querySelector('.hacker-load-scan');
|
|
511
530
|
if (regen && article) {
|
|
512
531
|
regen.addEventListener('click', function() {
|
|
532
|
+
if (prefersReducedMotion) {
|
|
533
|
+
article.classList.add('hacker-flash');
|
|
534
|
+
setTimeout(function() {
|
|
535
|
+
article.classList.remove('hacker-flash');
|
|
536
|
+
}, 120);
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
513
539
|
regen.disabled = true;
|
|
514
540
|
article.classList.add('hacker-flash');
|
|
515
541
|
if (scan) {
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
(function() {
|
|
2
|
+
function init() {
|
|
3
|
+
var prefersReducedMotion = false;
|
|
4
|
+
try {
|
|
5
|
+
prefersReducedMotion = !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);
|
|
6
|
+
} catch (_e) {
|
|
7
|
+
prefersReducedMotion = false;
|
|
8
|
+
}
|
|
9
|
+
// 阅读进度条
|
|
4
10
|
var progress = document.querySelector('.ai-read-progress');
|
|
5
11
|
var article = document.querySelector('.ai-article');
|
|
6
12
|
var toast = document.querySelector('.ai-stage-toast');
|
|
@@ -42,13 +48,13 @@
|
|
|
42
48
|
onScroll();
|
|
43
49
|
window.addEventListener('scroll', onScroll, { passive: true });
|
|
44
50
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
var backTop = document.querySelector('.ai-back-to-top');
|
|
52
|
+
if (backTop) {
|
|
53
|
+
backTop.addEventListener('click', function() {
|
|
54
|
+
window.scrollTo({ top: 0, behavior: prefersReducedMotion ? 'auto' : 'smooth' });
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function initHeroCanvas() {
|
|
52
58
|
var shell = document.querySelector('.hero-shell');
|
|
53
59
|
if (!shell) return;
|
|
54
60
|
var canvas = shell.querySelector('.hero-canvas');
|
|
@@ -283,6 +289,11 @@
|
|
|
283
289
|
sizeCanvas();
|
|
284
290
|
buildEdge(img);
|
|
285
291
|
wrap.classList.add('ready');
|
|
292
|
+
if (prefersReducedMotion) {
|
|
293
|
+
var staticCtx = canvas.getContext('2d');
|
|
294
|
+
if (staticCtx) staticCtx.drawImage(baseCanvas, 0, 0);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
286
297
|
heroRaf = requestAnimationFrame(heroRender);
|
|
287
298
|
};
|
|
288
299
|
img.src = new URL(src, window.location.href).href;
|
|
@@ -294,6 +305,7 @@
|
|
|
294
305
|
}
|
|
295
306
|
}, { passive: true });
|
|
296
307
|
function onHeroVisibilityChange() {
|
|
308
|
+
if (prefersReducedMotion) return;
|
|
297
309
|
if (document.hidden) {
|
|
298
310
|
if (heroRaf) cancelAnimationFrame(heroRaf);
|
|
299
311
|
heroRaf = 0;
|
|
@@ -305,7 +317,7 @@
|
|
|
305
317
|
window.addEventListener('beforeunload', function() { cancelAnimationFrame(heroRaf); }, { once: true });
|
|
306
318
|
}
|
|
307
319
|
initHeroCanvas();
|
|
308
|
-
|
|
320
|
+
function initRedQueenTv() {
|
|
309
321
|
var shell = document.querySelector('.rq-tv');
|
|
310
322
|
var stage = document.querySelector('.rq-tv-stage');
|
|
311
323
|
var toggle = document.querySelector('.rq-tv-toggle');
|
|
@@ -361,8 +373,22 @@
|
|
|
361
373
|
return new URL(item.url, window.location.href).href;
|
|
362
374
|
}
|
|
363
375
|
|
|
364
|
-
|
|
365
|
-
|
|
376
|
+
var playlist = [{ url: source, type: guessImageType(source), holdLast: 360 }];
|
|
377
|
+
if (source2) playlist.push({ url: source2, type: guessImageType(source2), holdLast: 500 });
|
|
378
|
+
if (prefersReducedMotion) {
|
|
379
|
+
setCollapsed(false);
|
|
380
|
+
var staticImg = new Image();
|
|
381
|
+
staticImg.className = 'rq-tv-screen';
|
|
382
|
+
staticImg.alt = '';
|
|
383
|
+
staticImg.decoding = 'async';
|
|
384
|
+
staticImg.loading = 'lazy';
|
|
385
|
+
staticImg.src = resolveItemUrl(playlist[0]);
|
|
386
|
+
stage.innerHTML = '';
|
|
387
|
+
stage.appendChild(staticImg);
|
|
388
|
+
toggle.hidden = true;
|
|
389
|
+
toggle.setAttribute('aria-hidden', 'true');
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
366
392
|
|
|
367
393
|
function setCollapsed(collapsed) {
|
|
368
394
|
shell.classList.toggle('rq-tv-collapsed', collapsed);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* Pagination styles for cyber blog list pages */
|
|
2
|
+
body.cyber-page .pagination {
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 0.5rem;
|
|
7
|
+
margin-top: 2.5rem;
|
|
8
|
+
padding: 1.5rem 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
body.cyber-page .pagination a {
|
|
12
|
+
padding: 0.5rem 1rem;
|
|
13
|
+
color: rgb(212, 196, 232);
|
|
14
|
+
text-decoration: none;
|
|
15
|
+
border: 1px solid rgba(198, 156, 224, 0.42);
|
|
16
|
+
border-radius: 4px;
|
|
17
|
+
transition: 0.25s ease;
|
|
18
|
+
text-shadow: 0 0 10px rgba(214, 152, 226, 0.2);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
body.cyber-page .pagination a:hover {
|
|
22
|
+
border-color: rgba(226, 166, 236, 0.88);
|
|
23
|
+
text-shadow: 0 0 15px rgba(232, 174, 242, 0.5);
|
|
24
|
+
box-shadow: 0 0 15px rgba(222, 154, 228, 0.26);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body.cyber-page .pagination a.current {
|
|
28
|
+
background: rgba(188, 122, 214, 0.2);
|
|
29
|
+
border-color: rgb(224, 170, 236);
|
|
30
|
+
color: rgb(244, 224, 252);
|
|
31
|
+
text-shadow: 0 0 15px rgba(232, 174, 242, 0.48);
|
|
32
|
+
box-shadow:
|
|
33
|
+
0 0 20px rgba(118, 198, 255, 0.24),
|
|
34
|
+
0 0 12px rgba(220, 152, 230, 0.22);
|
|
35
|
+
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
interface Props {
|
|
3
3
|
date: Date;
|
|
4
|
+
locale?: string;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
|
-
const { date } = Astro.props;
|
|
7
|
+
const { date, locale = 'en-US' } = Astro.props as Props;
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
<time datetime={date.toISOString()}>
|
|
10
11
|
{
|
|
11
|
-
date.toLocaleDateString(
|
|
12
|
+
date.toLocaleDateString(locale, {
|
|
12
13
|
year: 'numeric',
|
|
13
14
|
month: 'short',
|
|
14
15
|
day: 'numeric',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { SITE_TAGLINE, SITE_TITLE } from '@anglefeint/site-config/site';
|
|
3
3
|
import { SOCIAL_LINKS } from '@anglefeint/site-config/social';
|
|
4
|
+
import SocialMenu from './SocialMenu.astro';
|
|
4
5
|
|
|
5
6
|
const today = new Date();
|
|
6
7
|
interface Props {
|
|
@@ -16,36 +17,7 @@ const { tagline = SITE_TAGLINE, scanlines = false } = Astro.props as Props;
|
|
|
16
17
|
© {today.getFullYear()} {SITE_TITLE}. {tagline}
|
|
17
18
|
{SOCIAL_LINKS.length > 0 && (
|
|
18
19
|
<div class="social-links">
|
|
19
|
-
{SOCIAL_LINKS
|
|
20
|
-
<a href={link.href} target="_blank" rel="noopener noreferrer">
|
|
21
|
-
<span class="sr-only">{link.label}</span>
|
|
22
|
-
{link.icon === 'mastodon' && (
|
|
23
|
-
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32">
|
|
24
|
-
<path
|
|
25
|
-
fill="currentColor"
|
|
26
|
-
d="M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765c0 0-2.285 1.017-2.285 4.488l-.002.662c-.004.64-.007 1.35.011 2.091.083 3.394.626 6.74 3.78 7.57 1.454.383 2.703.463 3.709.408 1.823-.1 2.847-.647 2.847-.647l-.06-1.317s-1.303.41-2.767.36c-1.45-.05-2.98-.156-3.215-1.928a3.614 3.614 0 0 1-.033-.496s1.424.346 3.228.428c1.103.05 2.137-.064 3.188-.189zm1.613-2.47H11.13v-4.08c0-.859-.364-1.295-1.091-1.295-.804 0-1.207.517-1.207 1.541v2.233H7.168V5.89c0-1.024-.403-1.541-1.207-1.541-.727 0-1.091.436-1.091 1.296v4.079H3.197V5.522c0-.859.22-1.541.66-2.046.456-.505 1.052-.764 1.793-.764.856 0 1.504.328 1.933.983L8 4.39l.417-.695c.429-.655 1.077-.983 1.934-.983.74 0 1.336.259 1.791.764.442.505.661 1.187.661 2.046v4.203z"
|
|
27
|
-
/>
|
|
28
|
-
</svg>
|
|
29
|
-
)}
|
|
30
|
-
{link.icon === 'twitter' && (
|
|
31
|
-
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32">
|
|
32
|
-
<path
|
|
33
|
-
fill="currentColor"
|
|
34
|
-
d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"
|
|
35
|
-
/>
|
|
36
|
-
</svg>
|
|
37
|
-
)}
|
|
38
|
-
{link.icon === 'github' && (
|
|
39
|
-
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32">
|
|
40
|
-
<path
|
|
41
|
-
fill="currentColor"
|
|
42
|
-
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
|
|
43
|
-
/>
|
|
44
|
-
</svg>
|
|
45
|
-
)}
|
|
46
|
-
{!link.icon && <span>{link.label}</span>}
|
|
47
|
-
</a>
|
|
48
|
-
))}
|
|
20
|
+
<SocialMenu links={SOCIAL_LINKS} />
|
|
49
21
|
</div>
|
|
50
22
|
)}
|
|
51
23
|
{scanlines && <div class="ai-scanlines" aria-hidden="true"></div>}
|
|
@@ -3,6 +3,8 @@ import { SITE_TITLE } from '@anglefeint/site-config/site';
|
|
|
3
3
|
import { SOCIAL_LINKS } from '@anglefeint/site-config/social';
|
|
4
4
|
import { THEME } from '@anglefeint/site-config/theme';
|
|
5
5
|
import HeaderLink from '../HeaderLink.astro';
|
|
6
|
+
import LangSwitcher from './LangSwitcher.astro';
|
|
7
|
+
import SocialMenu from './SocialMenu.astro';
|
|
6
8
|
import {
|
|
7
9
|
DEFAULT_LOCALE,
|
|
8
10
|
LOCALE_LABELS,
|
|
@@ -67,59 +69,12 @@ const localeOptions = SUPPORTED_LOCALES.map((targetLocale) => ({
|
|
|
67
69
|
</div>
|
|
68
70
|
<div class="nav-right">
|
|
69
71
|
<div class="social-links">
|
|
70
|
-
<
|
|
71
|
-
<label class="lang-label" for="lang-select">{labels.language}</label>
|
|
72
|
-
<select
|
|
73
|
-
id="lang-select"
|
|
74
|
-
class="lang-select"
|
|
75
|
-
aria-label={labels.language}
|
|
76
|
-
onchange="if (this.value) window.location.href = this.value;"
|
|
77
|
-
>
|
|
78
|
-
{
|
|
79
|
-
localeOptions.map((option) => (
|
|
80
|
-
<option value={option.href} selected={option.locale === locale}>
|
|
81
|
-
{option.label}
|
|
82
|
-
</option>
|
|
83
|
-
))
|
|
84
|
-
}
|
|
85
|
-
</select>
|
|
86
|
-
</div>
|
|
72
|
+
<LangSwitcher label={labels.language} currentLocale={locale} options={localeOptions} />
|
|
87
73
|
<div class="nav-status" aria-label="System status">
|
|
88
74
|
<span class="nav-status-dot" aria-hidden="true"></span>
|
|
89
75
|
<span class="nav-status-text">{labels.status}</span>
|
|
90
76
|
</div>
|
|
91
|
-
{
|
|
92
|
-
SOCIAL_LINKS.map((link) => (
|
|
93
|
-
<a href={link.href} target="_blank" rel="noopener noreferrer">
|
|
94
|
-
<span class="sr-only">{link.label}</span>
|
|
95
|
-
{link.icon === 'mastodon' && (
|
|
96
|
-
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32">
|
|
97
|
-
<path
|
|
98
|
-
fill="currentColor"
|
|
99
|
-
d="M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765c0 0-2.285 1.017-2.285 4.488l-.002.662c-.004.64-.007 1.35.011 2.091.083 3.394.626 6.74 3.78 7.57 1.454.383 2.703.463 3.709.408 1.823-.1 2.847-.647 2.847-.647l-.06-1.317s-1.303.41-2.767.36c-1.45-.05-2.98-.156-3.215-1.928a3.614 3.614 0 0 1-.033-.496s1.424.346 3.228.428c1.103.05 2.137-.064 3.188-.189zm1.613-2.47H11.13v-4.08c0-.859-.364-1.295-1.091-1.295-.804 0-1.207.517-1.207 1.541v2.233H7.168V5.89c0-1.024-.403-1.541-1.207-1.541-.727 0-1.091.436-1.091 1.296v4.079H3.197V5.522c0-.859.22-1.541.66-2.046.456-.505 1.052-.764 1.793-.764.856 0 1.504.328 1.933.983L8 4.39l.417-.695c.429-.655 1.077-.983 1.934-.983.74 0 1.336.259 1.791.764.442.505.661 1.187.661 2.046v4.203z"
|
|
100
|
-
/>
|
|
101
|
-
</svg>
|
|
102
|
-
)}
|
|
103
|
-
{link.icon === 'twitter' && (
|
|
104
|
-
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32">
|
|
105
|
-
<path
|
|
106
|
-
fill="currentColor"
|
|
107
|
-
d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"
|
|
108
|
-
/>
|
|
109
|
-
</svg>
|
|
110
|
-
)}
|
|
111
|
-
{link.icon === 'github' && (
|
|
112
|
-
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32">
|
|
113
|
-
<path
|
|
114
|
-
fill="currentColor"
|
|
115
|
-
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
|
|
116
|
-
/>
|
|
117
|
-
</svg>
|
|
118
|
-
)}
|
|
119
|
-
{!link.icon && <span>{link.label}</span>}
|
|
120
|
-
</a>
|
|
121
|
-
))
|
|
122
|
-
}
|
|
77
|
+
<SocialMenu links={SOCIAL_LINKS} />
|
|
123
78
|
</div>
|
|
124
79
|
</div>
|
|
125
80
|
</nav>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
name?: 'mastodon' | 'twitter' | 'github';
|
|
4
|
+
size?: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { name, size = 32 } = Astro.props as Props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
{
|
|
11
|
+
name === 'mastodon' && (
|
|
12
|
+
<svg viewBox="0 0 16 16" aria-hidden="true" width={size} height={size}>
|
|
13
|
+
<path
|
|
14
|
+
fill="currentColor"
|
|
15
|
+
d="M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765c0 0-2.285 1.017-2.285 4.488l-.002.662c-.004.64-.007 1.35.011 2.091.083 3.394.626 6.74 3.78 7.57 1.454.383 2.703.463 3.709.408 1.823-.1 2.847-.647 2.847-.647l-.06-1.317s-1.303.41-2.767.36c-1.45-.05-2.98-.156-3.215-1.928a3.614 3.614 0 0 1-.033-.496s1.424.346 3.228.428c1.103.05 2.137-.064 3.188-.189zm1.613-2.47H11.13v-4.08c0-.859-.364-1.295-1.091-1.295-.804 0-1.207.517-1.207 1.541v2.233H7.168V5.89c0-1.024-.403-1.541-1.207-1.541-.727 0-1.091.436-1.091 1.296v4.079H3.197V5.522c0-.859.22-1.541.66-2.046.456-.505 1.052-.764 1.793-.764.856 0 1.504.328 1.933.983L8 4.39l.417-.695c.429-.655 1.077-.983 1.934-.983.74 0 1.336.259 1.791.764.442.505.661 1.187.661 2.046v4.203z"
|
|
16
|
+
/>
|
|
17
|
+
</svg>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
{
|
|
21
|
+
name === 'twitter' && (
|
|
22
|
+
<svg viewBox="0 0 16 16" aria-hidden="true" width={size} height={size}>
|
|
23
|
+
<path
|
|
24
|
+
fill="currentColor"
|
|
25
|
+
d="M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z"
|
|
26
|
+
/>
|
|
27
|
+
</svg>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
{
|
|
31
|
+
name === 'github' && (
|
|
32
|
+
<svg viewBox="0 0 16 16" aria-hidden="true" width={size} height={size}>
|
|
33
|
+
<path
|
|
34
|
+
fill="currentColor"
|
|
35
|
+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
|
|
36
|
+
/>
|
|
37
|
+
</svg>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { Locale } from '@anglefeint/site-i18n/config';
|
|
3
|
+
|
|
4
|
+
interface LocaleOption {
|
|
5
|
+
locale: Locale;
|
|
6
|
+
label: string;
|
|
7
|
+
href: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
label: string;
|
|
12
|
+
currentLocale: Locale;
|
|
13
|
+
options: LocaleOption[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { label, currentLocale, options } = Astro.props as Props;
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<div class="lang-switcher" aria-label={label}>
|
|
20
|
+
<label class="lang-label" for="lang-select">{label}</label>
|
|
21
|
+
<select
|
|
22
|
+
id="lang-select"
|
|
23
|
+
class="lang-select"
|
|
24
|
+
aria-label={label}
|
|
25
|
+
onchange="if (this.value) window.location.href = this.value;"
|
|
26
|
+
>
|
|
27
|
+
{
|
|
28
|
+
options.map((option) => (
|
|
29
|
+
<option value={option.href} selected={option.locale === currentLocale}>
|
|
30
|
+
{option.label}
|
|
31
|
+
</option>
|
|
32
|
+
))
|
|
33
|
+
}
|
|
34
|
+
</select>
|
|
35
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SOCIAL_LINKS, type SocialLink } from '@anglefeint/site-config/social';
|
|
3
|
+
import Icon from './Icon.astro';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
links?: SocialLink[];
|
|
7
|
+
iconSize?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { links = SOCIAL_LINKS, iconSize = 32 } = Astro.props as Props;
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
links.map((link) => (
|
|
15
|
+
<a href={link.href} target="_blank" rel="noopener noreferrer">
|
|
16
|
+
<span class="sr-only">{link.label}</span>
|
|
17
|
+
{link.icon ? <Icon name={link.icon} size={iconSize} /> : <span>{link.label}</span>}
|
|
18
|
+
</a>
|
|
19
|
+
))
|
|
20
|
+
}
|
package/src/i18n/messages.ts
CHANGED
|
@@ -243,7 +243,7 @@ for (let i = 0; i < pts.length; i++) {
|
|
|
243
243
|
)}
|
|
244
244
|
<h3 class="ai-related-card-title">{p.data.title}</h3>
|
|
245
245
|
<p class="ai-related-card-date">
|
|
246
|
-
<FormattedDate date={p.data.pubDate} />
|
|
246
|
+
<FormattedDate date={p.data.pubDate} locale={resolvedLocale} />
|
|
247
247
|
</p>
|
|
248
248
|
</a>
|
|
249
249
|
))}
|
|
@@ -32,7 +32,7 @@ const heroText = SITE_HERO_BY_LOCALE[locale] ?? messages.home.hero;
|
|
|
32
32
|
{post.data.title}
|
|
33
33
|
</a>
|
|
34
34
|
<div class="home-post-meta">
|
|
35
|
-
<FormattedDate date={post.data.pubDate} />
|
|
35
|
+
<FormattedDate date={post.data.pubDate} locale={locale} />
|
|
36
36
|
{post.data.description && <> · {post.data.description}</>}
|
|
37
37
|
</div>
|
|
38
38
|
</li>
|