@astro-minimax/core 0.1.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 +29 -0
- package/package.json +41 -0
- package/src/assets/icons/IconArchive.svg +1 -0
- package/src/assets/icons/IconArrowLeft.svg +1 -0
- package/src/assets/icons/IconArrowNarrowUp.svg +1 -0
- package/src/assets/icons/IconArrowRight.svg +1 -0
- package/src/assets/icons/IconArticle.svg +1 -0
- package/src/assets/icons/IconBrandX.svg +1 -0
- package/src/assets/icons/IconCalendar.svg +1 -0
- package/src/assets/icons/IconChevronLeft.svg +1 -0
- package/src/assets/icons/IconChevronRight.svg +1 -0
- package/src/assets/icons/IconEdit.svg +1 -0
- package/src/assets/icons/IconFacebook.svg +1 -0
- package/src/assets/icons/IconGitHub.svg +1 -0
- package/src/assets/icons/IconHash.svg +1 -0
- package/src/assets/icons/IconHome.svg +1 -0
- package/src/assets/icons/IconLinkedin.svg +1 -0
- package/src/assets/icons/IconMail.svg +1 -0
- package/src/assets/icons/IconMenuDeep.svg +1 -0
- package/src/assets/icons/IconMoon.svg +1 -0
- package/src/assets/icons/IconPinterest.svg +1 -0
- package/src/assets/icons/IconProject.svg +1 -0
- package/src/assets/icons/IconRss.svg +1 -0
- package/src/assets/icons/IconSearch.svg +1 -0
- package/src/assets/icons/IconSeries.svg +1 -0
- package/src/assets/icons/IconSunHigh.svg +1 -0
- package/src/assets/icons/IconTag.svg +1 -0
- package/src/assets/icons/IconTelegram.svg +1 -0
- package/src/assets/icons/IconUser.svg +1 -0
- package/src/assets/icons/IconWhatsapp.svg +1 -0
- package/src/assets/icons/IconX.svg +1 -0
- package/src/components/ai/AIChatWidget.astro +377 -0
- package/src/components/blog/Comments.astro +527 -0
- package/src/components/blog/Copyright.astro +152 -0
- package/src/components/blog/EditPost.astro +59 -0
- package/src/components/blog/FloatingTOC.astro +260 -0
- package/src/components/blog/InlineTOC.astro +223 -0
- package/src/components/blog/PostActions.astro +306 -0
- package/src/components/blog/RelatedPosts.astro +60 -0
- package/src/components/blog/SeriesNav.astro +176 -0
- package/src/components/blog/ShareLinks.astro +26 -0
- package/src/components/nav/BackButton.astro +37 -0
- package/src/components/nav/BackToTopButton.astro +223 -0
- package/src/components/nav/Breadcrumb.astro +57 -0
- package/src/components/nav/FloatingActions.astro +206 -0
- package/src/components/nav/Footer.astro +107 -0
- package/src/components/nav/Header.astro +252 -0
- package/src/components/nav/Pagination.astro +45 -0
- package/src/components/social/Socials.astro +19 -0
- package/src/components/social/Sponsors.astro +34 -0
- package/src/components/social/Sponsorship.astro +44 -0
- package/src/components/ui/Alert.astro +28 -0
- package/src/components/ui/Card.astro +206 -0
- package/src/components/ui/Collapse.astro +82 -0
- package/src/components/ui/ColorPreview.astro +29 -0
- package/src/components/ui/Datetime.astro +61 -0
- package/src/components/ui/GithubCard.astro +191 -0
- package/src/components/ui/LinkButton.astro +21 -0
- package/src/components/ui/Tag.astro +37 -0
- package/src/components/ui/TagCloud.astro +69 -0
- package/src/components/ui/Timeline.astro +39 -0
- package/src/layouts/AboutLayout.astro +24 -0
- package/src/layouts/Layout.astro +329 -0
- package/src/layouts/Main.astro +42 -0
- package/src/layouts/PostDetails.astro +445 -0
- package/src/plugins/rehype-autolink-headings.ts +46 -0
- package/src/plugins/rehype-external-links.ts +35 -0
- package/src/plugins/rehype-table-scroll.ts +35 -0
- package/src/plugins/remark-add-zoomable.ts +28 -0
- package/src/plugins/remark-reading-time.ts +18 -0
- package/src/plugins/shiki-transformers.ts +212 -0
- package/src/scripts/lightbox.ts +63 -0
- package/src/scripts/reading-position.ts +56 -0
- package/src/scripts/theme-utils.ts +19 -0
- package/src/scripts/theme.ts +179 -0
- package/src/scripts/web-vitals.ts +96 -0
- package/src/styles/code-blocks.css +194 -0
- package/src/styles/components.css +252 -0
- package/src/styles/global.css +403 -0
- package/src/styles/typography.css +149 -0
- package/src/types.ts +89 -0
- package/src/utils/generateOgImages.ts +38 -0
- package/src/utils/getCategoryPath.ts +23 -0
- package/src/utils/getPath.ts +52 -0
- package/src/utils/getPostsByCategory.ts +17 -0
- package/src/utils/getPostsByGroupCondition.ts +25 -0
- package/src/utils/getPostsByLang.ts +27 -0
- package/src/utils/getPostsByTag.ts +10 -0
- package/src/utils/getReadingTime.ts +33 -0
- package/src/utils/getRelatedPosts.ts +59 -0
- package/src/utils/getSeriesData.ts +57 -0
- package/src/utils/getSortedPosts.ts +18 -0
- package/src/utils/getTagsWithCount.ts +38 -0
- package/src/utils/getUniqueCategories.ts +81 -0
- package/src/utils/getUniqueTags.ts +23 -0
- package/src/utils/i18n.ts +249 -0
- package/src/utils/loadGoogleFont.ts +38 -0
- package/src/utils/og-templates/post.js +229 -0
- package/src/utils/og-templates/site.js +128 -0
- package/src/utils/pathUtils.ts +17 -0
- package/src/utils/postFilter.ts +11 -0
- package/src/utils/slugify.ts +23 -0
- package/src/utils/toc.ts +27 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SITE } from "@/config";
|
|
3
|
+
|
|
4
|
+
// Only render if Waline is enabled in config
|
|
5
|
+
const enabled = SITE.waline?.enabled;
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
{
|
|
9
|
+
enabled && (
|
|
10
|
+
<div class="comments-section panel-card mt-8 px-5 py-5 sm:px-6">
|
|
11
|
+
{/* Comment Section Header */}
|
|
12
|
+
<div class="mb-6 flex flex-col gap-3 border-b border-border/70 pb-4 sm:flex-row sm:items-center sm:justify-between">
|
|
13
|
+
<h3 class="flex items-center gap-2 font-display text-2xl leading-tight tracking-[-0.02em] text-foreground">
|
|
14
|
+
<svg class="size-5 text-accent" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
15
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
|
16
|
+
</svg>
|
|
17
|
+
<span>评论区</span>
|
|
18
|
+
</h3>
|
|
19
|
+
<span class="text-sm text-foreground-soft">文明评论,共建和谐社区</span>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
{/* Waline Container */}
|
|
23
|
+
<div id="waline" class="not-prose"></div>
|
|
24
|
+
|
|
25
|
+
{/* Loading indicator */}
|
|
26
|
+
<div id="waline-loading" class="flex items-center justify-center py-8">
|
|
27
|
+
<div class="animate-spin size-8 border-2 border-accent border-t-transparent rounded-full"></div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
{/* Fallback for disabled JS */}
|
|
31
|
+
<noscript>
|
|
32
|
+
<div class="rounded-lg bg-muted/50 p-4 text-center text-muted-foreground">
|
|
33
|
+
请启用 JavaScript 以查看评论功能。
|
|
34
|
+
</div>
|
|
35
|
+
</noscript>
|
|
36
|
+
|
|
37
|
+
<link rel="stylesheet" href="https://unpkg.com/@waline/client@v3/dist/waline.css" />
|
|
38
|
+
|
|
39
|
+
<script is:inline type="module" define:vars={{
|
|
40
|
+
serverURL: SITE.waline.serverURL,
|
|
41
|
+
emoji: SITE.waline.emoji,
|
|
42
|
+
lang: SITE.waline.lang,
|
|
43
|
+
reaction: SITE.waline.reaction,
|
|
44
|
+
pageview: SITE.waline.pageview,
|
|
45
|
+
login: SITE.waline.login,
|
|
46
|
+
wordLimit: SITE.waline.wordLimit,
|
|
47
|
+
imageUploader: SITE.waline.imageUploader,
|
|
48
|
+
requiredMeta: SITE.waline.requiredMeta,
|
|
49
|
+
copyright: SITE.waline.copyright
|
|
50
|
+
}}>
|
|
51
|
+
import { init } from 'https://unpkg.com/@waline/client@v3/dist/waline.js';
|
|
52
|
+
|
|
53
|
+
let walineInstance = null;
|
|
54
|
+
|
|
55
|
+
function loadWaline() {
|
|
56
|
+
const container = document.getElementById('waline');
|
|
57
|
+
const loading = document.getElementById('waline-loading');
|
|
58
|
+
|
|
59
|
+
if (container && serverURL) {
|
|
60
|
+
try {
|
|
61
|
+
// Clean up previous instance
|
|
62
|
+
if (walineInstance) {
|
|
63
|
+
// Handle both sync errors and Promise rejections from destroy()
|
|
64
|
+
// Waline's internal Vue components may reject with AbortError during cleanup
|
|
65
|
+
const result = walineInstance.destroy();
|
|
66
|
+
if (result && typeof result.catch === 'function') {
|
|
67
|
+
result.catch(() => {
|
|
68
|
+
// Suppress internal Vue AbortError during cleanup
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
walineInstance = null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
walineInstance = init({
|
|
75
|
+
el: '#waline',
|
|
76
|
+
serverURL: serverURL,
|
|
77
|
+
emoji: emoji,
|
|
78
|
+
lang: lang,
|
|
79
|
+
reaction: reaction,
|
|
80
|
+
pageview: pageview,
|
|
81
|
+
login: login,
|
|
82
|
+
wordLimit: wordLimit,
|
|
83
|
+
imageUploader: imageUploader,
|
|
84
|
+
requiredMeta: requiredMeta,
|
|
85
|
+
copyright: copyright,
|
|
86
|
+
dark: 'html[data-theme="dark"]',
|
|
87
|
+
path: window.location.pathname.replace(/\/$/, ''), // Ensure path consistency
|
|
88
|
+
locale: {
|
|
89
|
+
placeholder: '欢迎评论,支持 Markdown 语法。\n请遵守社区规范,友善发言。',
|
|
90
|
+
sofa: '快来抢沙发吧~',
|
|
91
|
+
submit: '发布评论',
|
|
92
|
+
reply: '回复',
|
|
93
|
+
cancelReply: '取消回复',
|
|
94
|
+
comment: '评论',
|
|
95
|
+
refresh: '刷新',
|
|
96
|
+
more: '加载更多...',
|
|
97
|
+
preview: '预览',
|
|
98
|
+
emoji: '表情',
|
|
99
|
+
uploadImage: '上传图片',
|
|
100
|
+
seconds: '秒前',
|
|
101
|
+
minutes: '分钟前',
|
|
102
|
+
hours: '小时前',
|
|
103
|
+
days: '天前',
|
|
104
|
+
now: '刚刚',
|
|
105
|
+
uploading: '上传中',
|
|
106
|
+
login: '登录',
|
|
107
|
+
logout: '退出',
|
|
108
|
+
admin: '博主',
|
|
109
|
+
sticky: '置顶',
|
|
110
|
+
word: '字',
|
|
111
|
+
wordHint: '评论字数应在 $0 到 $1 字之间!\n当前字数:$2',
|
|
112
|
+
anonymous: '匿名',
|
|
113
|
+
level0: '潜水',
|
|
114
|
+
level1: '冒泡',
|
|
115
|
+
level2: '吐槽',
|
|
116
|
+
level3: '活跃',
|
|
117
|
+
level4: '话痨',
|
|
118
|
+
level5: '传说',
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Hide loading indicator after successful load
|
|
123
|
+
if (loading) {
|
|
124
|
+
loading.style.display = 'none';
|
|
125
|
+
}
|
|
126
|
+
} catch (e) {
|
|
127
|
+
// eslint-disable-next-line no-console
|
|
128
|
+
console.error('Failed to load Waline:', e);
|
|
129
|
+
if (loading) {
|
|
130
|
+
loading.innerHTML = '<div class="text-center text-muted-foreground">评论加载失败,请刷新重试</div>';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Handle initial load
|
|
137
|
+
loadWaline();
|
|
138
|
+
|
|
139
|
+
// Handle View Transitions (if using ClientRouter)
|
|
140
|
+
document.addEventListener('astro:page-load', loadWaline);
|
|
141
|
+
|
|
142
|
+
// Cleanup before page swap to prevent AbortError
|
|
143
|
+
document.addEventListener('astro:before-swap', () => {
|
|
144
|
+
if (walineInstance) {
|
|
145
|
+
// Handle both sync errors and Promise rejections from destroy()
|
|
146
|
+
const result = walineInstance.destroy();
|
|
147
|
+
if (result && typeof result.catch === 'function') {
|
|
148
|
+
result.catch(() => {
|
|
149
|
+
// Ignore errors during cleanup - component may already be unmounted
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
walineInstance = null;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
</script>
|
|
156
|
+
|
|
157
|
+
<style is:global>
|
|
158
|
+
/* ===========================================
|
|
159
|
+
* WALINE COMMENT SYSTEM STYLES
|
|
160
|
+
* Comprehensive theming for light/dark modes
|
|
161
|
+
* =========================================== */
|
|
162
|
+
|
|
163
|
+
.comments-section {
|
|
164
|
+
animation: fadeIn 0.5s ease-out;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@keyframes fadeIn {
|
|
168
|
+
from {
|
|
169
|
+
opacity: 0;
|
|
170
|
+
transform: translateY(10px);
|
|
171
|
+
}
|
|
172
|
+
to {
|
|
173
|
+
opacity: 1;
|
|
174
|
+
transform: translateY(0);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* ===========================================
|
|
179
|
+
* ROOT VARIABLES (Common)
|
|
180
|
+
* =========================================== */
|
|
181
|
+
:root {
|
|
182
|
+
/* Theme Colors */
|
|
183
|
+
--waline-theme-color: var(--accent) !important;
|
|
184
|
+
--waline-active-color: var(--accent) !important;
|
|
185
|
+
|
|
186
|
+
/* Typography */
|
|
187
|
+
--waline-font-size: 0.9375rem !important;
|
|
188
|
+
--waline-border-radius: 0.5rem !important;
|
|
189
|
+
|
|
190
|
+
/* Avatar */
|
|
191
|
+
--waline-avatar-size: 2.75rem !important;
|
|
192
|
+
--waline-m-avatar-size: 2.25rem !important;
|
|
193
|
+
|
|
194
|
+
/* Box Shadow */
|
|
195
|
+
--waline-box-shadow: none !important;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* ===========================================
|
|
199
|
+
* LIGHT MODE THEME
|
|
200
|
+
* =========================================== */
|
|
201
|
+
html:not([data-theme="dark"]) {
|
|
202
|
+
/* Primary Backgrounds - use --card for consistency */
|
|
203
|
+
--waline-bg-color: var(--card) !important;
|
|
204
|
+
--waline-bg-color-light: var(--muted) !important;
|
|
205
|
+
--waline-bg-color-hover: rgba(0, 0, 0, 0.05) !important;
|
|
206
|
+
|
|
207
|
+
/* Text Colors */
|
|
208
|
+
--waline-color: var(--foreground) !important;
|
|
209
|
+
--waline-font-color: var(--foreground) !important;
|
|
210
|
+
|
|
211
|
+
/* Border & Disabled */
|
|
212
|
+
--waline-border-color: var(--border) !important;
|
|
213
|
+
--waline-disable-bg-color: var(--muted) !important;
|
|
214
|
+
--waline-disable-color: var(--foreground-soft) !important;
|
|
215
|
+
|
|
216
|
+
/* Special Colors */
|
|
217
|
+
--waline-bq-color: var(--muted) !important;
|
|
218
|
+
--waline-info-bg-color: var(--muted) !important;
|
|
219
|
+
--waline-info-color: var(--foreground-soft) !important;
|
|
220
|
+
--waline-code-bg-color: #1e1e1e !important;
|
|
221
|
+
|
|
222
|
+
/* White/Grey overrides */
|
|
223
|
+
--waline-white: var(--card) !important;
|
|
224
|
+
--waline-light-grey: var(--foreground-soft) !important;
|
|
225
|
+
--waline-dark-grey: var(--foreground) !important;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* ===========================================
|
|
229
|
+
* DARK MODE THEME
|
|
230
|
+
* =========================================== */
|
|
231
|
+
html[data-theme="dark"] {
|
|
232
|
+
/* Primary Backgrounds - use --card for consistency */
|
|
233
|
+
--waline-bg-color: var(--card) !important;
|
|
234
|
+
--waline-bg-color-light: var(--muted) !important;
|
|
235
|
+
--waline-bg-color-hover: rgba(255, 255, 255, 0.05) !important;
|
|
236
|
+
|
|
237
|
+
/* Text Colors */
|
|
238
|
+
--waline-color: var(--foreground) !important;
|
|
239
|
+
--waline-font-color: var(--foreground) !important;
|
|
240
|
+
|
|
241
|
+
/* Border & Disabled */
|
|
242
|
+
--waline-border-color: var(--border) !important;
|
|
243
|
+
--waline-disable-bg-color: rgba(128, 128, 128, 0.2) !important;
|
|
244
|
+
--waline-disable-color: var(--foreground-soft) !important;
|
|
245
|
+
|
|
246
|
+
/* Special Colors */
|
|
247
|
+
--waline-bq-color: var(--muted) !important;
|
|
248
|
+
--waline-info-bg-color: var(--muted) !important;
|
|
249
|
+
--waline-info-color: var(--foreground-soft) !important;
|
|
250
|
+
--waline-code-bg-color: #0d1117 !important;
|
|
251
|
+
|
|
252
|
+
/* White/Grey overrides */
|
|
253
|
+
--waline-white: var(--card) !important;
|
|
254
|
+
--waline-light-grey: var(--foreground-soft) !important;
|
|
255
|
+
--waline-dark-grey: var(--foreground) !important;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* ===========================================
|
|
259
|
+
* CONTAINER & PANEL STYLES
|
|
260
|
+
* =========================================== */
|
|
261
|
+
#waline {
|
|
262
|
+
padding-top: 0.5rem;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Main panel - ensure consistent background */
|
|
266
|
+
#waline .wl-panel {
|
|
267
|
+
background-color: var(--card) !important;
|
|
268
|
+
border-color: var(--border) !important;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/* Header area */
|
|
272
|
+
#waline .wl-header {
|
|
273
|
+
background-color: transparent !important;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
#waline .wl-header-item {
|
|
277
|
+
background-color: var(--muted) !important;
|
|
278
|
+
border-color: var(--border) !important;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* Input wrapper */
|
|
282
|
+
#waline .wl-input-wrapper {
|
|
283
|
+
background-color: var(--card) !important;
|
|
284
|
+
border-color: var(--border) !important;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* ===========================================
|
|
288
|
+
* INPUT & EDITOR STYLES
|
|
289
|
+
* =========================================== */
|
|
290
|
+
#waline .wl-editor,
|
|
291
|
+
#waline .wl-input {
|
|
292
|
+
min-height: 120px !important;
|
|
293
|
+
background-color: var(--card) !important;
|
|
294
|
+
border-color: var(--border) !important;
|
|
295
|
+
border-radius: 0.5rem !important;
|
|
296
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
#waline .wl-input {
|
|
300
|
+
min-height: auto !important;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
#waline .wl-editor:focus,
|
|
304
|
+
#waline .wl-input:focus {
|
|
305
|
+
border-color: var(--accent) !important;
|
|
306
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent) !important;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Textarea */
|
|
310
|
+
#waline textarea {
|
|
311
|
+
background-color: var(--card) !important;
|
|
312
|
+
color: var(--foreground) !important;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* ===========================================
|
|
316
|
+
* BUTTON STYLES
|
|
317
|
+
* =========================================== */
|
|
318
|
+
#waline .wl-btn {
|
|
319
|
+
transition: all 0.2s ease !important;
|
|
320
|
+
border-radius: 0.375rem !important;
|
|
321
|
+
background-color: var(--muted) !important;
|
|
322
|
+
color: var(--foreground) !important;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
#waline .wl-btn:hover {
|
|
326
|
+
transform: translateY(-1px);
|
|
327
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
328
|
+
background-color: var(--bg-color-hover) !important;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
#waline .wl-primary-btn {
|
|
332
|
+
font-weight: 500 !important;
|
|
333
|
+
background-color: var(--accent) !important;
|
|
334
|
+
color: var(--background) !important;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
#waline .wl-primary-btn:hover {
|
|
338
|
+
background-color: var(--accent) !important;
|
|
339
|
+
opacity: 0.9;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/* ===========================================
|
|
343
|
+
* COMMENT CARD STYLES
|
|
344
|
+
* =========================================== */
|
|
345
|
+
#waline .wl-card {
|
|
346
|
+
border-radius: 0.5rem !important;
|
|
347
|
+
background-color: var(--card) !important;
|
|
348
|
+
border-color: var(--border) !important;
|
|
349
|
+
transition: box-shadow 0.2s ease !important;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
#waline .wl-card:hover {
|
|
353
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/* Comment content area */
|
|
357
|
+
#waline .wl-content {
|
|
358
|
+
background-color: transparent !important;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* Comment meta info */
|
|
362
|
+
#waline .wl-meta {
|
|
363
|
+
color: var(--foreground-soft) !important;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* ===========================================
|
|
367
|
+
* AVATAR STYLES
|
|
368
|
+
* =========================================== */
|
|
369
|
+
#waline .wl-avatar {
|
|
370
|
+
border-radius: 50% !important;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/* ===========================================
|
|
374
|
+
* REACTION STYLES
|
|
375
|
+
* =========================================== */
|
|
376
|
+
#waline .wl-reaction {
|
|
377
|
+
background-color: transparent !important;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
#waline .wl-reaction-img {
|
|
381
|
+
transition: transform 0.2s ease !important;
|
|
382
|
+
background-color: var(--muted) !important;
|
|
383
|
+
border-radius: 0.5rem !important;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
#waline .wl-reaction-img:hover {
|
|
387
|
+
transform: scale(1.1);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
#waline .wl-reaction-title {
|
|
391
|
+
color: var(--foreground-soft) !important;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* ===========================================
|
|
395
|
+
* QUOTE & CODE STYLES
|
|
396
|
+
* =========================================== */
|
|
397
|
+
#waline .wl-quote {
|
|
398
|
+
border-left-color: var(--accent) !important;
|
|
399
|
+
background-color: var(--muted) !important;
|
|
400
|
+
color: var(--foreground) !important;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
#waline .wl-content pre,
|
|
404
|
+
#waline .wl-content code {
|
|
405
|
+
background-color: var(--waline-code-bg-color) !important;
|
|
406
|
+
border-radius: 0.25rem !important;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/* ===========================================
|
|
410
|
+
* EMOJI PICKER
|
|
411
|
+
* =========================================== */
|
|
412
|
+
#waline .wl-emoji-popup {
|
|
413
|
+
border-radius: 0.5rem !important;
|
|
414
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
|
|
415
|
+
background-color: var(--card) !important;
|
|
416
|
+
border-color: var(--border) !important;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
#waline .wl-tab-wrapper button {
|
|
420
|
+
color: var(--foreground) !important;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
#waline .wl-tab-wrapper button.active {
|
|
424
|
+
color: var(--accent) !important;
|
|
425
|
+
border-bottom-color: var(--accent) !important;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/* ===========================================
|
|
429
|
+
* REPLY FORM
|
|
430
|
+
* =========================================== */
|
|
431
|
+
#waline .wl-reply-wrapper {
|
|
432
|
+
border-radius: 0.5rem !important;
|
|
433
|
+
background-color: var(--muted) !important;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
#waline .wl-reply {
|
|
437
|
+
background-color: var(--card) !important;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* ===========================================
|
|
441
|
+
* PAGINATION
|
|
442
|
+
* =========================================== */
|
|
443
|
+
#waline .wl-page-button {
|
|
444
|
+
border-radius: 0.25rem !important;
|
|
445
|
+
transition: background-color 0.2s ease !important;
|
|
446
|
+
background-color: var(--muted) !important;
|
|
447
|
+
color: var(--foreground) !important;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
#waline .wl-page-button:hover {
|
|
451
|
+
background-color: var(--accent) !important;
|
|
452
|
+
color: var(--background) !important;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
#waline .wl-page-button.active {
|
|
456
|
+
background-color: var(--accent) !important;
|
|
457
|
+
color: var(--background) !important;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/* ===========================================
|
|
461
|
+
* ADMIN & BADGE STYLES
|
|
462
|
+
* =========================================== */
|
|
463
|
+
#waline .wl-badge {
|
|
464
|
+
background-color: var(--accent) !important;
|
|
465
|
+
color: var(--background) !important;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
#waline .wl-admin {
|
|
469
|
+
color: var(--accent) !important;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/* ===========================================
|
|
473
|
+
* LOGIN FORM
|
|
474
|
+
* =========================================== */
|
|
475
|
+
#waline .wl-login-form {
|
|
476
|
+
background-color: var(--card) !important;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/* ===========================================
|
|
480
|
+
* LOADING ANIMATION
|
|
481
|
+
* =========================================== */
|
|
482
|
+
#waline-loading {
|
|
483
|
+
transition: opacity 0.3s ease;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/* ===========================================
|
|
487
|
+
* GUEST STYLES
|
|
488
|
+
* =========================================== */
|
|
489
|
+
#waline .wl-guest {
|
|
490
|
+
background-color: transparent !important;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
#waline .wl-guest .wl-nick,
|
|
494
|
+
#waline .wl-guest .wl-link {
|
|
495
|
+
background-color: var(--card) !important;
|
|
496
|
+
border-color: var(--border) !important;
|
|
497
|
+
color: var(--foreground) !important;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/* ===========================================
|
|
501
|
+
* COMMENT OPERATIONS
|
|
502
|
+
* =========================================== */
|
|
503
|
+
#waline .wl-comment-actions button {
|
|
504
|
+
color: var(--foreground-soft) !important;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
#waline .wl-comment-actions button:hover {
|
|
508
|
+
color: var(--accent) !important;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/* ===========================================
|
|
512
|
+
* IMAGE PREVIEW
|
|
513
|
+
* =========================================== */
|
|
514
|
+
#waline .wl-image-preview {
|
|
515
|
+
background-color: rgba(0, 0, 0, 0.85) !important;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/* ===========================================
|
|
519
|
+
* VERIFICATION BADGE
|
|
520
|
+
* =========================================== */
|
|
521
|
+
#waline .wl-verified-icon {
|
|
522
|
+
color: var(--accent) !important;
|
|
523
|
+
}
|
|
524
|
+
</style>
|
|
525
|
+
</div>
|
|
526
|
+
)
|
|
527
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SITE } from "@/config";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
title: string;
|
|
6
|
+
pubDatetime: Date;
|
|
7
|
+
url?: string;
|
|
8
|
+
lang?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { title, pubDatetime, url, lang = "zh" } = Astro.props;
|
|
12
|
+
const pageUrl = url || Astro.url.href;
|
|
13
|
+
const copyrightConfig = SITE.copyright;
|
|
14
|
+
const hasSponsor = SITE.sponsor?.enabled;
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<div class="copyright-box mt-8 rounded-xl border">
|
|
18
|
+
<div class="flex flex-col gap-2 px-3 py-3 sm:px-4">
|
|
19
|
+
<div class="flex items-center gap-2 text-sm font-medium text-foreground">
|
|
20
|
+
<svg
|
|
21
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
22
|
+
width="18"
|
|
23
|
+
height="18"
|
|
24
|
+
viewBox="0 0 24 24"
|
|
25
|
+
fill="none"
|
|
26
|
+
stroke="currentColor"
|
|
27
|
+
stroke-width="2"
|
|
28
|
+
stroke-linecap="round"
|
|
29
|
+
stroke-linejoin="round"
|
|
30
|
+
>
|
|
31
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
32
|
+
<path d="M14.83 14.83a4 4 0 1 1 0-5.66"></path>
|
|
33
|
+
</svg>
|
|
34
|
+
<span class="line-clamp-1">{title}</span>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="text-xs text-foreground-soft break-all">{pageUrl}</div>
|
|
37
|
+
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs text-foreground-soft">
|
|
38
|
+
<span>
|
|
39
|
+
{lang === "zh" ? "作者" : "Author"}:
|
|
40
|
+
<span class="text-foreground">{SITE.author}</span>
|
|
41
|
+
</span>
|
|
42
|
+
<span>
|
|
43
|
+
{lang === "zh" ? "发布于" : "Published"}:
|
|
44
|
+
<time class="text-foreground">
|
|
45
|
+
{pubDatetime.toLocaleDateString(lang === "zh" ? "zh-CN" : "en-US", {
|
|
46
|
+
year: "numeric",
|
|
47
|
+
month: "short",
|
|
48
|
+
day: "numeric",
|
|
49
|
+
})}
|
|
50
|
+
</time>
|
|
51
|
+
</span>
|
|
52
|
+
<span>
|
|
53
|
+
{lang === "zh" ? "许可" : "License"}:
|
|
54
|
+
<a
|
|
55
|
+
href={copyrightConfig?.licenseUrl || "https://creativecommons.org/licenses/by-nc-sa/4.0/"}
|
|
56
|
+
target="_blank"
|
|
57
|
+
rel="noopener noreferrer"
|
|
58
|
+
class="text-accent hover:underline"
|
|
59
|
+
>
|
|
60
|
+
{copyrightConfig?.license || "CC BY-NC-SA 4.0"}
|
|
61
|
+
</a>
|
|
62
|
+
</span>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="mt-1 flex items-center gap-2">
|
|
65
|
+
<button
|
|
66
|
+
id="copy-link-btn"
|
|
67
|
+
class="flex items-center gap-1 rounded-md border px-2 py-1 text-xs text-foreground-soft transition-colors hover:bg-muted hover:text-foreground"
|
|
68
|
+
aria-label={lang === "zh" ? "复制链接" : "Copy link"}
|
|
69
|
+
>
|
|
70
|
+
<svg
|
|
71
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
72
|
+
width="14"
|
|
73
|
+
height="14"
|
|
74
|
+
viewBox="0 0 24 24"
|
|
75
|
+
fill="none"
|
|
76
|
+
stroke="currentColor"
|
|
77
|
+
stroke-width="2"
|
|
78
|
+
stroke-linecap="round"
|
|
79
|
+
stroke-linejoin="round"
|
|
80
|
+
>
|
|
81
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
|
|
82
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
|
83
|
+
</svg>
|
|
84
|
+
{lang === "zh" ? "复制链接" : "Copy link"}
|
|
85
|
+
</button>
|
|
86
|
+
<a
|
|
87
|
+
href={`https://x.com/intent/tweet?url=${encodeURIComponent(pageUrl)}&text=${encodeURIComponent(title)}`}
|
|
88
|
+
target="_blank"
|
|
89
|
+
rel="noopener noreferrer"
|
|
90
|
+
class="flex items-center gap-1 rounded-md border px-2 py-1 text-xs text-foreground-soft transition-colors hover:bg-muted hover:text-foreground"
|
|
91
|
+
aria-label="Share on X"
|
|
92
|
+
>
|
|
93
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
|
|
94
|
+
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
|
95
|
+
</svg>
|
|
96
|
+
</a>
|
|
97
|
+
<a
|
|
98
|
+
href={`https://service.weibo.com/share/share.php?url=${encodeURIComponent(pageUrl)}&title=${encodeURIComponent(title)}`}
|
|
99
|
+
target="_blank"
|
|
100
|
+
rel="noopener noreferrer"
|
|
101
|
+
class="flex items-center gap-1 rounded-md border px-2 py-1 text-xs text-foreground-soft transition-colors hover:bg-muted hover:text-foreground"
|
|
102
|
+
aria-label="Share on Weibo"
|
|
103
|
+
>
|
|
104
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
|
|
105
|
+
<path d="M9.82 13.87c-2.27 0-4.11.96-4.11 2.14s1.84 2.14 4.11 2.14 4.11-.96 4.11-2.14-1.84-2.14-4.11-2.14zm1.28 3.16c-.63.37-1.52.43-2 .13-.47-.29-.4-.87.18-1.28.58-.41 1.48-.47 1.97-.13.49.34.42.91-.15 1.28zM20.5 7.5c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5.67 1.5 1.5 1.5 1.5-.67 1.5-1.5zM22 4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-2.18 3.35c-.94-3.47-4.58-5.16-8.13-3.78-3.43 1.34-5.54 5.1-4.6 8.31.93 3.18 4.58 4.86 8.12 3.85 3.66-1.04 5.55-5.06 4.61-8.38z" />
|
|
106
|
+
</svg>
|
|
107
|
+
</a>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
{
|
|
111
|
+
hasSponsor && (
|
|
112
|
+
<div class="rounded-b-xl border-t px-3 pb-1.5 pt-1">
|
|
113
|
+
<a
|
|
114
|
+
href={`/${lang}/about#sponsorship`}
|
|
115
|
+
class="flex items-center justify-between text-sm text-foreground-soft transition-colors hover:text-accent"
|
|
116
|
+
>
|
|
117
|
+
<span>{lang === "zh" ? "请我喝杯咖啡 ☕" : "Buy me a cup of coffee ☕"}</span>
|
|
118
|
+
<svg
|
|
119
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
120
|
+
width="16"
|
|
121
|
+
height="16"
|
|
122
|
+
viewBox="0 0 24 24"
|
|
123
|
+
fill="none"
|
|
124
|
+
stroke="currentColor"
|
|
125
|
+
stroke-width="2"
|
|
126
|
+
stroke-linecap="round"
|
|
127
|
+
stroke-linejoin="round"
|
|
128
|
+
>
|
|
129
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
130
|
+
</svg>
|
|
131
|
+
</a>
|
|
132
|
+
</div>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<script>
|
|
138
|
+
function initCopyLink() {
|
|
139
|
+
document.querySelectorAll("#copy-link-btn").forEach(btn => {
|
|
140
|
+
btn.addEventListener("click", () => {
|
|
141
|
+
navigator.clipboard.writeText(window.location.href);
|
|
142
|
+
const original = btn.textContent;
|
|
143
|
+
btn.textContent = "✓ Copied!";
|
|
144
|
+
setTimeout(() => {
|
|
145
|
+
if (original) btn.textContent = original;
|
|
146
|
+
}, 2000);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
initCopyLink();
|
|
151
|
+
document.addEventListener("astro:page-load", initCopyLink);
|
|
152
|
+
</script>
|