Commit 01a2395
Changed files (8)
src
components
aside
recent-comments
comment
types
src/components/aside/recent-comments/Artalk.astro
@@ -0,0 +1,73 @@
+<script>
+ import { asideConfig, commentConfig } from '@/config';
+ import {
+ cleanCommentHtml,
+ cleanPlaceholders,
+ createCommentItem,
+ getTemplate,
+ } from './utils.ts';
+
+ async function setup() {
+ const artalkConfig = commentConfig.artalk!;
+ const commentCount = asideConfig.recentComment.count;
+
+ const apiCommentUrl = new URL(
+ `api/v2/stats/latest_comments?limit=${commentCount}`,
+ artalkConfig.serverURL
+ ).toString();
+ const apiConfigUrl = new URL(`api/v2/conf`, artalkConfig.serverURL).toString();
+
+ const responseComment = fetch(apiCommentUrl, {
+ method: 'GET',
+ });
+ const responseConfig = fetch(apiConfigUrl, {
+ method: 'GET',
+ });
+ if (!(await responseComment).ok) {
+ throw new Error('Failed to fetch recent comments');
+ }
+ if (!(await responseConfig).ok) {
+ throw new Error('Failed to fetch comment config');
+ }
+
+ const commentData: {
+ id: number;
+ nick: string;
+ content_marked: string;
+ date: string;
+ email_encrypted: string;
+ page_url: string;
+ }[] = (await (await responseComment).json()).data;
+ const configData: {
+ gravatar: {
+ mirror: string;
+ params: string;
+ };
+ } = (await (await responseConfig).json()).frontend_conf;
+
+ const getAvatarUrl = (email: string) => {
+ return `${configData.gravatar.mirror}${email}?${configData.gravatar.params}`;
+ };
+
+ const { container, template } = getTemplate()!;
+ if (container && !template) {
+ // 说明已经加载完毕, 模板被删除了
+ return;
+ }
+
+ commentData.forEach((item) =>
+ createCommentItem(container, template!, {
+ avatarUrl: getAvatarUrl(item.email_encrypted),
+ commentContent: cleanCommentHtml(item.content_marked),
+ commentUrl: `${item.page_url}#atk-comment-${item.id}`,
+ author: item.nick,
+ time: new Date(item.date),
+ })
+ );
+
+ cleanPlaceholders(container, template!);
+ }
+
+ document.addEventListener('astro:page-load', setup);
+ await setup();
+</script>
src/components/aside/recent-comments/Waline.astro
@@ -10,8 +10,10 @@
async function setup() {
const walineConfig = commentConfig.waline!;
const commentCount = asideConfig.recentComment.count;
- const apiUrl = `${walineConfig.serverURL}/api/comment?type=recent&count=${commentCount}`;
- console.log('apiUrl', apiUrl);
+ const apiUrl = new URL(
+ `api/comment?type=recent&count=${commentCount}`,
+ walineConfig.serverURL
+ ).toString();
const response = await fetch(apiUrl, {
method: 'GET',
src/components/aside/ResentCommentsCard.astro
@@ -2,6 +2,7 @@
import { asideConfig, commentConfig } from '@/config';
import I18nKey from '@i18n/I18nKey';
import { i18n } from '@i18n/translation';
+import ArtalkRecentCommentScript from './recent-comments/Artalk.astro';
import TwikooRecentCommentScript from './recent-comments/Twikoo.astro';
import WalineRecentCommentScript from './recent-comments/Waline.astro';
---
@@ -50,6 +51,8 @@ import WalineRecentCommentScript from './recent-comments/Waline.astro';
return <TwikooRecentCommentScript />;
case 'waline':
return <WalineRecentCommentScript />;
+ case 'artalk':
+ return <ArtalkRecentCommentScript />;
default:
throw new Error(
`Unsupported comment provider: '${commentConfig.provider}' for recent comments`
src/components/comment/Artalk.astro
@@ -0,0 +1,42 @@
+---
+import 'artalk/Artalk.css';
+---
+
+<div id="artalk-wrapper" class="mt-6"></div>
+
+<script>
+ import { commentConfig, siteConfig } from '@/config';
+ import Artalk from 'artalk';
+
+ function setup() {
+ function getCurrentMode(): boolean {
+ if (!('darkMode' in localStorage)) {
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
+ }
+ return localStorage.darkMode === 'true';
+ }
+
+ const artalk = Artalk.init({
+ el: '#artalk-wrapper',
+ darkMode: getCurrentMode(),
+ pageKey: window.location.pathname,
+ pageTitle: document.title,
+ server: commentConfig.artalk?.serverURL,
+ site: siteConfig.title,
+ locale: commentConfig.artalk?.locale || siteConfig.lang,
+ });
+
+ document.addEventListener('blog:darkmode-change', (e) => {
+ // @ts-expect-error CustomEvent.detail is not defined in TypeScript
+ const { isDark } = e.detail;
+ artalk.setDarkMode(isDark);
+ });
+
+ document.addEventListener('astro:before-swap', () => {
+ artalk.destroy();
+ });
+ }
+
+ document.addEventListener('astro:page-load', setup);
+ setup();
+</script>
src/components/Comment.astro
@@ -3,6 +3,7 @@ import { commentConfig } from '@/config';
import Giscus from '@components/comment/Giscus.astro';
import Twikoo from '@components/comment/Twikoo.astro';
import Waline from '@components/comment/Waline.astro';
+import Artalk from './comment/Artalk.astro';
---
<div id="page-comment">
@@ -15,6 +16,8 @@ import Waline from '@components/comment/Waline.astro';
return <Giscus />;
case 'waline':
return <Waline />;
+ case 'artalk':
+ return <Artalk />;
}
})()
}
src/types/config.ts
@@ -498,7 +498,7 @@ export type CommentConfig = {
*
* 评论的提供者。
*/
- provider: 'twikoo' | 'giscus' | 'waline';
+ provider: 'twikoo' | 'giscus' | 'waline' | 'artalk';
/**
* The configuration of Twikoo.
*
@@ -708,4 +708,32 @@ export type CommentConfig = {
*/
reaction?: boolean | string[];
};
+ /**
+ * The configuration of Artalk.
+ * Most settings should be configured on the server side,
+ * so only the most basic configuration is provided here.
+ *
+ * Artalk 的配置。大多数设置应当在服务端进行配置,因此这里仅提供最基本的配置。
+ *
+ * @see https://artalk.js.org/
+ */
+ artalk?: {
+ /**
+ * The server URL of Artalk.
+ *
+ * Artalk 的服务端地址。
+ *
+ * @see https://artalk.js.org/en/guide/frontend/config.html#server
+ */
+ serverURL: string;
+ /**
+ * Language setting of Artalk.
+ *
+ * 语言设置
+ *
+ * @default siteConfig.lang
+ * @see https://artalk.js.org/en/guide/frontend/config.html#locale
+ */
+ locale?: string;
+ };
};
src/config.ts
@@ -199,4 +199,8 @@ export const commentConfig: CommentConfig = {
pageSize: 10,
reaction: false,
},
+ artalk: {
+ serverURL: 'https://artalk.yourdomain.com',
+ // locale: 'en', // Optional, default is site language.
+ },
};
package.json
@@ -33,6 +33,7 @@
"@swup/scroll-plugin": "^3.3.2",
"@tailwindcss/vite": "^4.1.2",
"@waline/client": "^3.5.6",
+ "artalk": "^2.9.1",
"astro": "^5.6.1",
"astro-compress": "2.3.5",
"astro-icon": "^1.1.5",