mirror of
https://codeberg.org/HPCesia/AstralHalo.git
synced 2025-04-06 17:14:27 +08:00
feat(comment): supports artalk
This commit is contained in:
parent
1a6cd77bf8
commit
01a23952ac
@ -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",
|
||||
|
@ -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 />;
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
@ -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`
|
||||
|
73
src/components/aside/recent-comments/Artalk.astro
Normal file
73
src/components/aside/recent-comments/Artalk.astro
Normal file
@ -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>
|
@ -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',
|
||||
|
42
src/components/comment/Artalk.astro
Normal file
42
src/components/comment/Artalk.astro
Normal file
@ -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>
|
@ -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.
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user