From 19540bd6d790b9bbd2225a6f197156e39cad9737 Mon Sep 17 00:00:00 2001 From: qwqcode Date: Tue, 17 Sep 2024 21:11:15 +0800 Subject: [PATCH] docs(i18n): add English translations --- Makefile | 6 +- README.en.md | 54 +- docs/docs/.vitepress/config/en.ts | 42 +- docs/docs/.vitepress/config/shared.ts | 7 +- docs/docs/.vitepress/config/zh.ts | 14 - docs/docs/en/develop/compatibility.md | 18 + docs/docs/en/develop/contributing.md | 3 + docs/docs/en/develop/event.md | 50 ++ docs/docs/en/develop/fe-api.md | 195 +++++++ docs/docs/en/develop/import-blog.md | 175 ++++++ docs/docs/en/develop/import-framework.md | 225 ++++++++ docs/docs/en/develop/index.md | 39 ++ docs/docs/en/develop/plugin.md | 130 +++++ docs/docs/en/guide/about.md | 3 + docs/docs/en/guide/backend/admin_notify.md | 403 ++++++++++++++ docs/docs/en/guide/backend/captcha.md | 159 ++++++ docs/docs/en/guide/backend/config.md | 360 ++++++++++++ docs/docs/en/guide/backend/daemon.md | 144 +++++ docs/docs/en/guide/backend/docker.md | 101 ++++ docs/docs/en/guide/backend/email.md | 325 +++++++++++ docs/docs/en/guide/backend/img-upload.md | 114 ++++ docs/docs/en/guide/backend/moderator.md | 118 ++++ docs/docs/en/guide/backend/multi-site.md | 86 +++ docs/docs/en/guide/backend/relative-path.md | 53 ++ docs/docs/en/guide/backend/reverse-proxy.md | 123 +++++ docs/docs/en/guide/backend/update.md | 25 + docs/docs/en/guide/cases.md | 12 + docs/docs/en/guide/deploy.md | 2 +- docs/docs/en/guide/env.md | 350 ++++++++++++ docs/docs/en/guide/extras.md | 3 + docs/docs/en/guide/frontend/artalk-lite.md | 13 + docs/docs/en/guide/frontend/auth.md | 75 +++ docs/docs/en/guide/frontend/config.md | 520 ++++++++++++++++++ docs/docs/en/guide/frontend/emoticons.md | 180 ++++++ docs/docs/en/guide/frontend/i18n.md | 72 +++ docs/docs/en/guide/frontend/img-lazy-load.md | 55 ++ docs/docs/en/guide/frontend/ip-region.md | 46 ++ docs/docs/en/guide/frontend/latex.md | 41 ++ docs/docs/en/guide/frontend/lightbox.md | 121 ++++ docs/docs/en/guide/frontend/pv.md | 81 +++ docs/docs/en/guide/frontend/sidebar.md | 45 ++ docs/docs/en/guide/intro.md | 54 +- docs/docs/en/guide/security.md | 3 + docs/docs/en/guide/transfer.md | 214 +++++++ docs/docs/{ => zh}/develop/api-old.md | 0 docs/docs/{ => zh}/develop/api.md | 0 docs/docs/{ => zh}/develop/compatibility.md | 0 docs/docs/{ => zh}/develop/contributing.md | 0 docs/docs/{ => zh}/develop/event.md | 0 docs/docs/{ => zh}/develop/fe-api.md | 0 docs/docs/{ => zh}/develop/import-blog.md | 0 .../docs/{ => zh}/develop/import-framework.md | 0 docs/docs/{ => zh}/develop/index.md | 0 docs/docs/{ => zh}/develop/plugin.md | 0 docs/docs/{ => zh}/develop/plugs.md | 0 docs/docs/{ => zh}/guide/about.md | 0 .../{ => zh}/guide/backend/admin_notify.md | 0 docs/docs/{ => zh}/guide/backend/build.md | 0 docs/docs/{ => zh}/guide/backend/captcha.md | 4 +- docs/docs/{ => zh}/guide/backend/config.md | 0 docs/docs/{ => zh}/guide/backend/daemon.md | 0 docs/docs/{ => zh}/guide/backend/data.md | 0 docs/docs/{ => zh}/guide/backend/docker.md | 0 docs/docs/{ => zh}/guide/backend/email.md | 0 .../docs/{ => zh}/guide/backend/fe-control.md | 0 .../docs/{ => zh}/guide/backend/img-upload.md | 0 docs/docs/{ => zh}/guide/backend/install.md | 0 docs/docs/{ => zh}/guide/backend/moderator.md | 0 .../docs/{ => zh}/guide/backend/multi-site.md | 0 docs/docs/{ => zh}/guide/backend/notify.md | 0 .../{ => zh}/guide/backend/relative-path.md | 0 .../{ => zh}/guide/backend/reverse-proxy.md | 0 docs/docs/{ => zh}/guide/backend/update.md | 0 docs/docs/{ => zh}/guide/cases.md | 0 docs/docs/{ => zh}/guide/deploy.md | 0 docs/docs/{ => zh}/guide/env.md | 0 docs/docs/{ => zh}/guide/extras.md | 0 .../{ => zh}/guide/frontend/artalk-lite.md | 0 docs/docs/{ => zh}/guide/frontend/auth.md | 14 +- docs/docs/{ => zh}/guide/frontend/config.md | 0 .../docs/{ => zh}/guide/frontend/emoticons.md | 0 docs/docs/{ => zh}/guide/frontend/i18n.md | 0 .../{ => zh}/guide/frontend/img-lazy-load.md | 0 .../{ => zh}/guide/frontend/import-blog.md | 0 .../guide/frontend/import-framework.md | 0 docs/docs/{ => zh}/guide/frontend/install.md | 0 .../docs/{ => zh}/guide/frontend/ip-region.md | 0 docs/docs/{ => zh}/guide/frontend/latex.md | 0 docs/docs/{ => zh}/guide/frontend/lightbox.md | 0 docs/docs/{ => zh}/guide/frontend/pv.md | 0 docs/docs/{ => zh}/guide/frontend/sidebar.md | 0 docs/docs/{ => zh}/guide/intro.md | 0 docs/docs/{ => zh}/guide/security.md | 0 docs/docs/{ => zh}/guide/transfer.md | 0 docs/docs/{ => zh}/index.md | 0 docs/landing/scripts/update-readme.ts | 35 +- 96 files changed, 4785 insertions(+), 127 deletions(-) create mode 100644 docs/docs/en/develop/compatibility.md create mode 100644 docs/docs/en/develop/contributing.md create mode 100644 docs/docs/en/develop/event.md create mode 100644 docs/docs/en/develop/fe-api.md create mode 100644 docs/docs/en/develop/import-blog.md create mode 100644 docs/docs/en/develop/import-framework.md create mode 100644 docs/docs/en/develop/index.md create mode 100644 docs/docs/en/develop/plugin.md create mode 100644 docs/docs/en/guide/about.md create mode 100644 docs/docs/en/guide/backend/admin_notify.md create mode 100644 docs/docs/en/guide/backend/captcha.md create mode 100644 docs/docs/en/guide/backend/config.md create mode 100644 docs/docs/en/guide/backend/daemon.md create mode 100644 docs/docs/en/guide/backend/docker.md create mode 100644 docs/docs/en/guide/backend/email.md create mode 100644 docs/docs/en/guide/backend/img-upload.md create mode 100644 docs/docs/en/guide/backend/moderator.md create mode 100644 docs/docs/en/guide/backend/multi-site.md create mode 100644 docs/docs/en/guide/backend/relative-path.md create mode 100644 docs/docs/en/guide/backend/reverse-proxy.md create mode 100644 docs/docs/en/guide/backend/update.md create mode 100644 docs/docs/en/guide/cases.md create mode 100644 docs/docs/en/guide/env.md create mode 100644 docs/docs/en/guide/extras.md create mode 100644 docs/docs/en/guide/frontend/artalk-lite.md create mode 100644 docs/docs/en/guide/frontend/auth.md create mode 100644 docs/docs/en/guide/frontend/config.md create mode 100644 docs/docs/en/guide/frontend/emoticons.md create mode 100644 docs/docs/en/guide/frontend/i18n.md create mode 100644 docs/docs/en/guide/frontend/img-lazy-load.md create mode 100644 docs/docs/en/guide/frontend/ip-region.md create mode 100644 docs/docs/en/guide/frontend/latex.md create mode 100644 docs/docs/en/guide/frontend/lightbox.md create mode 100644 docs/docs/en/guide/frontend/pv.md create mode 100644 docs/docs/en/guide/frontend/sidebar.md create mode 100644 docs/docs/en/guide/security.md create mode 100644 docs/docs/en/guide/transfer.md rename docs/docs/{ => zh}/develop/api-old.md (100%) rename docs/docs/{ => zh}/develop/api.md (100%) rename docs/docs/{ => zh}/develop/compatibility.md (100%) rename docs/docs/{ => zh}/develop/contributing.md (100%) rename docs/docs/{ => zh}/develop/event.md (100%) rename docs/docs/{ => zh}/develop/fe-api.md (100%) rename docs/docs/{ => zh}/develop/import-blog.md (100%) rename docs/docs/{ => zh}/develop/import-framework.md (100%) rename docs/docs/{ => zh}/develop/index.md (100%) rename docs/docs/{ => zh}/develop/plugin.md (100%) rename docs/docs/{ => zh}/develop/plugs.md (100%) rename docs/docs/{ => zh}/guide/about.md (100%) rename docs/docs/{ => zh}/guide/backend/admin_notify.md (100%) rename docs/docs/{ => zh}/guide/backend/build.md (100%) rename docs/docs/{ => zh}/guide/backend/captcha.md (97%) rename docs/docs/{ => zh}/guide/backend/config.md (100%) rename docs/docs/{ => zh}/guide/backend/daemon.md (100%) rename docs/docs/{ => zh}/guide/backend/data.md (100%) rename docs/docs/{ => zh}/guide/backend/docker.md (100%) rename docs/docs/{ => zh}/guide/backend/email.md (100%) rename docs/docs/{ => zh}/guide/backend/fe-control.md (100%) rename docs/docs/{ => zh}/guide/backend/img-upload.md (100%) rename docs/docs/{ => zh}/guide/backend/install.md (100%) rename docs/docs/{ => zh}/guide/backend/moderator.md (100%) rename docs/docs/{ => zh}/guide/backend/multi-site.md (100%) rename docs/docs/{ => zh}/guide/backend/notify.md (100%) rename docs/docs/{ => zh}/guide/backend/relative-path.md (100%) rename docs/docs/{ => zh}/guide/backend/reverse-proxy.md (100%) rename docs/docs/{ => zh}/guide/backend/update.md (100%) rename docs/docs/{ => zh}/guide/cases.md (100%) rename docs/docs/{ => zh}/guide/deploy.md (100%) rename docs/docs/{ => zh}/guide/env.md (100%) rename docs/docs/{ => zh}/guide/extras.md (100%) rename docs/docs/{ => zh}/guide/frontend/artalk-lite.md (100%) rename docs/docs/{ => zh}/guide/frontend/auth.md (92%) rename docs/docs/{ => zh}/guide/frontend/config.md (100%) rename docs/docs/{ => zh}/guide/frontend/emoticons.md (100%) rename docs/docs/{ => zh}/guide/frontend/i18n.md (100%) rename docs/docs/{ => zh}/guide/frontend/img-lazy-load.md (100%) rename docs/docs/{ => zh}/guide/frontend/import-blog.md (100%) rename docs/docs/{ => zh}/guide/frontend/import-framework.md (100%) rename docs/docs/{ => zh}/guide/frontend/install.md (100%) rename docs/docs/{ => zh}/guide/frontend/ip-region.md (100%) rename docs/docs/{ => zh}/guide/frontend/latex.md (100%) rename docs/docs/{ => zh}/guide/frontend/lightbox.md (100%) rename docs/docs/{ => zh}/guide/frontend/pv.md (100%) rename docs/docs/{ => zh}/guide/frontend/sidebar.md (100%) rename docs/docs/{ => zh}/guide/intro.md (100%) rename docs/docs/{ => zh}/guide/security.md (100%) rename docs/docs/{ => zh}/guide/transfer.md (100%) rename docs/docs/{ => zh}/index.md (100%) diff --git a/Makefile b/Makefile index 9246663b9..09236efa9 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,11 @@ update-conf: go generate ./internal/config update-conf-docs: - go run ./internal/config/meta/gen --format markdown --locale zh-CN -o ./docs/docs/guide/env.md + go run ./internal/config/meta/gen --format markdown --locale en -o ./docs/docs/en/guide/env.md + go run ./internal/config/meta/gen --format markdown --locale zh-CN -o ./docs/docs/zh/guide/env.md + +update-docs-features: + pnpm -F docs-landing update:readme update-swagger: go install github.com/swaggo/swag/cmd/swag@latest diff --git a/README.en.md b/README.en.md index 143dc7a7c..47f38e7d1 100644 --- a/README.en.md +++ b/README.en.md @@ -27,38 +27,38 @@ * [Sidebar](https://artalk.js.org/guide/frontend/sidebar.html): Quick management, intuitive browsing -* [Social Login](https://artalk.js.org/guide/frontend/auth.html): Quick login via social accounts -* [Email Notification](https://artalk.js.org/guide/backend/email.html): Multiple sending methods, email templates -* [Multi-channel Push](https://artalk.js.org/guide/backend/admin_notify.html): Multiple push methods, notification templates -* [In-site Notifications](https://artalk.js.org/guide/frontend/sidebar.html): Red dot marking, mention list -* [CAPTCHA](https://artalk.js.org/guide/backend/captcha.html): Multiple verification types, frequency limitation +* [Social Login](https://artalk.js.org/guide/frontend/auth.html): Fast login via social accounts +* [Email Notification](https://artalk.js.org/guide/backend/email.html): Various sending methods, email templates +* [Diverse Push](https://artalk.js.org/guide/backend/admin_notify.html): Multiple push methods, notification templates +* [Site Notification](https://artalk.js.org/guide/frontend/sidebar.html): Red dot marks, mention list +* [Captcha](https://artalk.js.org/guide/backend/captcha.html): Various verification types, frequency limits * [Comment Moderation](https://artalk.js.org/guide/backend/moderator.html): Content detection, spam interception -* [Image Upload](https://artalk.js.org/guide/backend/img-upload.html): Custom upload, support for image hosting -* [Markdown](https://artalk.js.org/guide/intro.html): Support Markdown syntax -* [Emoticons](https://artalk.js.org/guide/frontend/emoticons.html): Compatible with OwO, quick integration -* [Multi-site](https://artalk.js.org/guide/backend/multi-site.html): Site isolation, centralized management +* [Image Upload](https://artalk.js.org/guide/backend/img-upload.html): Custom upload, supports image hosting +* [Markdown](https://artalk.js.org/guide/intro.html): Supports Markdown syntax +* [Emoji Pack](https://artalk.js.org/guide/frontend/emoticons.html): Compatible with OwO, quick integration +* [Multi-Site](https://artalk.js.org/guide/backend/multi-site.html): Site isolation, centralized management * [Admin](https://artalk.js.org/guide/backend/multi-site.html): Password verification, badge identification -* [Page Management](https://artalk.js.org/guide/frontend/sidebar.html): Quick view, one-click title jump -* [Page Views Statistics](https://artalk.js.org/guide/frontend/pv.html): Easily track page views -* [Hierarchy](https://artalk.js.org/guide/frontend/config.html#nestmax): Nested paginated lists, scroll loading +* [Page Management](https://artalk.js.org/guide/frontend/sidebar.html): Quick view, one-click title navigation +* [Page View Statistics](https://artalk.js.org/guide/frontend/pv.html): Easily track page views +* [Hierarchical Structure](https://artalk.js.org/guide/frontend/config.html#nestmax): Nested paginated list, infinite scroll * [Comment Voting](https://artalk.js.org/guide/frontend/config.html#vote): Upvote or downvote comments -* [Comment Sorting](https://artalk.js.org/guide/frontend/config.html#listsort): Multiple sorting options, freedom to choose -* [Comment Search](https://artalk.js.org/guide/frontend/sidebar.html): Quickly search comment content +* [Comment Sorting](https://artalk.js.org/guide/frontend/config.html#listsort): Various sorting options, freely selectable +* [Comment Search](https://artalk.js.org/guide/frontend/sidebar.html): Quick comment content search * [Comment Pinning](https://artalk.js.org/guide/frontend/sidebar.html): Pin important messages -* [Author-only View](https://artalk.js.org/guide/frontend/config.html): Show only comments from the author -* [Comment Jumping](https://artalk.js.org/guide/intro.html): Quickly jump to referenced comments -* [Auto Save](https://artalk.js.org/guide/frontend/config.html): Content input auto-saving -* [IP Geolocation](https://artalk.js.org/guide/frontend/ip-region.html): User IP location display +* [View Author Only](https://artalk.js.org/guide/frontend/config.html): Show only the author's comments +* [Comment Jump](https://artalk.js.org/guide/intro.html): Quickly jump to quoted comment +* [Auto Save](https://artalk.js.org/guide/frontend/config.html): Content loss prevention +* [IP Region](https://artalk.js.org/guide/frontend/ip-region.html): Display user's IP region * [Data Migration](https://artalk.js.org/guide/transfer.html): Free migration, quick backup -* [Image Lightbox](https://artalk.js.org/guide/frontend/lightbox.html): Quickly integrate image lightbox -* [Image Lazy Loading](https://artalk.js.org/guide/frontend/img-lazy-load.html): Delay loading images, optimize experience -* [Latex](https://artalk.js.org/guide/frontend/latex.html): Latex formula parsing integration -* [Dark Mode](https://artalk.js.org/guide/frontend/config.html#darkmode): Dark mode switching -* [Extension Plugins](https://artalk.js.org/develop/): Create more possibilities -* [Multi-language](https://artalk.js.org/guide/frontend/i18n.html): Multi-language switching -* [Command Line](https://artalk.js.org/guide/backend/config.html): Command line operation management capability -* [API Documentation](https://artalk.js.org/develop/): Provides OpenAPI format documentation -* [Program Upgrade](https://artalk.js.org/guide/backend/update.html): Version detection, one-click upgrade +* [Image Lightbox](https://artalk.js.org/guide/frontend/lightbox.html): Quick integration of image lightbox +* [Image Lazy Load](https://artalk.js.org/guide/frontend/img-lazy-load.html): Lazy load images, optimize experience +* [Latex](https://artalk.js.org/guide/frontend/latex.html): Integrate Latex formula parsing +* [Night Mode](https://artalk.js.org/guide/frontend/config.html#darkmode): Switch to night mode +* [Extension Plugin](https://artalk.js.org/develop/plugin.html): Create more possibilities +* [Multi-Language](https://artalk.js.org/guide/frontend/i18n.html): Switch between multiple languages +* [Command Line](https://artalk.js.org/guide/backend/config.html): Command line operation management +* [API Documentation](https://artalk.js.org/http-api.html): Provides OpenAPI format documentation +* [Program Upgrade](https://artalk.js.org/guide/backend/update.html): Version check, one-click upgrade diff --git a/docs/docs/.vitepress/config/en.ts b/docs/docs/.vitepress/config/en.ts index 6d6c569ce..59e80497c 100644 --- a/docs/docs/.vitepress/config/en.ts +++ b/docs/docs/.vitepress/config/en.ts @@ -27,7 +27,7 @@ export const en = defineConfig({ { text: 'Comment Moderation', link: '/en/guide/backend/moderator.md' }, { text: 'Captcha', link: '/en/guide/backend/captcha.md' }, { text: 'Image Upload', link: '/en/guide/backend/img-upload.md' }, - { text: 'Accounts and Multi-site', link: '/en/guide/backend/multi-site.md' }, + { text: 'Admins and Multi-Site', link: '/en/guide/backend/multi-site.md' }, { text: 'Resolve Relative Path', link: '/en/guide/backend/relative-path.md' }, ], }, @@ -41,7 +41,7 @@ export const en = defineConfig({ { text: 'Image Lightbox', link: '/en/guide/frontend/lightbox.md' }, { text: 'Image Lazy Load', link: '/en/guide/frontend/img-lazy-load.md' }, { text: 'IP Region', link: '/en/guide/frontend/ip-region.md' }, - { text: 'Multi-language', link: '/en/guide/frontend/i18n.md' }, + { text: 'Localization', link: '/en/guide/frontend/i18n.md' }, { text: 'Development Documentation', link: '/en/develop/index.md' }, ], }, @@ -56,32 +56,29 @@ export const en = defineConfig({ }, { text: 'Deployment Instructions', - collapsed: true, + collapsed: false, items: [ - { text: 'Daemon', link: '/en/guide/backend/daemon.md' }, + { text: 'Daemon Process', link: '/en/guide/backend/daemon.md' }, { text: 'Reverse Proxy', link: '/en/guide/backend/reverse-proxy.md' }, - { text: 'Build', link: '/en/develop/contributing.md' }, + { + text: 'Compile Source', + link: 'https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md', + }, { text: 'Program Upgrade', link: '/en/guide/backend/update.md' }, { text: 'Docker', link: '/en/guide/backend/docker.md' }, ], }, - { - text: 'More Content', - collapsed: true, - items: [ - { text: 'Security', link: '/en/guide/security.md' }, - { text: 'Additional Reading', link: '/en/guide/extras.md' }, - { text: 'Case Studies', link: '/en/guide/cases.md' }, - { text: 'About Us', link: '/en/guide/about.md' }, - ], - }, ], '/en/develop/': [ { text: 'Development Documentation', items: [ { text: 'Development Instructions', link: '/en/develop/index.md' }, - { text: 'Contribution Guide', link: '/en/develop/contributing.md' }, + { + text: 'Contribution Guide', + link: 'https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md', + target: '_blank', + }, { text: 'Import to Blog', link: '/en/develop/import-blog.md' }, { text: 'Import to Framework', link: '/en/develop/import-framework.md' }, { text: 'Frontend API', link: '/en/develop/fe-api.md' }, @@ -114,23 +111,10 @@ export const en = defineConfig({ text: 'Migration', link: '/en/guide/transfer', }, - { - text: 'Cases', - link: '/en/guide/cases', - }, { text: 'Development', link: '/en/develop/', }, - { - text: 'Links', - items: [ - { - text: 'Code Repository', - link: 'https://github.com/ArtalkJS/Artalk', - }, - ], - }, ], editLink: { diff --git a/docs/docs/.vitepress/config/shared.ts b/docs/docs/.vitepress/config/shared.ts index e584788b8..02c4ecc74 100644 --- a/docs/docs/.vitepress/config/shared.ts +++ b/docs/docs/.vitepress/config/shared.ts @@ -5,10 +5,9 @@ import * as Version from '../../code/ArtalkVersion.json' export const shared = defineConfig({ title: 'Artalk', - // TODO: Uncomment after move default language to subfolder - // rewrites: { - // 'zh/:rest*': ':rest*', - // }, + rewrites: { + 'zh/:rest*': ':rest*', + }, /* prettier-ignore */ head: [ diff --git a/docs/docs/.vitepress/config/zh.ts b/docs/docs/.vitepress/config/zh.ts index e229eb4c1..fa1ea3340 100644 --- a/docs/docs/.vitepress/config/zh.ts +++ b/docs/docs/.vitepress/config/zh.ts @@ -123,20 +123,6 @@ export const zh = defineConfig({ text: '开发', link: '/develop/', }, - // NavbarGroup - { - text: '传送', - items: [ - { - text: '代码仓库', - link: 'https://github.com/ArtalkJS/Artalk', - }, - // { - // text: "文档镜像 (国内)", - // link: "https://artalk-docs.qwqaq.com", - // }, - ], - }, ], editLink: { diff --git a/docs/docs/en/develop/compatibility.md b/docs/docs/en/develop/compatibility.md new file mode 100644 index 000000000..5e05af09d --- /dev/null +++ b/docs/docs/en/develop/compatibility.md @@ -0,0 +1,18 @@ +# Compatibility + +## Browser Compatibility + +The Artalk client production environment code is built using esbuild with a target of `es2015`. However, please note that the build process only handles syntax transpilation to comply with the `es2015` standard and does not address API compatibility (no polyfills are included). + +If your project needs to support older browsers and devices, consider including global polyfills in your bundled application. We recommend using the [Polyfill.io](https://polyfill.io/) service, which dynamically returns the necessary polyfills based on the user's User-Agent. Alternatively, you can manually add polyfills using [core-js](https://github.com/zloirock/core-js) or [Babel](https://babeljs.io/). + +Here is a list of modern features used by Artalk: + +- [All ECMAScript 2015 (ES6) features](https://compat-table.github.io/compat-table/es6/) +- [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) +- [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) +- [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) + +## Server Compatibility + +The Artalk server program is developed in Golang and supports operating systems such as Linux, Windows, and macOS. The current Golang version for Artalk can be found in the [go.mod](https://github.com/ArtalkJS/Artalk/blob/master/go.mod#L3). For the minimum operating system requirements for Golang, refer to the [Go Wiki](https://go.dev/wiki/MinimumRequirements). diff --git a/docs/docs/en/develop/contributing.md b/docs/docs/en/develop/contributing.md new file mode 100644 index 000000000..8ade7bff2 --- /dev/null +++ b/docs/docs/en/develop/contributing.md @@ -0,0 +1,3 @@ + diff --git a/docs/docs/en/develop/event.md b/docs/docs/en/develop/event.md new file mode 100644 index 000000000..05d1dfd9f --- /dev/null +++ b/docs/docs/en/develop/event.md @@ -0,0 +1,50 @@ +# Frontend Event + +## Basic Events + +| Event Name | Description | +| ------------------- | ------------------------------- | +| `created` | After initialization | +| `mounted` | After data loading | +| `updated` | After data update | +| `unmounted` | After destruction | +| `list-fetch` | During comment list request | +| `list-fetched` | After comment list request | +| `list-load` | Before comment loading | +| `list-loaded` | After comment loading | +| `list-failed` | When comment loading fails | +| `list-goto-first` | When comment list resets | +| `list-reach-bottom` | When comment list reaches bottom| +| `comment-inserted` | After comment insertion | +| `comment-updated` | After comment update | +| `comment-deleted` | After comment deletion | +| `comment-rendered` | After comment node rendering | +| `notifies-updated` | When unread messages change | +| `list-goto` | During comment jump | +| `page-loaded` | After page data update | +| `editor-submit` | When editor submits | +| `editor-submitted` | After editor submission | +| `user-changed` | When local user data changes | +| `sidebar-show` | When sidebar is shown | +| `sidebar-hide` | When sidebar is hidden | + +Event declaration code: [@ArtalkJS/Artalk - src/types/event.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/event.ts) + +## Adding Event Listeners + +```js +artalk.on('list-loaded', () => { + alert('Comments have been loaded') +}) +``` + +## Removing Event Listeners + +```js +let foo = function () { + /* do something */ +} + +artalk.on('list-loaded', foo) +artalk.off('list-loaded', foo) +``` diff --git a/docs/docs/en/develop/fe-api.md b/docs/docs/en/develop/fe-api.md new file mode 100644 index 000000000..b35be57fe --- /dev/null +++ b/docs/docs/en/develop/fe-api.md @@ -0,0 +1,195 @@ +# Frontend API + +## Install Dependencies + +Use your preferred package manager to install Artalk: + +```bash +pnpm add artalk +# or using npm +npm install artalk +``` + +## Create Instance `init` + +Calling this function creates and returns an instantiated Artalk object for subsequent operations. + + + +```js +import Artalk from 'artalk' + +const artalk = Artalk.init({ + el: '#Comments', + pageKey: '/post/1', + pageTitle: 'About Introducing Artalk', + server: 'http://your_domain:8080', + site: 'Artalk Blog', +}) +``` + + + +Calling this function will asynchronously send requests to the backend to: + +1. Fetch frontend configuration +2. Fetch comment list + +The `mounted` event is triggered after configuration and plugins are loaded. + +The `list-loaded` event is triggered after the comment list is loaded. + +> Note: The frontend UI configuration may be overridden. See: [UI Configuration](../guide/frontend/config.md). + +## Release Resources `destroy` + +Destroy the Artalk instance to release resources. + +```js +const artalk = Artalk.init({ ... }) + +artalk.destroy() +``` + +Calling this function triggers the `unmounted` event. Releasing resources involves deleting DOM nodes mounted by Artalk and removing Artalk event listeners. After this function completes, the Artalk instance will no longer be usable. + +In frameworks like Vue/React, make sure to call this function when the component is destroyed to prevent memory leaks: + +```ts +import { onUnmounted } from 'vue' + +onUnmounted(() => { + artalk.destroy() +}) +``` + +## Update Configuration `update` + +Modify the current Artalk configuration. + +```js +const artalk = Artalk.init({ ... }) + +artalk.update({ + // new configuration... +}) +``` + +Calling this function will trigger the `updated` event. + +Updating the configuration will not automatically refresh the comment list. You can continue to call the `artalk.reload()` function as needed. + +Note that this function is a member method of an instantiated object, not a global function. + +Frontend configuration reference: [Frontend Configuration](../guide/frontend/config.md) + +## Reload `reload` + +Reload the Artalk comment list data from the backend. + +```js +const artalk = Artalk.init({ ... }) + +artalk.reload() +``` + +The `list-load` event is triggered before loading the list, and the `list-loaded` event is triggered after the loading is complete. + +## Listen to Events `on` + +Add Artalk event listeners. + +```js +const artalk = Artalk.init({ ... }) + +artalk.on('list-loaded', (comments) => { + // 'comments' contains all comments on the current page (not just the comments fetched in this request) + console.log('Comments have been loaded: ', comments) +}) +``` + +Refer to: [Frontend Event](./event.md). + +## Remove Event Listeners `off` + +Remove Artalk event listeners. + +```js +const artalk = Artalk.init({ ... }) + +const handler = () => { + alert('Comments have been loaded') +} + +artalk.on('list-loaded', handler) +artalk.off('list-loaded', handler) +``` + +## Trigger Events `trigger` + +Trigger Artalk events. + +```js +const artalk = Artalk.init({ ... }) + +artalk.trigger('list-loaded', [...]) +``` + +## Load Plugins `use` + +Load plugins using the `Artalk.use` function. Note that this function is a global function, not a method of an instantiated object. Plugins loaded through this function will be effective for all Artalk instances. + +```js +import Artalk from 'artalk' + +Artalk.use((ctx) => { + ctx.editor.setContent("Hello World") +}) + +const artalk = Artalk.init({ ... }) +``` + +See: [Plugin Development](./plugin.md) + +## Dark Mode `setDarkMode` + +Toggle dark mode, which can be called in conjunction with the blog theme, such as when a user clicks a dark mode toggle button. + +```js +const artalk = Artalk.init({ ... }) + +artalk.setDarkMode(true) +``` + +You can also set the initial dark mode by passing the `darkMode` parameter when calling `Artalk.init`. + +```js +const artalk = Artalk.init({ + // ...other configurations + darkMode: 'auto', +}) +``` + +## View Count Widget `loadCountWidget` + +See: [Page View Statistics](../guide/frontend/pv.md) + +## Get Configuration `getConf` + +Get the current Artalk configuration. + +```js +const artalk = Artalk.init({ ... }) + +const conf = artalk.getConf() +``` + +## Get Mounted Element `getEl` + +Get the DOM element that Artalk is currently mounted to. + +```js +const artalk = Artalk.init({ ... }) + +const el = artalk.getEl() +``` diff --git a/docs/docs/en/develop/import-blog.md b/docs/docs/en/develop/import-blog.md new file mode 100644 index 000000000..6c4b9f723 --- /dev/null +++ b/docs/docs/en/develop/import-blog.md @@ -0,0 +1,175 @@ +# Import to Blog + +## General Method + +<<< @/code/quick-start/cdn.html + +### When to execute `Artalk.init({})`? + +- You can include JS and CSS resources anywhere, but ensure the JS is included before executing `Artalk.init({})`. +- Ensure `
` is present in the page before executing `Artalk.init({ el: '#artalk' })`. + +## Hugo + +Create the template file `/themes/YOUR_THEME/layouts/partials/comment/artalk.html`: + + + +```html + + + + +
+ + +``` + + + +Add the following to the appropriate place in your article template `/themes/YOUR_THEME/layouts/_default/single.html`: + +```html +
{{- partial "comment/artalk" . -}}
+``` + +Modify the Hugo configuration file: + +::: code-group + +```toml [config.toml] +[params.artalk] +server = 'https://artalk.example.org' +site = 'Your Site Name' +``` + +```yaml [config.yaml] +params: + artalk: + server: 'https://artalk.example.org' + site: 'Your Site Name' +``` + +::: + +## Hexo + +Create `/themes/YOUR_THEME/layout/comment/artalk.ejs`: + +```html + + + +
+ + +``` + +Modify the article template file, for example `/themes/YOUR_THEME/layout/post.ejs`: + +```html +
<%- partial('comment/artalk') %>
+``` + +Edit the theme configuration `/themes/YOUR_THEME/_config.yml`: + +```yaml +comment: + artalk: + site: 'Your Site Name' + server: 'https://artalk.example.org' +``` + +::: tip + +For NexT theme, you can install the [Artalk plugin for Hexo NexT theme](https://github.com/leirock/hexo-next-artalk) + +::: + +## VitePress + +Refer to: [docs/.vitepress](https://github.com/ArtalkJS/Artalk/tree/master/docs/docs/.vitepress) + +- Modify `config.ts` to include CSS resources +- Create `theme/Artalk.vue` component +- Register the component in `theme/index.ts` +- Use the component in `theme/Layout.vue` + +Sample code: [docs/.vitepress/theme/Artalk.vue](https://github.com/ArtalkJS/Artalk/blob/master/docs/docs/.vitepress/theme/Artalk.vue) + +## VuePress + +(To be supplemented) + +::: tip + +Refer to: [Import to Frameworks](./import-framework.md) + +::: + +## Typecho + +Modify the theme article template file, for example, `post.php`: + +```php + + + + + + + +
+ +``` + +## WordPress + +Modify the theme article template file, for example, `single.php`: + +```php + + + + + + + +
+ +``` diff --git a/docs/docs/en/develop/import-framework.md b/docs/docs/en/develop/import-framework.md new file mode 100644 index 000000000..01013a68e --- /dev/null +++ b/docs/docs/en/develop/import-framework.md @@ -0,0 +1,225 @@ +# Import to Frameworks + +## Install Artalk + +Install Artalk using a package manager. It is recommended to use [pnpm](https://pnpm.io/zh/). + +```bash +pnpm add artalk +``` + +## Vue + +::: code-group + +```vue [Vue 3] + + + +``` + +```vue [Vue 3 + Vue Router] + + + +``` + +::: + +## React + +::: code-group + +```tsx [React Hooks] +import React, { useEffect, useRef } from 'react' +import { useLocation } from 'react-router-dom' +import 'artalk/dist/Artalk.css' +import Artalk from 'artalk' + +const ArtalkComment = () => { + const container = useRef(null) + const location = useLocation() + const artalk = useRef() + + useEffect(() => { + artalk.current = Artalk.init({ + el: container.current!, + pageKey: location.pathname, + pageTitle: document.title, + server: 'http://localhost:8080', + site: 'Artalk Blog', + // ... + }) + + return () => { + artalk.current?.destroy() + } + }, [location.pathname]) + + return
+} + +export default ArtalkComment +``` + +```jsx [React Class] +import React, { createRef } from 'react' +import 'artalk/dist/Artalk.css' +import Artalk from 'artalk' + +export default class ArtalkComponent extends React.Component { + el = createRef() + artalk = null + + componentDidMount() { + this.artalk = Artalk.init({ + el: this.el.current, + pageKey: location.pathname, + pageTitle: document.title, + server: 'http://localhost:8080', + site: 'Artalk Blog', + // ... + }) + } + + componentWillUnmount() { + this.artalk?.destroy() + } + + render() { + return
+ } +} +``` + +::: + +## SolidJS + +```tsx +import { onCleanup, onMount } from 'solid-js' +import Artalk from 'artalk' +import 'artalk/dist/Artalk.css' + +const ArtalkComment = () => { + let el: HTMLDivElement + let artalk: Artalk + + onMount(() => { + artalk = Artalk.init({ + el: el, + pageKey: location.pathname, + pageTitle: document.title, + server: 'http://localhost:8080', + site: 'Artalk Blog', + // ... + }) + + onCleanup(() => { + artalk.destroy() + }) + }) + + return
+} +``` + +## Svelte + +```html + + +
+``` diff --git a/docs/docs/en/develop/index.md b/docs/docs/en/develop/index.md new file mode 100644 index 000000000..b85abddef --- /dev/null +++ b/docs/docs/en/develop/index.md @@ -0,0 +1,39 @@ +# Development Instructions + +Welcome to the official Artalk development documentation, where you will find guidelines for building Artalk plugins and themes. Should you need to set up the Artalk development environment, please refer to the [Developer Contribution Guide](./contributing.md). + +Thank you for your interest and support of Artalk. We deeply understand that the success of an open-source project relies on the contributions of every developer. Whether it is code, documentation, testing, or feedback, your participation is the driving force behind the project's continuous advancement. We sincerely invite you to join us in perfecting and enhancing Artalk. + +## Index + +- [Developer Contribution Guide](./contributing.md) ⭐️ + +**Frontend Interface** + +- [Embed in Blog](./import-blog.md) +- [Embed in Framework](./import-framework.md) +- [Frontend API Documentation](./fe-api.md) +- [Frontend Events](./event.md) +- [Frontend Configuration](../guide/frontend/config.md) + +**Plugin Development** + +- [Plugin Development](./plugin.md) +- [Plugin Development Vite Integration](https://github.com/ArtalkJS/Artalk/blob/master/ui/plugin-kit/README.md) + +**Backend Program** + +- HTTP API Documentation +- [Environment Variables](../guide/env.md) +- [Configuration Files](../guide/backend/config.md) + +**Other Content** + +- [Compatibility](../develop/compatibility.md) +- [Changelog](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md) +- [i18n Multi-language Contribution Guide](../guide/frontend/i18n.md#贡献翻译) +- [Contributor Covenant Code of Conduct](https://github.com/ArtalkJS/Artalk/blob/master/CODE_OF_CONDUCT.md) + +::: tip +Artalk is under active maintenance. Please be mindful of API version compatibility. Upgrades may include breaking changes, refer to the [Changelog](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md). +::: diff --git a/docs/docs/en/develop/plugin.md b/docs/docs/en/develop/plugin.md new file mode 100644 index 000000000..c63073483 --- /dev/null +++ b/docs/docs/en/develop/plugin.md @@ -0,0 +1,130 @@ +# Plugin Development + +## Developing with Vite + +We provide an integrated Vite plugin, enabling you to effortlessly build Artalk plugins with out-of-the-box Vite configuration. + +Reference Documentation: [@artalk/plugin-kit](https://github.com/ArtalkJS/Artalk/blob/master/ui/plugin-kit/README.md). + +Additionally, we offer a template repository that you can fork to develop your plugins: [artalk-plugin-sample](https://github.com/ArtalkJS/artalk-plugin-sample). + +Utilizing Vite in combination with the frontend ecosystem, you can develop Artalk plugins using any framework you prefer, such as Vue, React, Svelte, or SolidJS. + +## `Artalk.use` + +Extend Artalk's functionality using `Artalk.use`. + +```js +import Artalk from 'artalk' + +Artalk.use((ctx) => { + ctx.on('list-loaded', () => { + console.log('Comment list loaded') + ctx.getCommentNodes().forEach((node) => { + node.getEl().style.background = 'red' + }) + }) +}) + +Artalk.use((ctx) => { + let el = null + + ctx.on('mounted', () => { + el = document.createElement('div') + document.body.appendChild(el) + console.log('Artalk instance mounted') + }) + + ctx.on('unmounted', () => { + el.remove() + console.log('Artalk instance unmounted') + }) +}) + +const artalk = Artalk.init({ ... }) +``` + +Please note: + +- `Artalk.use` must be called before `Artalk.init` to take effect. +- Do not rely on the order of plugin loading; instead, listen for events to execute plugin logic. +- The `created` event is triggered once all plugins are loaded. +- The `mounted` event is triggered when the instance and configuration are fully loaded. +- The `unmounted` event is triggered when the Artalk instance is destroyed. +- The `updated` event is triggered when the configuration changes. + +Within the use function, you can access Artalk's Context object via `ctx`. + +### Configurable Plugin Options + +In TypeScript, you can define a plugin with options using `ArtalkPlugin`. + +```ts +export interface DemoPluginOptions { + foo?: string +} + +export const ArtalkDemoPlugin: ArtalkPlugin = (ctx, options = {}) => { + console.log(options.foo) +} +``` + +Pass options when calling `Artalk.use`: + +```ts +import { ArtalkDemoPlugin } from 'artalk-plugin-demo' + +Artalk.use(ArtalkDemoPlugin, { foo: 'bar' }) +``` + +## Context API + +The Context object contains Artalk's contextual information. + +| Member | Description | +| -------------------- | ----------------------- | +| `ctx.getEl` | Get container element | +| `ctx.getConf` | Get configuration | +| `ctx.updateConf` | Update configuration | +| `ctx.watchConf` | Watch configuration | +| `ctx.setDarkMode` | Set dark mode | +| `ctx.getApi` | Get API client object | +| -- | -- | +| `ctx.fetch` | Fetch comment data | +| `ctx.reload` | Reload comment list | +| `ctx.getComments` | Get all comment data | +| `ctx.getCommentNodes`| Get all comment nodes | +| -- | -- | +| `ctx.on` | Add event listener | +| `ctx.off` | Remove event listener | +| `ctx.trigger` | Trigger event | +| -- | -- | +| `ctx.get` | Get dependency | +| `ctx.inject` | Inject dependency | + +::: warning +The Context API is currently unstable and subject to change. Please refer to the CHANGELOG when upgrading. +::: + +Reference: [@artalk/src/types/context.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/context.ts) + +Artalk includes comprehensive TypeScript type definitions, allowing you to explore the API through editor autocompletion. + +## Sample Plugins + +Below is a list of externally maintained Artalk plugins: + +| Plugin | Description | +| -------------------------------------------------------------------------------------------- | ----------------------- | +| [artalk-plugin-sample](https://github.com/ArtalkJS/artalk-plugin-sample) | Sample Plugin | +| [@artalk/plugin-katex](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-katex) | LaTeX Formula Plugin | +| [@artalk/plugin-auth](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-auth) | Auth Plugin (SolidJS) | +| [@artalk/plugin-lightbox](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-lightbox) | Basic Image Lightbox | + +Additionally, many plugins are implemented within Artalk itself, which you can reference for developing your own plugins: + +[@ArtalkJS/Artalk - src/plugins](https://github.com/ArtalkJS/Artalk/tree/master/ui/artalk/src/plugins) + +## Backend Plugin Development + +【TODO】 diff --git a/docs/docs/en/guide/about.md b/docs/docs/en/guide/about.md new file mode 100644 index 000000000..4ddd30f75 --- /dev/null +++ b/docs/docs/en/guide/about.md @@ -0,0 +1,3 @@ +# About Us + +【TODO】 diff --git a/docs/docs/en/guide/backend/admin_notify.md b/docs/docs/en/guide/backend/admin_notify.md new file mode 100644 index 000000000..e5ccd502e --- /dev/null +++ b/docs/docs/en/guide/backend/admin_notify.md @@ -0,0 +1,403 @@ +# Multi-channel Notifications + +Artalk supports sending administrator notifications through its multi-channel notification feature in various ways. + +Supported platforms include **Telegram**, **Feishu**, **DingTalk**, **Bark**, **Slack**, and **LINE**, with the ability to enable multiple methods simultaneously. + +You can modify these configurations in the settings interface of the [Dashboard](../frontend/sidebar.md#Settings) or via the [configuration file](../backend/config.md#multi-channel-notifications-admin-notify) or [environment variables](../env.md#multi-channel-notifications). + +## Configuration File + +The complete `admin_notify` configuration is as follows: + +::: details Click to reveal + +```yaml +# Multi-channel Notifications +admin_notify: + # Notification Template + notify_tpl: default + noise_mode: false + # Email notification for administrators + email: + enabled: true # Disable email notifications for administrators when using other push methods + mail_subject: '[{{site_name}}] Your article "{{page_title}}" has a new reply' + mail_tpl: '' + # Telegram + telegram: + enabled: false + api_token: '' + receivers: + - 7777777 + # Feishu + lark: + enabled: false + webhook_url: '' + # DingTalk + ding_talk: + enabled: false + token: '' + secret: '' + # Bark + bark: + enabled: false + server: http://day.app/xxxxxxx/ + # Slack + slack: + enabled: false + oauth_token: '' + receivers: + - CHANNEL_ID + # LINE + line: + enabled: false + channel_secret: '' + channel_access_token: '' + receivers: + - USER_ID_1 + - GROUP_ID_1 + # WebHook + webhook: + enabled: false + url: '' +``` + +::: + +## Email Notifications + +Send message notifications to administrators via email. + +```yaml +admin_notify: + enabled: true # Disable email notifications for administrators when using other push methods + mail_subject: '[{{site_name}}] Your article "{{page_title}}" has a new reply' + mail_tpl: '' +``` + +You can disable email notifications when using other push methods. + +Before doing this, you need to configure the global email sending functionality: [refer here](./email.md). + +### Administrator Email Template + +- The `mail_subject` configuration item is the email subject sent to the administrator. +- The `mail_tpl` configuration item specifies the email template for the administrator (fill in the email template file path). + + (If this item is empty, it will inherit the `email.mail_tpl` configuration item). + +## Telegram + +```yaml +admin_notify: + # Telegram + telegram: + enabled: true + api_token: '' + receivers: + - 7777777 +``` + +- `api_token`: The API token for the TG Bot. +- `receivers`: The numeric IDs of the message recipients, multiple recipients can be set. + +### Creating a TG Bot + +Search for `@BotFather`, reply with `/newbot`, and follow the prompts to create a new TG bot. + +![](/images/notify/tg-1.png) + +The red text is the `api_token` you need to fill in Artalk's configuration. + +Fill in the `receivers` field with the numeric IDs of the accounts that need to receive messages. You can use `@RawDataBot` to get these IDs, as shown: + +![](/images/notify/tg-2.png) + +For more details, refer to: [Bots: An introduction for developers - Telegram](https://core.telegram.org/bots) + +::: tip + +Given the complex network environment, if you need to use a proxy, configure the environment variable before starting Artalk, for example: + +```sh +export https_proxy=http://127.0.0.1:7890 +``` + +::: + +## Feishu + +```yaml +admin_notify: + # Feishu + lark: + enabled: true + webhook_url: '' +``` + +- `webhook_url`: The WebHook address obtained when creating the group bot. + +### Creating a Group Bot + +Click the plus sign at the top to create a new group: + +![](/images/notify/lark-1.png) + +Find "Group Settings" on the right, select "Group Bot", click "Add Bot", choose "Custom Bot", and follow the prompts to create it. + + + +Copy the WebHook address as shown above and modify Artalk's `webhook_url` configuration. + + + +For more details, refer to: [Feishu Help Center Documentation](https://www.feishu.cn/hc/zh-CN/articles/360024984973) + +## DingTalk + +```yaml +admin_notify: + # DingTalk + ding_talk: + enabled: true + token: '' + secret: '' +``` + +Refer to: [DingTalk Open Documentation](https://open.dingtalk.com/document/robots/custom-robot-access) + +## Bark + +```yaml +admin_notify: + # Bark + bark: + enabled: true + server: http://day.app/xxxxxxx/ +``` + +[Bark](https://github.com/Finb/Bark) is an open-source iOS app that [supports self-hosting](https://github.com/Finb/bark-server), allowing you to easily push messages to your iOS device. + +You can search and download it from the App Store and get the `server` configuration item to fill in Artalk: + + + +## Slack + +```yaml +admin_notify: + # Slack + slack: + enabled: true + oauth_token: '' + receivers: + - CHANNEL_ID +``` + +## LINE + +```yaml +admin_notify: + # LINE + line: + enabled: true + channel_secret: '' + channel_access_token: '' + receivers: + - USER_ID_1 + - GROUP_ID_1 +``` + +## Notification Template + +```yaml +admin_notify: + notify_tpl: default +``` + +The `admin_notify.notify_tpl` configuration item can be set to a custom notification template file path. The default notification template is: + +``` +@{{reply_nick}}: + +{{reply_content}} + +{{link_to_reply}} +``` + +The available variables are the same as in the email template, refer to: [Email Template](./email.md#邮件模板) + +## Notify Pending Comments `notify_pending` + +```yaml +admin_notify: + notify_pending: false +``` + +`notify_pending` is turned off by default. When set to `false`, pending comments will not send notifications. You can view all pending comments in the Dashboard. + +## Noise Mode `noise_mode` + +```yaml +admin_notify: + noise_mode: false +``` + +`noise_mode` is turned off by default. When set to `false`, only messages directed to the administrator will send notifications. For example, communication between "User A" and "User B" will not notify the administrator. + +Note: When `moderator.pending_default` is set to `true`, noise_mode is always enabled. + +## WebHook Callback + +When WebHook is enabled, a new comment will send a **POST** request with `application/json` type Body data to the specified WebHook address. + +You can write your own server-side code to handle requests from Artalk. + +**Artalk Configuration File** + +```yaml +admin_notify: + webhook: + enabled: true + url: http://localhost:8080/ +``` + +**Body Data Content** + +`application/json` type + +| Key | Description | Type | Remarks | +| ---------------- | ----------------- | ------ | ----------------------------------------- | +| `notify_subject` | Notification Title | String | Corresponds to the admin_notify.notify_subject configuration item | +| `notify_body` | Notification Content | String | Rendered according to the admin_notify.notify_tpl template | +| `comment` | Comment Content | Object | New comment data object | +| `parent_comment` | Target of Comment Reply | Object | If it's a root comment, the value is null | + +**Body Data Sample** + +```js +{ + "notify_subject": "", + "notify_body": "@TestUser:\n\nTestContent\n\nhttps://127.0.0.1/index.html?atk_comment=1057", + "comment": { + "id": 1057, + "content": "TestContent", + "user_id": 226, + "nick": "TestUser", + "email_encrypted": "654236c1e78i4c09a17c4869c9d43910", + "link": "https://qwqaq.com", + "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_4_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36", + "date": "2022-05-23 17:00:23", + "is_collapsed": false, + "is_pending": false, + "is_pinned": false, + "is_allow_reply": false, + "rid": 0, + "badge_name": "", + "badge_color": "", + "visible": true, + "vote_up": 0, + "vote_down": 0, + "page_key": "/index.html", + "page_url": "https://127.0.0.1/index.html", + "site_name": "ArtalkDocs" + }, + "parent_comment": null +} +``` + +**Node.js Express Handling Example** + +```js +const express = require('express') + +const app = express() + +app.use(express.json()) // Use JSON middleware + +app.post('/', (request, response) => { + console.log(request.body) + + const notifySubject = request.body.notify_subject + const notifyBody = request.body.notify_body + console.log(notifySubject, notifyBody) + + response.send(request.body) +}) + +app.listen(8080) +``` + +**Node.js HTTP Handling Example** + +```js +const http = require('http') + +const requestListener = (req, res) => { + // receive json request + let body = '' + req.on('data', (data) => { + body += data + }) + req.on('end', () => { + let json = '' + try { + json = JSON.parse(body) + } catch {} + + // do something with json + console.log(json) + res.end() + }) + + res.writeHead(200) + res.end('Hello, World!') +} + +const server = http.createServer(requestListener) +server.listen(8080) +``` + +**PHP Laravel Handling Example** + +```php +Route::get('/', function (Request $request) { + $data = $request->json()->all(); + $notify_subject = $data["notify_subject"]; + $notify_body = $data["notify_body"]; +}); +``` + +**Golang net/http Handling Example** + +```go +package main + +import ( + "encoding/json" + "log" + "net/http" +) + +type ArtalkNotify struct { + NotifySubject string `json:"notify_subject"` + NotifyBody string `json:"notify_body"` + Comment interface{} `json:"comment"` + ParentComment interface{} `json:"parent_comment"` +} + +func webhookHandler(rw http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(req.Body) + var notify ArtalkNotify + err := decoder.Decode(¬ify) + if err != nil { + panic(err) + } + log.Println(notify.NotifyBody) +} + +func main() { + http.HandleFunc("/webhook", webhookHandler) + log.Fatal(http.ListenAndServe(":8080", nil)) +} +``` diff --git a/docs/docs/en/guide/backend/captcha.md b/docs/docs/en/guide/backend/captcha.md new file mode 100644 index 000000000..4857e77ef --- /dev/null +++ b/docs/docs/en/guide/backend/captcha.md @@ -0,0 +1,159 @@ +# Captcha + +Artalk comes with a built-in image captcha feature, allowing you to configure operation frequency limits that activate the captcha when exceeded. + +Additionally, you can integrate various verification service providers to gain diversified verification functionality. + +Currently, Artalk supports: Turnstile, reCAPTCHA, hCaptcha, and Geetest. + +You can modify these settings in the [Dashboard](../frontend/sidebar.md#Settings) or via the [configuration file](./config.md#captcha) or [environment variables](../env.md#captcha). + +## Configuration File + +The full `captcha` configuration is as follows: + +```yaml +# Captcha +captcha: + enabled: true # Master switch + always: false # Always require captcha + captcha_type: image # Type of captcha + action_limit: 3 # Number of actions required to activate captcha + action_reset: 60 # Timeout to reset action counter (unit: s, set to -1 to never reset) + # Turnstile + # (https://www.cloudflare.com/products/turnstile/) + turnstile: + site_key: '' + secret_key: '' + # reCAPTCHA + # (https://www.google.com/recaptcha/about/) + recaptcha: + site_key: '' + secret_key: '' + # hCaptcha (https://www.hcaptcha.com/) + hcaptcha: + site_key: '' + secret_key: '' + # Geetest (https://www.geetest.com) + geetest: + captcha_id: '' + captcha_key: '' +``` + +- **always**: When set to `true`, captcha is always required. +- **captcha_type**: Type of captcha, options include: `image`, `turnstile`, `recaptcha`, `hcaptcha`, `geetest`. +- **action_limit**: The number of actions required to activate the captcha. +- **action_reset**: When the time exceeds this value, the action counter resets. Unit is seconds; set to `-1` to never reset. + +Note: When `always` is enabled, `action_limit` and `action_reset` configurations are ignored. + +## Configuration Examples + +### Example 1 + +Within a 60-second time frame, if the number of actions exceeds 3, captcha will be required: + +```yaml +captcha: + action_limit: 3 + action_reset: 60 +``` + +The counter will automatically reset after 60 seconds, allowing for 3 more actions without requiring a captcha. + +### Example 2 + +Regardless of the time frame, if the number of actions from an IP address exceeds 5, captcha will be required: + +```yaml +captcha: + action_limit: 5 + action_reset: -1 +``` + +### Example 3 + +Always require captcha, regardless of the number of actions: + +```yaml +captcha: + always: true +``` + +## Definition of Actions + +Each "comment, vote, image upload, password verification" by an IP address counts as an "action." + +## Turnstile + +[Turnstile](https://www.cloudflare.com/zh-cn/products/turnstile/) is a verification service from Cloudflare. You can obtain the `site_key` and `secret_key` from the CF dashboard, then fill in these keys in the Artalk settings and change `captcha_type` to `turnstile`. + +Illustrations: + + + + + +Corresponding configuration file: + +```yaml +captcha: + # Omit other configurations... + captcha_type: turnstile + turnstile: + site_key: '' + secret_key: '' +``` + +## reCAPTCHA + +[reCAPTCHA](https://developers.google.com/recaptcha) is a verification service from Google, and Artalk supports reCAPTCHA v3. You can obtain the `site_key` and `secret_key` from the Google developer dashboard, then fill in these keys in the Artalk settings and change `captcha_type` to `recaptcha`. + +Corresponding configuration file: + +```yaml +captcha: + # Omit other configurations... + captcha_type: recaptcha + recaptcha: + site_key: '' + secret_key: '' +``` + +Note: Accessing Google APIs from within China may require configuring a system proxy. + +Google provides test keys for reCAPTCHA: [see here](https://developers.google.com/recaptcha/docs/faq?hl=en#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do). + +## hCaptcha + +[hCaptcha](https://www.hcaptcha.com/) is a verification service. You can obtain the `site_key` and `secret_key` from its official website, then fill in these keys in the Artalk settings and change `captcha_type` to `hcaptcha`. + +Corresponding configuration file: + +```yaml +captcha: + # Omit other configurations... + captcha_type: hcaptcha + hcaptcha: + site_key: '' + secret_key: '' +``` + +hCaptcha provides test keys: [see here](https://docs.hcaptcha.com/#integration-testing-test-keys). + +## Geetest + +Artalk supports integrating [Geetest](https://www.geetest.com/adaptive-captcha) for advanced behavior verification. + +First, register an account on the Geetest website to obtain the `captcha_id` and `captcha_key`, then modify the configuration in the Artalk settings and change `captcha_type` to `geetest`. + +Corresponding configuration file: + +```yaml +captcha: + # Omit other configurations... + captcha_type: geetest + geetest: + captcha_id: '' + captcha_key: '' +``` diff --git a/docs/docs/en/guide/backend/config.md b/docs/docs/en/guide/backend/config.md new file mode 100644 index 000000000..8500f7c4f --- /dev/null +++ b/docs/docs/en/guide/backend/config.md @@ -0,0 +1,360 @@ +# Configuration File + +## Easy Configuration + +It is recommended to modify the configuration through the graphical interface in the sidebar "[Dashboard](../frontend/sidebar.md)" without manually editing the configuration file. + +## Environment Variables + +You can configure via environment variables, refer to the documentation: [Environment Variables](../env.md). + +## Specifying the Configuration File Path + +By default, Artalk uses `artalk.yml` in the working directory as the configuration file. You can specify a specific file using the `-c` parameter: + +```bash +artalk -c ./conf.yml +``` + +## Obtaining a Template Configuration File + +You can refer to a "complete configuration file": [artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/blob/master/conf/artalk.example.zh-CN.yml) + +### Generate Configuration File Using the `gen` Command + +Artalk provides the `gen` command, allowing you to quickly generate a new configuration file: + +```bash +artalk gen conf -lang zh-CN ./artalk.yml +``` + +### Download Configuration File via Command Line + +```bash +wget -O artalk.yml https://raw.githubusercontent.com/ArtalkJS/Artalk/master/conf/artalk.example.zh-CN.yml +``` + +## Encryption Key `app_key` + +Before starting Artalk, you need to configure an `app_key` for securely encrypting site content: + +```yaml +app_key: +``` + +## Language `locale` + +Set the language for Artalk. Follows the Unicode BCP 47 standard, with the default being "zh-CN" (Simplified Chinese). + +```yaml +locale: zh-CN +``` + +For details, refer to: [Multilingual](../frontend/i18n.md) + +## Database `db` + +Artalk supports connecting to various databases, including SQLite, MySQL, PostgreSQL, and SQL Server. The configurations are as follows: + +#### SQLite + +SQLite is a lightweight database that stores data in a single file, requiring no additional running programs. It is especially suitable for small sites, such as personal blogs. + +```yaml +db: + type: sqlite + file: ./data/artalk.db +``` + +#### MySQL / PostgreSQL / SQL Server + +Modify `type` to your database type: + +```yaml +db: + type: mysql # sqlite, mysql, pgsql, mssql + name: artalk # Database name + host: localhost # Address + port: 3306 # Port + user: root # Username + password: '' # Password + charset: utf8mb4 # Charset + table_prefix: '' # Table prefix (e.g., "atk_") + ssl: false # Enable SSL + prepare_stmt: true # Prepared statements +``` + +The data tables will be automatically created when Artalk starts, no additional operation is required. + +#### Database Connection String (DSN) + +If needed, you can manually configure `db.dsn` to specify the database connection string, for example: + +```yaml +db: + type: mysql + dsn: mysql://myuser:mypassword@localhost:3306/mydatabase?tls=skip-verify +``` + +For more details, refer to: [@go-sql-driver/mysql:README.md](https://github.com/go-sql-driver/mysql) + +## Server `http` + +```yaml +http: + # Request body size limit (unit: MB) + body_limit: 100 + # Proxy header name (when using CDN, fill in `X-Forwarded-For` to get the user's real IP) + proxy_header: "" +``` + +## Admin Users `admin_users` + +You need to configure administrator accounts to manage site content through the "[Dashboard](../frontend/sidebar.md)". + +Artalk supports multiple sites, allowing you to create multiple administrator accounts and assign sites to them, enabling your friends to share the same backend program. + +For details, refer to: [Admin Users × Multi-site](./multi-site.md) + +## Trusted Domains `trusted_domains` + +```yaml +trusted_domains: + - https://frontend.domainA.com + - https://frontend.domainB.com +``` + +Only the domains in the list are allowed to access the backend API, restricting cross-domain requests from external domains. + +::: tip + +You need to add the URL address of the "frontend page" to the trusted domains list. + +If it's not the default 80/443 port, include the port number, e.g., `https://example.com:8080`. + +::: + +In the sidebar [Dashboard](../frontend/sidebar.md#控制中心), under the "Site" tab - select the site and "Modify URL", fill in the site URL to achieve the same setting effect; to add multiple URLs, separate them with commas `,`. After modification, manually restart Artalk. + +The default site address `ATK_SITE_URL` configuration item will also be automatically added to the trusted domains list. + +Additionally, you can configure trusted domains via the environment variable `ATK_TRUSTED_DOMAINS` when starting, for example: + +```bash +ATK_TRUSTED_DOMAINS="https://a.com https://b.org" artalk server +``` + +Note that environment variables will override the settings in the configuration file. + +Technical details: `trusted_domains` configuration controls cross-origin requests by setting the HTTP response header `Access-Control-Allow-Origin` (refer to: [W3C Cross-Origin Resource Sharing](https://fetch.spec.whatwg.org/#http-cors-protocol) / [OWASP Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)). + +## Default Site `site_default` + +If you think you won't use the multi-site feature of Artalk, you can directly set this item to your site name, for example: + +```yaml +site_default: Artalk Official Website +``` + +Then use this site name in the frontend: + +```js +Artalk.init({ site: 'Artalk Official Website' }) +``` + +This way, you don't need to manually create the site in the sidebar [Dashboard](../frontend/sidebar.md#控制中心). + +## Frontend Configuration `frontend` + +In Artalk's configuration file `artalk.yml`, you can configure the `frontend` field to control the frontend interface, for example: + +```yaml +frontend: + placeholder: Type content... + noComment: "Silence is golden" + sendBtn: Send Comment + emoticons: 'https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json' + # ----- Omitted ------- + # Keep the same as the frontend configuration item name +``` + +A complete backend `frontend` field configuration file can be referred to: [artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/blob/master/conf/artalk.example.zh-CN.yml) + +## Email Notifications `email` + +Configure email notifications to notify the target user of replies via email. You can customize the sender name, title, template, etc. + +For details, refer to: [Backend · Email Notifications](./email.md) + +## Multi-channel Notifications `admin_notify` + +You can configure various message sending methods, such as Feishu, Telegram, etc., to notify administrators when new comments are received. + +For details, refer to: [Backend · Multi-channel Notifications](./admin_notify.md) + +## Comment Moderation `moderator` + +Configure comment moderation to automatically intercept spam comments. + +For details, refer to: [Backend · Comment Moderation](./moderator.md) + +## Captcha `captcha` + +Supports image and slide captchas to limit request frequency. + +For details, refer to: [Backend · Captcha](./captcha.md) + +## Cache `cache` + +To save memory resources, caching is disabled by default. If you have high performance requirements for your site, enable it manually. You can also connect to external cache servers, supporting Redis and Memcache. + +```yaml +cache: + enabled: true # Enable cache (default is off) + type: builtin # Supports redis, memcache, builtin (built-in cache) + expires: 30 # Cache expiration time (unit: minutes) + warm_up: false # Warm up cache on program startup + server: '' # Connect to cache server (e.g., "localhost:6379") +``` + +- **warm_up**: Cache warm-up feature. Set to `true`, it will immediately cache all database content when Artalk starts. If you have a large number of comments, this may extend the startup time. +- **type**: Cache type, defaults to `builtin`. Options: `redis`, `memcache`, `builtin`. + +Note: If you modify the database content outside the Artalk program, you need to refresh the Artalk cache to update it. + +--- + +Redis authentication and database configuration: + +```yaml +# Cache +cache: + # Omit other configurations... + redis: + network: tcp # Connection method (tcp or unix) + username: '' # Username + password: '' # Password + db: 0 # Use database 0 +``` + + + + +## Listening Address `host` + +The default HTTP port for Artalk is 23366. You can specify it in the configuration file: + +```yaml +host: '0.0.0.0' +port: 23366 +``` + +Configuring the `host` listening address to `0.0.0.0` will expose the Artalk service to the entire network. + +If you want Artalk to be accessible only locally, configure `host` to `127.0.0.1`. + +When starting Artalk via the command line, you can specify the address and port using the `--host` and `--port` parameters, for example: + +```bash +artalk server --host 127.0.0.1 --port 8080 +``` + +## Encrypted Transmission `ssl` + +```yaml +ssl: + enabled: true + cert_path: '' + key_path: '' +``` + +You can configure this item to upgrade HTTP to HTTPS, encrypting data transmission via SSL. + +- `cert_path`: Path to the SSL certificate public key file. +- `key_path`: Path to the SSL certificate private key file. + +You can also directly reverse proxy the Artalk local server and then enable HTTPS in, for example, Nginx. + +## Time Zone Configuration `timezone` + +```yaml +timezone: Asia/Shanghai +``` + +Fill in the time zone where you are located, corresponding to the IANA database time zone name, refer to: [Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) / [RFC-6557](https://www.rfc-editor.org/rfc/rfc6557.html). + +``` +UTC+08:00 Asia/Shanghai +UTC+09:00 Asia/Tokyo +UTC-07:00 America/Los_Angeles +UTC-04:00 America/New_York +``` + +## Login Timeout `login_timeout` + +This value sets the validity period of the administrator account login JWT token, in seconds. + +For example, valid for 3 days: + +```yaml +login_timeout: 259200 +``` + +## Log Configuration `log` + +When logging is enabled, system errors and other information will be recorded in the specified file. + +```yaml +log: + enabled: true # Master switch + filename: ./data/artalk.log # Log file path +``` + +Logs are in JSON format, which can be viewed using the `tail` command combined with the `jq` tool in Linux: + +```bash +tail -f ./data/artalk.log | jq +``` + +If you are a Grafana user, you can use Loki and Promtail to collect and query logs. + +## Debug Mode `debug` + +Set `debug` to `true` to enable debug mode. + +```yaml +debug: true +``` + +## Working Directory `-w` Parameter + +If the working directory is not specified, Artalk will use the "directory where the program is started" as the working directory. + +```bash +pwd # Display the current directory path +``` + +Use the `-w` parameter to specify the working directory, which is usually an "absolute path", for example: + +```bash +artalk -w /root/artalk -c ./conf.yml +``` + +Note: The relative path of `-c` will be based on the path of `-w`, and Artalk will read `/root/artalk/conf.yml` as the configuration file. + +Additionally, the "relative path" used in the "configuration file" will also be based on the "working directory". + +For example, if the configuration in `conf.yml` is: + +```yaml +test_file: ./data/artalk.log +``` + +It will read `/root/artalk/data/artalk.log`. + +::: tip + +Configuration file related code: [/internal/config/config.go](https://github.com/ArtalkJS/Artalk/blob/master/internal/config/config.go) + +Go to: [Frontend Configuration](../frontend/config.md) +::: diff --git a/docs/docs/en/guide/backend/daemon.md b/docs/docs/en/guide/backend/daemon.md new file mode 100644 index 000000000..557f21a9c --- /dev/null +++ b/docs/docs/en/guide/backend/daemon.md @@ -0,0 +1,144 @@ +# Daemon Process + +## Systemd + +Prerequisites: + +- The Artalk binary file, which can be downloaded from [GitHub Release](https://github.com/ArtalkJS/Artalk/releases) +- `systemctl --version` 232 or later +- `sudo` administrator privileges + +Move Artalk to `$PATH`, for example: + +```bash +sudo mv artalk /usr/bin/ +``` + +Test if it works: + +```bash +artalk version +``` + +Create a user group named `artalk`: + +```bash +sudo groupadd --system artalk +``` + +Create a user named `artalk` with a writable home directory: + +```bash +sudo useradd --system \ + --gid artalk \ + --create-home \ + --home-dir /var/lib/artalk \ + --shell /usr/sbin/nologin \ + --comment "Artalk server" \ + artalk +``` + +If you have the Artalk configuration file, ensure that the newly created `artalk` user has read permissions. + +Create the service file: + +```bash +sudo vim /etc/systemd/system/artalk.service +``` + +```ini +[Unit] +Description=Artalk +Documentation=https://artalk.js.org +After=network.target network-online.target +Requires=network-online.target + +[Service] +Type=simple +User=artalk +Group=artalk +ExecStart=/usr/bin/artalk server -w /var/lib/artalk -c /etc/artalk/artalk.yml +ExecReload=/bin/kill -s HUP $MAINPID +ExecStop=/bin/kill -s QUIT $MAINPID +TimeoutStopSec=5s +LimitNOFILE=1048576 +LimitNPROC=512 +PrivateTmp=true +ProtectSystem=full +AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + +[Install] +WantedBy=multi-user.target +``` + +Carefully check `ExecStart` and `ExecReload`. Ensure that the binary file location and program startup parameters are correct. + +For example, change the path of the `-c` parameter to specify the configuration file and the `-w` parameter to change the working directory. + +Note that all relative paths in the configuration file are based on the working directory. For example, the `./data/` folder in the configuration file, if the startup parameter is `-w /var/lib/artalk`, will read from the `/var/lib/artalk/data/` directory. Ensure the files in this directory are readable and writable by the created `artalk` account. + +After saving the service file, you can set the service to start automatically: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now artalk +``` + +Verify that the service is running correctly: + +```bash +systemctl status artalk +``` + +Some common commands: + +- Start the service: `systemctl start artalk` +- Stop the service: `systemctl stop artalk` +- Check the status: `systemctl status artalk` +- View logs: `journalctl -u artalk --no-pager | less +G` + +## Tmux + +tmux will create a persistent command-line session that remains in the background after SSH or tty disconnection. + +Note: tmux sessions will be cleared after the server shuts down or restarts, and you will need to manually rerun the program. + +1. Create a session `tmux new -s artalk` +2. Run the program `./artalk server` + +Reconnect to the session: `tmux attach -t artalk` + +View all sessions: `tmux ls` + +## Supervisor + +Taking Baota Panel as an example: Open the "Software Store," search for and install the "Supervisor Manager": + +![](/images/baota-supervisor/0.png) + +After installation, open the plugin and click "Add Daemon": + +![](/images/baota-supervisor/1.png) + +> - Startup User: `root` or others +> - Working Directory: Click the icon on the right and select the Artalk directory +> - Startup Command: `./artalk server` + +## Docker + +Update the Docker container's [Restart Policy](https://docs.docker.com/config/containers/start-containers-automatically/#use-a-restart-policy) to achieve the effect of process daemonization. + +```bash +docker update --restart=unless-stopped artalk +``` + +## Docker Compose + +Add the `restart: unless-stopped` policy to the service in the `docker-compose.yml` file: + +```diff +version: '3' +services: + artalk: ++ restart: unless-stopped +``` diff --git a/docs/docs/en/guide/backend/docker.md b/docs/docs/en/guide/backend/docker.md new file mode 100644 index 000000000..1f1769eb7 --- /dev/null +++ b/docs/docs/en/guide/backend/docker.md @@ -0,0 +1,101 @@ +# Docker + +Artalk provides Docker images for the backend program to accelerate the deployment process and offer a good deployment experience. + +The [Docker Hub](https://hub.docker.com/r/artalk/artalk-go) image versions are kept in sync with the [Releases](https://github.com/ArtalkJS/Artalk/releases) in the code repository. + +## Pulling the Image + +```bash +docker pull artalk/artalk-go +``` + +## Creating the Container + +::: tip + +It is recommended to use Docker Compose. Refer to the steps on the [Program Deployment](../deploy) page. + +::: + +## Generating the Configuration File + +```bash +docker run -it -v $(pwd)/data:/data --rm artalk/artalk-go gen config data/artalk.yml +``` + +## Restart + +After modifying the configuration file, you need to restart to apply the changes. + +```bash +# Docker Compose +docker-compose restart + +# Docker +docker restart artalk +``` + +## Stop + +```bash +# Docker Compose +docker-compose stop + +# Docker +docker stop artalk +``` + +## Upgrade + +Delete the existing container, pull the latest image, and then recreate the container. + +### Docker Compose + +```bash +docker-compose down +docker-compose pull +docker-compose up -d +``` + +### Docker + +```bash +docker stop artalk +docker rm artalk +docker pull artalk/artalk-go +``` + +::: tip +For breaking changes, please refer to the update notes in the version changelog: [CHANGELOG.md](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md) +::: + +## Testing Version + +The nightly image is a testing version that is updated daily and automatically built from the latest code in the repository. + +```bash +docker pull artalk/artalk-go:nightly +``` + +## Historical Versions + +Images are automatically built and released with the repository tags. You can pull images of different versions. + +```bash +docker pull artalk/artalk-go: +``` + +## Entering the Container + +```bash +# Docker Compose +docker-compose exec artalk bash + +# Docker +docker exec -it artalk bash +``` + +## Multi-Platform Compatibility + +The Docker image currently only provides builds for x86 and arm64 architectures. For more platform architectures, please download the binary build and deploy it using the [Ordinary Deployment](../deploy.md#普通方式部署) method. diff --git a/docs/docs/en/guide/backend/email.md b/docs/docs/en/guide/backend/email.md new file mode 100644 index 000000000..0ddcd07a8 --- /dev/null +++ b/docs/docs/en/guide/backend/email.md @@ -0,0 +1,325 @@ +# Email Notifications + +Artalk supports sending email notifications to users through various methods such as SMTP protocol, Alibaba Cloud Email Service, and system Sendmail command invocation. + +You can modify this configuration in the settings interface of the [Dashboard](../frontend/sidebar.md#settings), or configure it through [configuration files](./config.md#email-notifications-email) or [environment variables](../env.md#email-notifications). + +## Configuration File + +The complete `email` configuration is as follows: + +```yaml +# Email Notifications +email: + enabled: false # Master Switch + send_type: smtp # Sending Method [smtp, ali_dm, sendmail] + send_name: '{{reply_nick}}' # Sender's Nickname + send_addr: example@qq.com # Sender's Address + mail_subject: '[{{site_name}}] You have received a reply from @{{reply_nick}}' + mail_tpl: default # Email Template File + smtp: + host: smtp.qq.com + port: 587 + username: example@qq.com + password: '' + ali_dm: # https://help.aliyun.com/document_detail/29444.html + access_key_id: '' # Access Key ID issued by Alibaba Cloud + access_key_secret: '' # Secret key for encryption + account_name: example@example.com # Sending address configured in the management console +``` + +### Choosing a Sending Method + +The configuration item `enabled` enables email notifications, and `send_type` is used to select the sending method. Options are: `smtp`, `ali_dm`, `sendmail`. + +```yaml +email: + enabled: true + send_type: smtp # Sending Method + # Other configurations omitted... + smtp: + # SMTP Configuration... + ali_dm: + # Alibaba Cloud Push Configuration... +``` + +### SMTP Configuration + +```yaml +# Email Notifications +email: + enabled: true + send_type: smtp # Selecting smtp + smtp: + host: smtp.qq.com + port: 587 + username: example@qq.com + password: '' +``` + +### Alibaba Cloud Push Configuration + +```yaml +email: + enabled: true + send_type: ali_dm # Selecting ali_dm + ali_dm: + access_key_id: '' # Access Key ID issued by Alibaba Cloud + access_key_secret: '' # Secret key for encryption + account_name: example@example.com # Sending address configured in the management console +``` + +Refer to: [Alibaba Cloud Official Documentation](https://help.aliyun.com/document_detail/29444.html) + +## Comment Replies + +The email will include a comment reply button, linking to the given PageKey on the frontend. If your `pageKey` configuration item is a "relative path" of the page, you need to set a URL for your site in the "[Dashboard](../frontend/sidebar.md#dashboard)" - "Site": + + + +## Email Templates + +### Template Variables + +You can use template variables in `mail_subject` and `mail_subject_to_admin` as well as in the email template file: + +```yaml +email: + # Other configurations omitted... + mail_subject: '[{{site_name}}] You have received a reply from @{{reply_nick}}' + mail_subject_to_admin: '[{{site_name}}] Your article "{{page_title}}" has a new reply' + mail_tpl: default # Email Template File +``` + +Variables follow the "Mustache" syntax, outputting a variable with `double braces` + `variable name`: + +**Basic Content Variables** + +```yaml +{{content}} # Comment content +{{link_to_reply}} # Reply link +{{nick}} # Commenter's nickname +{{page_title}} # Page title +{{page_url}} # Page PageKey (URL) +{{reply_content}} # Content of the reply +{{reply_nick}} # Nickname of the reply target +{{site_name}} # Site name +{{site_url}} # Site URL +``` + +::: details View Other Variables + +```yaml +# Comment Creator +{{comment.badge_color}} +{{comment.badge_name}} +{{comment.content}} +{{comment.content_raw}} +{{comment.date}} +{{comment.datetime}} +{{comment.email}} +{{comment.email_encrypted}} +{{comment.id}} +{{comment.is_allow_reply}} +{{comment.is_collapsed}} +{{comment.is_pending}} +{{comment.link}} +{{comment.nick}} +{{comment.page.admin_only}} +{{comment.page.id}} +{{comment.page.key}} +{{comment.page.site_name}} +{{comment.page.title}} +{{comment.page.url}} +{{comment.page.vote_down}} +{{comment.page.vote_up}} +{{comment.page_key}} +{{comment.page_title}} +{{comment.rid}} +{{comment.site.first_url}} +{{comment.site.id}} +{{comment.site.name}} +{{comment.site.urls.0}} +{{comment.site.urls_raw}} +{{comment.site_name}} +{{comment.time}} +{{comment.ua}} +{{comment.visible}} +{{comment.vote_down}} +{{comment.vote_up}} + +# Parent Comment (Comment that the creator is replying to) +{{parent_comment.badge_color}} +{{parent_comment.badge_name}} +{{parent_comment.content}} +{{parent_comment.content_raw}} +{{parent_comment.date}} +{{parent_comment.datetime}} +{{parent_comment.email}} +{{parent_comment.email_encrypted}} +{{parent_comment.id}} +{{parent_comment.is_allow_reply}} +{{parent_comment.is_collapsed}} +{{parent_comment.is_pending}} +{{parent_comment.link}} +{{parent_comment.nick}} +{{parent_comment.page.admin_only}} +{{parent_comment.page.id}} +{{parent_comment.page.key}} +{{parent_comment.page.site_name}} +{{parent_comment.page.title}} +{{parent_comment.page.url}} +{{parent_comment.page.vote_down}} +{{parent_comment.page.vote_up}} +{{parent_comment.page_key}} +{{parent_comment.page_title}} +{{parent_comment.rid}} +{{parent_comment.site.first_url}} +{{parent_comment.site.id}} +{{parent_comment.site.name}} +{{parent_comment.site.urls}} +{{parent_comment.site.urls_raw}} +{{parent_comment.site_name}} +{{parent_comment.time}} +{{parent_comment.ua}} +{{parent_comment.visible}} +{{parent_comment.vote_down}} +{{parent_comment.vote_up}} +``` + +::: + +::: details View Data Sample + +```json +{ + "content": "

Test content

\n", + "link_to_reply": "https://artalk.js.org/?atk_comment=8100&atk_notify_key=44a9b2f08312565fba47c716df9d177f", + "nick": "Username", + "page_title": "Artalk", + "page_url": "https://artalk.js.org/", + + "reply_content": "

Replier's content

\n", + "reply_nick": "Replier", + "site_name": "ArtalkDemo", + "site_url": "http://localhost:3000/", + + "comment.badge_color": "", + "comment.badge_name": "", + "comment.content": "

Replier's content

\n", + "comment.content_raw": "Replier's content", + "comment.date": "2021-11-22", + "comment.datetime": "2021-11-22 22:22:42", + "comment.email": "replyer@example.com", + "comment.email_encrypted": "249898bd50e0febc5799485cf10b345a", + "comment.id": 8100, + "comment.is_allow_reply": true, + "comment.is_collapsed": false, + "comment.is_pending": false, + "comment.link": "", + "comment.nick": "Replier", + "comment.page.admin_only": false, + "comment.page.id": 75, + "comment.page.key": "https://artalk.js.org/", + "comment.page.site_name": "ArtalkDemo", + "comment.page.title": "Artalk", + "comment.page.url": "https://artalk.js.org/", + "comment.page.vote_down": 0, + "comment.page.vote_up": 0, + "comment.page_key": "https://artalk.js.org/", + "comment.page_title": "Artalk", + "comment.rid": 8099, + "comment.site.first_url": "http://localhost:3000/", + "comment.site.id": 2, + "comment.site.name": "ArtalkDemo", + "comment.site.urls.0": "http://localhost:3000/", + "comment.site.urls_raw": "http://localhost:3000/", + "comment.site_name": "ArtalkDemo", + "comment.time": "22:22:42", + "comment.ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", + "comment.visible": false, + "comment.vote_down": 0, + "comment.vote_up": 0, + + "parent_comment.badge_color": "", + "parent_comment.badge_name": "", + "parent_comment.content": "

Test content

\n", + "parent_comment.content_raw": "Test content", + "parent_comment.date": "2021-11-22", + "parent_comment.datetime": "2021-11-22 22:21:17", + "parent_comment.email": "test@example.com", + "parent_comment.email_encrypted": "55502f40dc8b7c769880b10874abc9d0", + "parent_comment.id": 8099, + "parent_comment.is_allow_reply": true, + "parent_comment.is_collapsed": false, + "parent_comment.is_pending": false, + "parent_comment.link": "https://qwqaq.com", + "parent_comment.nick": "Username", + "parent_comment.page.admin_only": false, + "parent_comment.page.id": 75, + "parent_comment.page.key": "https://artalk.js.org/", + "parent_comment.page.site_name": "ArtalkDemo", + "parent_comment.page.title": "Artalk", + "parent_comment.page.url": "https://artalk.js.org/", + "parent_comment.page.vote_down": 0, + "parent_comment.page.vote_up": 0, + "parent_comment.page_key": "https://artalk.js.org/", + "parent_comment.page_title": "Artalk", + "parent_comment.rid": 0, + "parent_comment.site.first_url": "http://localhost:3000/", + "parent_comment.site.id": 2, + "parent_comment.site.name": "ArtalkDemo", + "parent_comment.site.urls.0": "http://localhost:3000/", + "parent_comment.site.urls_raw": "http://localhost:3000/", + "parent_comment.site_name": "ArtalkDemo", + "parent_comment.time": "22:21:17", + "parent_comment.ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36", + "parent_comment.visible": false, + "parent_comment.vote_down": 0, + "parent_comment.vote_up": 0 +} +``` + +::: + +### Custom Templates + +You can set `mail_tpl` to a "specific file path" to use an external custom email template. + +For example, set `mail_tpl` to `"/root/Artalk/data/mail_tpl/your_email_template.html"` + +```yaml +email: + mail_tpl: /root/Artalk/data/mail_tpl/your_email_template.html + # Other configurations omitted... +``` + +Then, there should be a file at this path: + +```html +
+

Hi, {{nick}}:

+

You have received a reply in “{{page_title}}”:

+
+
@{{reply_nick}}:
+
{{reply_content}}
+
+

Reply to the message »

+
+``` + +Artalk includes many preset email templates, such as `mail_tpl: "default"`, which uses: [@ArtalkJS/Artalk:/internal/template/email_tpl/default.html](https://github.com/ArtalkJS/Artalk/blob/master/internal/template/email_tpl/default.html) + +## Emails to Administrators + +Email notifications target both administrators and regular users. You can set different subjects for emails sent to administrators via the following configuration: + +```yaml +admin_notify: + enabled: true + mail_subject: '[{{site_name}}] Your article "{{page_title}}" has a new reply' +``` + +Note: The old `email.mail_subject_to_admin` configuration item has been deprecated. Please use the above instead. + +Artalk supports various methods to send notifications to administrators, not limited to emails. Refer to: [Diverse Push Notifications](./admin_notify.md#email-notifications). diff --git a/docs/docs/en/guide/backend/img-upload.md b/docs/docs/en/guide/backend/img-upload.md new file mode 100644 index 000000000..9de7e278b --- /dev/null +++ b/docs/docs/en/guide/backend/img-upload.md @@ -0,0 +1,114 @@ +# Image Upload + +Artalk provides an image upload feature with options to limit image size, upload frequency, and more. You can also integrate with UpGit to upload images to image hosting services. + +You can modify this configuration in the settings interface of the [Dashboard](../frontend/sidebar.md#settings), or configure it through [configuration files](./config.md#image-upload-img_upload) or [environment variables](../env.md#image-upload). + +## Configuration File + +The complete `img_upload` configuration is as follows: + +```yaml +# Image Upload +img_upload: + enabled: true # Master Switch + path: ./data/artalk-img/ # Image storage path + max_size: 5 # Image size limit (Unit: MB) + public_path: null # Specify the base URL for image links (default is "/static/images/") + # Use UpGit to upload images to GitHub or image hosting services + upgit: + enabled: false # Enable UpGit + exec: upgit -c -t /artalk-img + del_local: true # Delete local images after uploading +``` + +## Using UpGit to Upload to Image Hosting Services + +[UpGit](https://github.com/pluveto/upgit) supports uploading images to various image hosting services or code repositories such as GitHub, Gitee, Tencent Cloud COS, Qiniu Cloud, UpYun, SM.MS, and more. + +First, download UpGit and complete the configuration for your target image hosting service according to the [README.md](https://github.com/pluveto/upgit). + +Then, add UpGit to the system's environment variables by adding the following to `~/.bashrc`: + +```bash +export PATH=$PATH:/path/to/upgit +``` + +(Or move it directly to `/usr/bin`) + +Finally, fill in the UpGit startup parameters in Artalk's `img_upload.upgit` field: + +```yaml +upgit: + enabled: true # Enable UpGit + exec: upgit -c -t /artalk-img + del_local: true # Delete local images after uploading +``` + +::: warning Update Notice +Starting from version `v2.8.4`, to enhance security, Artalk no longer allows specifying the UpGit executable file path. Please add it to the system's environment variables. :) +::: + +### Mounting UpGit with Docker + +If you are deploying Artalk with Docker, you can mount the UpGit executable to the container: + +```bash +docker run -d --name artalk -v /path/to/upgit:/usr/bin/upgit -v /path/to/artalk:/app/data -p 8080:23366 artalk +``` + +## Upload Frequency Limit + +The frequency limit follows the `captcha` configuration. When the limit is exceeded, a captcha will be prompted. + +Refer to: [Backend · Captcha](./captcha.md) + +## Path + +`img_upload.path` is the "local storage directory" path for uploaded image files. This directory will be mapped by Artalk to be accessible at: + +``` +http:///static/images/ +``` + +## Public Path + +The default value for `img.public_path` is: `/static/images/` + +When this item is a "relative path", for example: `/static/images/`, the HTML tag for the uploaded image on the frontend will be: + +```html + +``` + +Note: The `` is configured in the frontend `conf.server`. + +When this item is a "complete URL path", for example: `https://cdn.github.com/img/`, the image tag will be: + +```html + +``` + +Tip: This configuration can be used in scenarios such as load balancing. + +## Custom Upload API on the Frontend + +The frontend provides the `imgUploader` configuration option, allowing you to customize the API for image upload requests, for example: + +```js +Artalk.init({ + imgUploader: async (file) => { + const form = new FormData() + form.set('file', file) + + const imgUrl = await fetch('https://api.example.org/upload', { + method: 'POST', + body: form, + }) + + return imgUrl + }, +}) +``` + +Refer to: [Frontend Configuration Documentation](../frontend/config.md#imguploader) diff --git a/docs/docs/en/guide/backend/moderator.md b/docs/docs/en/guide/backend/moderator.md new file mode 100644 index 000000000..1283e902d --- /dev/null +++ b/docs/docs/en/guide/backend/moderator.md @@ -0,0 +1,118 @@ +# Comment Moderation + +Artalk supports multiple comment filtering methods to intercept spam comments. It offers integration with online APIs like Akismet, Tencent Cloud Content Safety, Alibaba Cloud Content Safety, and local offline keyword libraries. You can further enhance comment moderation by combining it with the [captcha](./captcha.md) feature, making it hard for spam comments to get through. + +You can modify this configuration in the settings interface of the [Dashboard](../frontend/sidebar.md#settings), or configure it through [configuration files](./config.md#comment-moderation-moderator) or [environment variables](../env.md#comment-moderation). + +## Configuration File + +The complete `moderator` configuration is as follows: + +```yaml +# Comment Moderation +moderator: + pending_default: false # New comments default to "pending review" status + api_fail_block: false # Intercept comments even if the spam detection API request fails + # akismet.com anti-spam + akismet_key: '' + # Tencent Cloud Text Content Safety (tms) + tencent: # https://cloud.tencent.com/document/product/1124/64508 + enabled: false + secret_id: '' + secret_key: '' + region: ap-guangzhou + # Alibaba Cloud Content Safety + aliyun: # https://help.aliyun.com/document_detail/28417.html + enabled: false + access_key_id: '' + access_key_secret: '' + region: cn-shanghai + # Keyword library filtering + keywords: + enabled: false + pending: false # Set to pending review if matched + files: # Support multiple keyword files + - './data/keyword_1.txt' + file_sep: "\n" # Keyword file content separator + replace_to: 'x' # Replacement character +``` + +## Default Pending Mode + +Enable new comments to default to "pending review" status: + +```yaml +moderator: + pending_default: true +``` + +## Akismet + +[Akismet](https://akismet.com/) is a globally recognized anti-spam API provided by WordPress, particularly effective against English spam comments. Akismet offers a free Personal version suitable for personal blog sites. + +![](/images/akismet/1.png) + +You can easily apply for an `akismet_key` on the [Akismet official website](https://akismet.com/) and fill it in the configuration file to enable Akismet spam filtering. + +![](/images/akismet/2.png) + +```yaml +moderator: + akismet_key: your_key +``` + +## Tencent Cloud Text Content Safety + +Refer to: [Tencent Cloud Documentation](https://cloud.tencent.com/document/product/1124/64508) + +After enabling "Text Content Safety", add a Secret with permissions in "Access Management" - "API Key Management", and fill in the configuration: + +```yaml +moderator: + tencent: + enabled: true + secret_id: '' + secret_key: '' + region: ap-guangzhou +``` + +## Alibaba Cloud Content Safety + +Refer to: [Alibaba Cloud Documentation](https://help.aliyun.com/document_detail/28417.html) + +After enabling "Alibaba Cloud Content Safety", create an Access Key in the Alibaba Cloud backend and fill in the configuration: + +```yaml +moderator: + aliyun: + enabled: true + access_key_id: '' + access_key_secret: '' + region: cn-shanghai +``` + +## Keyword Library Filtering + +If you prefer not to rely on remote APIs, you can configure and import keyword files locally to let Artalk detect spam comments based on keywords: + +```yaml +moderator: + keywords: + enabled: true + pending: false # Set to pending review if matched + files: # Support multiple keyword files + - ./data/keyword_1.txt + file_sep: "\n" # Keyword file content separator + replace_to: 'x' # Replacement character +``` + +- **pending**: Whether to set the comment to pending review status upon successful match. +- **files**: Keyword files. Multiple files are allowed, and Artalk will merge the keyword libraries upon startup. +- **file_sep**: Keyword file content separator. For example, if each line in the file contains a keyword, set this item to `\n`. +- **replace_to**: Replacement character. For example, if this item is set to `x`, you can set `pending` to `false`, allowing the comment to pass review automatically, but the matched keywords will be replaced with `x`, resulting in `fxxk` or `xxxx`. + +Note: It is recommended not to use `*` asterisk as `replace_to` because it conflicts with the Markdown bold syntax. + +## Using Captcha + +You can enable Artalk's captcha feature, supporting image and slider captchas, [refer here](./captcha.md). diff --git a/docs/docs/en/guide/backend/multi-site.md b/docs/docs/en/guide/backend/multi-site.md new file mode 100644 index 000000000..6ad98059f --- /dev/null +++ b/docs/docs/en/guide/backend/multi-site.md @@ -0,0 +1,86 @@ +# Admins and Multi-Site Support + +Artalk supports multi-site management, allowing administrators to create and manage multiple sites and their respective comments and pages from a centralized interface. + +## Creating an Administrator + +Run the following command and follow the prompts to quickly create an administrator: + +```sh +./artalk admin +``` + +If you are using Docker, you can run the following command: + +```sh +docker exec -it artalk artalk admin +``` + +After creating the administrator account, you can log into the control panel to create additional accounts through the graphical user interface on the user management page, eliminating the need to manually edit configuration files. + +## Creating and Managing Sites + +You can create and manage multiple sites and switch between them quickly in the "Dashboard" accessible from the sidebar. + +## Admin Configuration + +You can set up multiple administrator accounts. When the input field matches an administrator's username and email, a password verification prompt will appear. Only administrators can access the "Dashboard" and manage comments from the frontend. + +(Optional) Add administrators via the configuration file: + +```yaml +admin_users: + - name: admin + email: admin@example.com + password: (bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm + badge_name: Administrator + badge_color: '#0083FF' + - name: admin2 + email: admin2@example.com + password: (bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm + badge_name: Junior Admin + badge_color: '#0083FF' +``` + +Explanation of each configuration item: + +- **name** & **email**: Username and email, **case-insensitive**. +- **password**: User password. + + Supports bcrypt and md5 encryption. For example, you can specify: `"(md5)50c21190c6e4e5418c6a90d2b5031119"`. + + **Using the more secure bcrypt encryption algorithm is recommended**. In a Linux environment, you can use the [htpasswd command](https://httpd.apache.org/docs/2.4/programs/htpasswd.html) to generate the encrypted password: + + ```bash + unset HISTFILE # Temporarily disable history to prevent the password from appearing in the history + htpasswd -bnBC 10 "" "your_password" | tr -d ':' + ``` + + Then configure it as: `"(bcrypt)$2y$10$ti4vZYIrxVN8rLcY..."`, starting with `(bcrypt)`. + + Command explanation reference: [Compute bcrypt hash from command line](https://unix.stackexchange.com/questions/307994/compute-bcrypt-hash-from-command-line#answer-419855) + +- **badge_name**: The title badge text displayed for the user. +- **badge_color**: The background color of the title badge displayed for the user. + +::: tip + +You can also configure administrator accounts through environment variables. Refer to: [Environment Variable Configuration](../env.md) + +::: + +### Controlling Admin Email Notifications + +By default, when there are new comments on a page, emails are sent to all administrators. However, you can configure `receive_email` to forcefully disable email notifications for specific administrators. + +This is useful if you have multiple email addresses configured but do not want certain addresses to receive comment notifications. + +- **receive_email**: When set to `false`, the system will not send email notifications to that user. + + Note: Even if email notifications are disabled, the administrator will still receive @AT replies from others. The system will not send email notifications when the user comments on a page (creates a root comment). + +```yaml +admin_users: + - name: admin + receive_email: false # ← Forcefully disable email notifications +``` diff --git a/docs/docs/en/guide/backend/relative-path.md b/docs/docs/en/guide/backend/relative-path.md new file mode 100644 index 000000000..bbe53896c --- /dev/null +++ b/docs/docs/en/guide/backend/relative-path.md @@ -0,0 +1,53 @@ +# Resolve Relative Path + +Artalk supports parsing relative paths, allowing you to configure it on the frontend as follows: + +```js +Artalk.init({ + site: 'Example Site', // Your site name + pageKey: '/relative-path/xx.html', // Using relative path +}) +``` + +Using relative paths is recommended because it facilitates future "site migration" needs. + +Next, in the sidebar, navigate to "Dashboard" - "Site", find "Example Site", and modify the site URL. + +![](/images/relative-path/1.png) + +Afterward, all relative paths will be "based on this site URL". For example: + +```bash +"/relative-path/xx.html" + ↓ resolves to +"https://set-example-site-url.xxx/relative-path/xx.html" +``` + +## Uses of Resolved URLs + +The site URL + page relative path will be used for: + +- **Email notifications** containing links to reply to comments +- **Sidebar** quick jumps to specific comments +- **Dashboard** page management to open pages +- **Fetching page titles** and other information + +## Configuring Multiple Site URLs + +You might need to configure multiple URLs for a site to allow referer and cross-origin requests. + +In "Dashboard" - "Site", you can modify the site URL to support adding multiple URLs by separating each URL with a comma `,`. + +**When a site has multiple URLs**, the "relative path" will be based on the "first" URL in the list. + +## Using Absolute Paths + +As opposed to using relative paths, you can use absolute paths. For example, configure the frontend like this: + +```js +Artalk.init({ + pageKey: 'https://your_domain.com/relative-path/xx.html', // Using absolute path +}) +``` + +In this case, the backend will not resolve this address. The absolute path specified in `pageKey` will be directly used for locating the page in emails, sidebar, etc. diff --git a/docs/docs/en/guide/backend/reverse-proxy.md b/docs/docs/en/guide/backend/reverse-proxy.md new file mode 100644 index 000000000..24d4234c1 --- /dev/null +++ b/docs/docs/en/guide/backend/reverse-proxy.md @@ -0,0 +1,123 @@ +# Reverse Proxy + +## Caddy + +**/etc/caddy/Caddyfile** + +```nginx +artalk.your_domain.com { + tls /etc/caddy/ssl/cert.pem /etc/caddy/ssl/cert.key + + reverse_proxy http://localhost:23366 { + header_up X-Forwarded-For {header.X-Forwarded-For} + } +} +``` + +Reload the Caddy configuration: + +```sh +sudo systemctl reload caddy +``` + +## Nginx + +Assumptions: + +- The domain you want to bind is: `artalk.your_domain.com` +- Artalk local address: `http://localhost:23366` + +For Ubuntu 20.04: + +Create the site configuration file: + +```bash +sudo vim /etc/nginx/sites-available/artalk.your_domain.com +``` + +Edit the reverse proxy configuration file: + +```nginx +server { + listen 80; + listen [::]:80; + + server_name artalk.your_domain.com; + + location / { + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://localhost:23366/; + } +} +``` + +Create a symbolic link to enable the site: + +```bash +sudo ln -s /etc/nginx/sites-available/artalk.your_domain.com /etc/nginx/sites-enabled/ +``` + +Check if the configuration file is valid: + +```bash +sudo nginx -t +``` + +If the configuration is correct, restart Nginx: + +```bash +sudo systemctl restart nginx +``` + +Configure the frontend: + +```js +Artalk.init({ server: 'http://artalk.your_domain.com' }) +``` + +::: tip +You can also add a layer of CDN and SSL. + +Pay attention to the configuration file permissions and the accessibility of the reverse proxy target URL. + +Especially if Artalk is running inside a Docker container, make sure the IP and port can be accessed by Nginx. +::: + +## Apache + +You need to enable the reverse proxy module `mod_proxy.c` + +```apache + + ServerName your_domain.xxx + ServerAlias + + RewriteEngine On + RewriteCond %{QUERY_STRING} transport=polling [NC] + RewriteRule /(.*) http://localhost:23366/$1 [P] + + + ProxyRequests Off + SSLProxyEngine on + ProxyPass / http://localhost:23366/ + ProxyPassReverse / http://localhost:23366/ + + +``` + +## BaoTa Panel (宝塔面板) + +First, create a site (e.g., `artalk.your_domain.com`), then click the site "Settings": + +![](/images/baota-proxy/1.png) + +Open the "Reverse Proxy" tab, click "Add Reverse Proxy", fill in the "Target URL" with `http://localhost:port` (where the port corresponds to the Artalk port), and fill in the "Send Domain" with `$host`, as shown in the figure: + +![](/images/baota-proxy/2.png) + +## Getting the Accurate IP Address + +When using a reverse proxy server, you need to configure the proxy headers to get the user's accurate IP address. Refer to the [IP Region](../frontend/ip-region.md#获取准确的-ip-地址) documentation for more details. diff --git a/docs/docs/en/guide/backend/update.md b/docs/docs/en/guide/backend/update.md new file mode 100644 index 000000000..43e43f427 --- /dev/null +++ b/docs/docs/en/guide/backend/update.md @@ -0,0 +1,25 @@ +# Program Upgrade + +## Update Changes + +For significant changes, such as updates that require modifications to existing configurations, please refer to the version update log for relevant prompts: [CHANGELOG.md](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md). + +## One-Click Upgrade via Command Line + +Execute `./artalk upgrade` + +This operation will automatically download and upgrade the program from GitHub Release. Ensure to stop Artalk before executing this command. + +::: tip +Execute `./artalk upgrade -f` with the `-f` parameter to force an update. +::: + +## Docker Upgrade + +Refer to: [Docker · Upgrade](./docker.md#升级) + +## Manual Method + +Go to [GitHub Release](https://github.com/ArtalkJS/Artalk/releases) to manually download the latest build. + +Replace the old version files with the new ones. diff --git a/docs/docs/en/guide/cases.md b/docs/docs/en/guide/cases.md new file mode 100644 index 000000000..c4128fc3a --- /dev/null +++ b/docs/docs/en/guide/cases.md @@ -0,0 +1,12 @@ +# 🚀 Case Showcase + +### Open Source Projects + +- [Wiki.js](https://github.com/requarks/wiki/): A modern and powerful wiki app built on Node.js +- [vuepress-theme-hope](https://github.com/vuepress-theme-hope/vuepress-theme-hope): A vuepress theme with tons of features +- [hexo-theme-stellar](https://github.com/xaoxuu/hexo-theme-stellar): Elegant and powerful theme for Hexo +- [FixIt Theme | Hugo](https://github.com/Lruihao/FixIt): A clean, elegant but advanced blog theme for Hugo +- [hexo-theme-volantis](https://github.com/volantis-x/hexo-theme-volantis): A Wonderful Theme for Hexo +- [hexo-theme-cards](https://github.com/ChrAlpha/hexo-theme-cards): Another Simple & Swift theme for Hexo +- [hexo-theme-butterfly](https://github.com/jerryc127/hexo-theme-butterfly): A Hexo Theme: Butterfly +- [hexo-theme-solitude](https://github.com/valor-x/hexo-theme-solitude): A Hexo Theme: Solitude diff --git a/docs/docs/en/guide/deploy.md b/docs/docs/en/guide/deploy.md index 8abeebb7e..26b23807c 100644 --- a/docs/docs/en/guide/deploy.md +++ b/docs/docs/en/guide/deploy.md @@ -70,7 +70,7 @@ Advanced operations: - [Daemon Process (Systemd, Supervisor)](./backend/daemon.md) - [Reverse Proxy (Caddy, Nginx, Apache)](./backend/reverse-proxy.md) -- [Self-compile (Build from the latest code)](../develop/contributing.md) +- [Self-compile (Build from the latest code)](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md) ## Compose Deployment diff --git a/docs/docs/en/guide/env.md b/docs/docs/en/guide/env.md new file mode 100644 index 000000000..785df6269 --- /dev/null +++ b/docs/docs/en/guide/env.md @@ -0,0 +1,350 @@ +# Environment Variables + +Artalk supports configuration changes via environment variables, simplifying containerized cloud deployments such as Docker. + +Environment variable names start with `ATK_`, in all uppercase, corresponding to each node in the [configuration file](./backend/config.md). + +Environment variables take precedence over configuration files. Verify if the configuration has taken effect using the following command: + +```bash +artalk config +``` + +To deploy Artalk using Docker Compose, add environment variables in the `compose.yml` file, for instance: + +```yaml +version: '3.8' +services: + artalk: + container_name: artalk + image: artalk/artalk-go + restart: unless-stopped + ports: + - 8080:23366 + volumes: + - ./data:/data + environment: + - TZ=America/New_York + - ATK_LOCALE=en + - ATK_SITE_DEFAULT=Artalk's Blog + - ATK_SITE_URL=https://example.com + - ATK_TRUSTED_DOMAINS=https://dev.example.com https://localhost:8080 + - ATK_ADMIN_USERS_0_NAME=admin + - ATK_ADMIN_USERS_0_EMAIL=admin@example.org + - ATK_ADMIN_USERS_0_PASSWORD=(bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm + - ATK_ADMIN_USERS_0_BADGE_NAME=Administrator + - ATK_ADMIN_USERS_0_BADGE_COLOR=#0083FF +``` + +When the variable is an array, set array values using space-separated strings or numerical indices, for example: + +``` +ATK_TRUSTED_DOMAINS="https://a.com https://b.com" +ATK_TRUSTED_DOMAINS_0="https://a.com" +``` + + + +
+ + +## 通用配置 + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_APP_KEY** | `""` | App Key (for generation of JWT) | app_key (App Key) | +| **ATK_DEBUG** | `false` | Debug mode | debug (Debug mode) | +| **ATK_HOST** | `"0.0.0.0"` | Listen host | host (Listen host) | +| **ATK_LOCALE** | `"en"` | Language (follow Unicode BCP 47) (可选:`["en", "zh-CN", "zh-TW", "ja", "fr", "ko", "ru"]`) | locale (Language) | +| **ATK_LOGIN_TIMEOUT** | `259200` | Login timeout (in seconds) | login_timeout (Login timeout) | +| **ATK_PORT** | `23366` | Listen port | port (Listen port) | +| **ATK_SITE_DEFAULT** | `"Default Site"` | Default site name (create when app is first launched) | site_default (Default site name) | +| **ATK_SITE_URL** | `""` | Default site url | site_url (Default site url) | +| **ATK_TIMEZONE** | `"Asia/Shanghai"` | Timezone (follow IANA Time Zone Database) | timezone (Timezone) | +| **ATK_TRUSTED_DOMAINS** | `[]` | Trusted domains | trusted_domains (Trusted domains) | + + +## Multi-Push + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_ADMIN_NOTIFY_BARK_ENABLED** | `false` | 启用 | admin_notify.bark.enabled (Multi-Push > Bark > Enabled) | +| **ATK_ADMIN_NOTIFY_BARK_SERVER** | `"http://day.app/xxxxxxx/"` | Server | admin_notify.bark.server (Multi-Push > Bark > Server) | +| **ATK_ADMIN_NOTIFY_DING_TALK_ENABLED** | `false` | 启用 | admin_notify.ding_talk.enabled (Multi-Push > DingTalk > Enabled) | +| **ATK_ADMIN_NOTIFY_DING_TALK_SECRET** | `""` | Secret | admin_notify.ding_talk.secret (Multi-Push > DingTalk > Secret) | +| **ATK_ADMIN_NOTIFY_DING_TALK_TOKEN** | `""` | Token | admin_notify.ding_talk.token (Multi-Push > DingTalk > Token) | +| **ATK_ADMIN_NOTIFY_EMAIL_ENABLED** | `true` | Enable (can be disabled when using other push methods) | admin_notify.email.enabled (Multi-Push > Notify admin > Enable) | +| **ATK_ADMIN_NOTIFY_EMAIL_MAIL_SUBJECT** | `"[{{site_name}}] Post \"{{page_title}}\" has new a comment"` | Email subject (email subject sent to admin) | admin_notify.email.mail_subject (Multi-Push > Notify admin > Email subject) | +| **ATK_ADMIN_NOTIFY_EMAIL_MAIL_TPL** | `""` | Admin email template file (set to file path to use custom template) | admin_notify.email.mail_tpl (Multi-Push > Notify admin > Admin email template file) | +| **ATK_ADMIN_NOTIFY_LARK_ENABLED** | `false` | 启用 | admin_notify.lark.enabled (Multi-Push > Lark > Enabled) | +| **ATK_ADMIN_NOTIFY_LARK_MSG_TYPE** | `"text"` | Message type (可选:`["text", "card"]`) | admin_notify.lark.msg_type (Multi-Push > Lark > Message type) | +| **ATK_ADMIN_NOTIFY_LARK_WEBHOOK_URL** | `""` | WebhookUrl | admin_notify.lark.webhook_url (Multi-Push > Lark > WebhookUrl) | +| **ATK_ADMIN_NOTIFY_LINE_CHANNEL_ACCESS_TOKEN** | `""` | ChannelAccessToken | admin_notify.line.channel_access_token (Multi-Push > LINE > ChannelAccessToken) | +| **ATK_ADMIN_NOTIFY_LINE_CHANNEL_SECRET** | `""` | ChannelSecret | admin_notify.line.channel_secret (Multi-Push > LINE > ChannelSecret) | +| **ATK_ADMIN_NOTIFY_LINE_ENABLED** | `false` | 启用 | admin_notify.line.enabled (Multi-Push > LINE > Enabled) | +| **ATK_ADMIN_NOTIFY_LINE_RECEIVERS** | `[USER_ID_1 GROUP_ID_1]` | Receivers | admin_notify.line.receivers (Multi-Push > LINE > Receivers) | +| **ATK_ADMIN_NOTIFY_NOISE_MODE** | `false` | Noise mode | admin_notify.noise_mode (Multi-Push > Noise mode) | +| **ATK_ADMIN_NOTIFY_NOTIFY_PENDING** | `false` | Pending comment still send notification (notifications are still sent when comments are intercepted) | admin_notify.notify_pending (Multi-Push > Pending comment still send notification) | +| **ATK_ADMIN_NOTIFY_NOTIFY_TPL** | `"default"` | Notification template (set to file path to use custom template) | admin_notify.notify_tpl (Multi-Push > Notification template) | +| **ATK_ADMIN_NOTIFY_SLACK_ENABLED** | `false` | 启用 | admin_notify.slack.enabled (Multi-Push > Slack > Enabled) | +| **ATK_ADMIN_NOTIFY_SLACK_OAUTH_TOKEN** | `""` | OauthToken | admin_notify.slack.oauth_token (Multi-Push > Slack > OauthToken) | +| **ATK_ADMIN_NOTIFY_SLACK_RECEIVERS** | `[CHANNEL_ID]` | Receivers | admin_notify.slack.receivers (Multi-Push > Slack > Receivers) | +| **ATK_ADMIN_NOTIFY_TELEGRAM_API_TOKEN** | `""` | ApiToken | admin_notify.telegram.api_token (Multi-Push > Telegram > ApiToken) | +| **ATK_ADMIN_NOTIFY_TELEGRAM_ENABLED** | `false` | 启用 | admin_notify.telegram.enabled (Multi-Push > Telegram > Enabled) | +| **ATK_ADMIN_NOTIFY_TELEGRAM_RECEIVERS** | `[7777777]` | Receivers | admin_notify.telegram.receivers (Multi-Push > Telegram > Receivers) | +| **ATK_ADMIN_NOTIFY_WEBHOOK_ENABLED** | `false` | 启用 | admin_notify.webhook.enabled (Multi-Push > WebHook > Enabled) | +| **ATK_ADMIN_NOTIFY_WEBHOOK_URL** | `""` | Url | admin_notify.webhook.url (Multi-Push > WebHook > Url) | + + +## Social Login + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_AUTH_ANONYMOUS** | `false` | Allow anonymous commenting (Allow skipping verification, only fill in an anonymous nickname and email) | auth.anonymous (Social Login > Allow anonymous commenting) | +| **ATK_AUTH_APPLE_CLIENT_ID** | `""` | ClientId | auth.apple.client_id (Social Login > Apple > ClientId) | +| **ATK_AUTH_APPLE_CLIENT_SECRET** | `""` | ClientSecret | auth.apple.client_secret (Social Login > Apple > ClientSecret) | +| **ATK_AUTH_APPLE_ENABLED** | `false` | 启用 | auth.apple.enabled (Social Login > Apple > Enabled) | +| **ATK_AUTH_AUTH0_CLIENT_ID** | `""` | ClientId | auth.auth0.client_id (Social Login > Auth0 > ClientId) | +| **ATK_AUTH_AUTH0_CLIENT_SECRET** | `""` | ClientSecret | auth.auth0.client_secret (Social Login > Auth0 > ClientSecret) | +| **ATK_AUTH_AUTH0_DOMAIN** | `""` | Domain | auth.auth0.domain (Social Login > Auth0 > Domain) | +| **ATK_AUTH_AUTH0_ENABLED** | `false` | 启用 | auth.auth0.enabled (Social Login > Auth0 > Enabled) | +| **ATK_AUTH_CALLBACK** | `"http://localhost:23366/api/v2/auth/{provider}/callback"` | Callback URL (https://example.com/api/v2/auth/{provider}/callback) | auth.callback (Social Login > Callback URL) | +| **ATK_AUTH_DISCORD_CLIENT_ID** | `""` | ClientId | auth.discord.client_id (Social Login > Discord > ClientId) | +| **ATK_AUTH_DISCORD_CLIENT_SECRET** | `""` | ClientSecret | auth.discord.client_secret (Social Login > Discord > ClientSecret) | +| **ATK_AUTH_DISCORD_ENABLED** | `false` | 启用 | auth.discord.enabled (Social Login > Discord > Enabled) | +| **ATK_AUTH_EMAIL_ENABLED** | `true` | Enable email password login | auth.email.enabled (Social Login > Email > Enable email password login) | +| **ATK_AUTH_EMAIL_VERIFY_SUBJECT** | `"Your Code - {{code}}"` | Verification email subject | auth.email.verify_subject (Social Login > Email > Verification email subject) | +| **ATK_AUTH_EMAIL_VERIFY_TPL** | `"default"` | Verification email template (set to file path to use custom template) | auth.email.verify_tpl (Social Login > Email > Verification email template) | +| **ATK_AUTH_ENABLED** | `false` | Enable Social Login | auth.enabled (Social Login > Enable Social Login) | +| **ATK_AUTH_FACEBOOK_CLIENT_ID** | `""` | ClientId | auth.facebook.client_id (Social Login > Facebook > ClientId) | +| **ATK_AUTH_FACEBOOK_CLIENT_SECRET** | `""` | ClientSecret | auth.facebook.client_secret (Social Login > Facebook > ClientSecret) | +| **ATK_AUTH_FACEBOOK_ENABLED** | `false` | 启用 | auth.facebook.enabled (Social Login > Facebook > Enabled) | +| **ATK_AUTH_GITEA_CLIENT_ID** | `""` | ClientId | auth.gitea.client_id (Social Login > Gitea > ClientId) | +| **ATK_AUTH_GITEA_CLIENT_SECRET** | `""` | ClientSecret | auth.gitea.client_secret (Social Login > Gitea > ClientSecret) | +| **ATK_AUTH_GITEA_ENABLED** | `false` | 启用 | auth.gitea.enabled (Social Login > Gitea > Enabled) | +| **ATK_AUTH_GITHUB_CLIENT_ID** | `""` | ClientId | auth.github.client_id (Social Login > GitHub > ClientId) | +| **ATK_AUTH_GITHUB_CLIENT_SECRET** | `""` | ClientSecret | auth.github.client_secret (Social Login > GitHub > ClientSecret) | +| **ATK_AUTH_GITHUB_ENABLED** | `false` | 启用 | auth.github.enabled (Social Login > GitHub > Enabled) | +| **ATK_AUTH_GITLAB_CLIENT_ID** | `""` | ClientId | auth.gitlab.client_id (Social Login > GitLab > ClientId) | +| **ATK_AUTH_GITLAB_CLIENT_SECRET** | `""` | ClientSecret | auth.gitlab.client_secret (Social Login > GitLab > ClientSecret) | +| **ATK_AUTH_GITLAB_ENABLED** | `false` | 启用 | auth.gitlab.enabled (Social Login > GitLab > Enabled) | +| **ATK_AUTH_GOOGLE_CLIENT_ID** | `""` | ClientId | auth.google.client_id (Social Login > Google > ClientId) | +| **ATK_AUTH_GOOGLE_CLIENT_SECRET** | `""` | ClientSecret | auth.google.client_secret (Social Login > Google > ClientSecret) | +| **ATK_AUTH_GOOGLE_ENABLED** | `false` | 启用 | auth.google.enabled (Social Login > Google > Enabled) | +| **ATK_AUTH_LINE_CLIENT_ID** | `""` | ClientId | auth.line.client_id (Social Login > Line > ClientId) | +| **ATK_AUTH_LINE_CLIENT_SECRET** | `""` | ClientSecret | auth.line.client_secret (Social Login > Line > ClientSecret) | +| **ATK_AUTH_LINE_ENABLED** | `false` | 启用 | auth.line.enabled (Social Login > Line > Enabled) | +| **ATK_AUTH_MASTODON_CLIENT_ID** | `""` | ClientId | auth.mastodon.client_id (Social Login > Mastodon > ClientId) | +| **ATK_AUTH_MASTODON_CLIENT_SECRET** | `""` | ClientSecret | auth.mastodon.client_secret (Social Login > Mastodon > ClientSecret) | +| **ATK_AUTH_MASTODON_ENABLED** | `false` | 启用 | auth.mastodon.enabled (Social Login > Mastodon > Enabled) | +| **ATK_AUTH_MICROSOFT_CLIENT_ID** | `""` | ClientId | auth.microsoft.client_id (Social Login > Microsoft > ClientId) | +| **ATK_AUTH_MICROSOFT_CLIENT_SECRET** | `""` | ClientSecret | auth.microsoft.client_secret (Social Login > Microsoft > ClientSecret) | +| **ATK_AUTH_MICROSOFT_ENABLED** | `false` | 启用 | auth.microsoft.enabled (Social Login > Microsoft > Enabled) | +| **ATK_AUTH_PATREON_CLIENT_ID** | `""` | ClientId | auth.patreon.client_id (Social Login > Patreon > ClientId) | +| **ATK_AUTH_PATREON_CLIENT_SECRET** | `""` | ClientSecret | auth.patreon.client_secret (Social Login > Patreon > ClientSecret) | +| **ATK_AUTH_PATREON_ENABLED** | `false` | 启用 | auth.patreon.enabled (Social Login > Patreon > Enabled) | +| **ATK_AUTH_SLACK_CLIENT_ID** | `""` | ClientId | auth.slack.client_id (Social Login > Slack > ClientId) | +| **ATK_AUTH_SLACK_CLIENT_SECRET** | `""` | ClientSecret | auth.slack.client_secret (Social Login > Slack > ClientSecret) | +| **ATK_AUTH_SLACK_ENABLED** | `false` | 启用 | auth.slack.enabled (Social Login > Slack > Enabled) | +| **ATK_AUTH_STEAM_API_KEY** | `""` | ApiKey | auth.steam.api_key (Social Login > Steam > ApiKey) | +| **ATK_AUTH_STEAM_ENABLED** | `false` | 启用 | auth.steam.enabled (Social Login > Steam > Enabled) | +| **ATK_AUTH_TIKTOK_CLIENT_ID** | `""` | ClientId | auth.tiktok.client_id (Social Login > Tiktok > ClientId) | +| **ATK_AUTH_TIKTOK_CLIENT_SECRET** | `""` | ClientSecret | auth.tiktok.client_secret (Social Login > Tiktok > ClientSecret) | +| **ATK_AUTH_TIKTOK_ENABLED** | `false` | 启用 | auth.tiktok.enabled (Social Login > Tiktok > Enabled) | +| **ATK_AUTH_TWITTER_CLIENT_ID** | `""` | ClientId | auth.twitter.client_id (Social Login > Twitter > ClientId) | +| **ATK_AUTH_TWITTER_CLIENT_SECRET** | `""` | ClientSecret | auth.twitter.client_secret (Social Login > Twitter > ClientSecret) | +| **ATK_AUTH_TWITTER_ENABLED** | `false` | 启用 | auth.twitter.enabled (Social Login > Twitter > Enabled) | +| **ATK_AUTH_WECHAT_CLIENT_ID** | `""` | ClientId | auth.wechat.client_id (Social Login > WeChat > ClientId) | +| **ATK_AUTH_WECHAT_CLIENT_SECRET** | `""` | ClientSecret | auth.wechat.client_secret (Social Login > WeChat > ClientSecret) | +| **ATK_AUTH_WECHAT_ENABLED** | `false` | 启用 | auth.wechat.enabled (Social Login > WeChat > Enabled) | + + +## Cache + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_CACHE_ENABLED** | `false` | Enable cache | cache.enabled (Cache > Enable cache) | +| **ATK_CACHE_EXPIRES** | `30` | Cache expiration time (in minutes) | cache.expires (Cache > Cache expiration time) | +| **ATK_CACHE_REDIS_DB** | `0` | Redis database number (e.g. 0) | cache.redis.db (Cache > Redis config > Redis database number) | +| **ATK_CACHE_REDIS_NETWORK** | `"tcp"` | Connection type (可选:`["tcp", "unix"]`) | cache.redis.network (Cache > Redis config > Connection type) | +| **ATK_CACHE_REDIS_PASSWORD** | `""` | Redis password | cache.redis.password (Cache > Redis config > Redis password) | +| **ATK_CACHE_REDIS_USERNAME** | `""` | Redis username | cache.redis.username (Cache > Redis config > Redis username) | +| **ATK_CACHE_SERVER** | `""` | Cache server address (e.g. "localhost:6379") | cache.server (Cache > Cache server address) | +| **ATK_CACHE_TYPE** | `"builtin"` | Cache type (可选:`["redis", "memcache", "builtin"]`) | cache.type (Cache > Cache type) | +| **ATK_CACHE_WARM_UP** | `false` | Cache warm up (warm up cache when program starts) | cache.warm_up (Cache > Cache warm up) | + + +## Captcha + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_CAPTCHA_ACTION_LIMIT** | `3` | Action limit (the number of actions required to activate captcha) | captcha.action_limit (Captcha > Action limit) | +| **ATK_CAPTCHA_ACTION_RESET** | `60` | Reset Timeout (timeout to reset action counter. unit: s, set to -1 to disable) | captcha.action_reset (Captcha > Reset Timeout) | +| **ATK_CAPTCHA_ALWAYS** | `false` | Captcha is required always | captcha.always (Captcha > Captcha is required always) | +| **ATK_CAPTCHA_CAPTCHA_TYPE** | `"image"` | Captcha type (可选:`["image", "turnstile", "recaptcha", "hcaptcha", "geetest"]`) | captcha.captcha_type (Captcha > Captcha type) | +| **ATK_CAPTCHA_ENABLED** | `true` | Enable captcha | captcha.enabled (Captcha > Enable captcha) | +| **ATK_CAPTCHA_GEETEST_CAPTCHA_ID** | `""` | CaptchaId | captcha.geetest.captcha_id (Captcha > Geetest > CaptchaId) | +| **ATK_CAPTCHA_GEETEST_CAPTCHA_KEY** | `""` | CaptchaKey | captcha.geetest.captcha_key (Captcha > Geetest > CaptchaKey) | +| **ATK_CAPTCHA_HCAPTCHA_SECRET_KEY** | `""` | SecretKey | captcha.hcaptcha.secret_key (Captcha > hCaptcha > SecretKey) | +| **ATK_CAPTCHA_HCAPTCHA_SITE_KEY** | `""` | SiteKey | captcha.hcaptcha.site_key (Captcha > hCaptcha > SiteKey) | +| **ATK_CAPTCHA_RECAPTCHA_SECRET_KEY** | `""` | SecretKey | captcha.recaptcha.secret_key (Captcha > reCaptcha > SecretKey) | +| **ATK_CAPTCHA_RECAPTCHA_SITE_KEY** | `""` | SiteKey | captcha.recaptcha.site_key (Captcha > reCaptcha > SiteKey) | +| **ATK_CAPTCHA_TURNSTILE_SECRET_KEY** | `""` | SecretKey | captcha.turnstile.secret_key (Captcha > Turnstile > SecretKey) | +| **ATK_CAPTCHA_TURNSTILE_SITE_KEY** | `""` | SiteKey | captcha.turnstile.site_key (Captcha > Turnstile > SiteKey) | + + +## Database + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_DB_CHARSET** | `"utf8mb4"` | Database charset | db.charset (Database > Database charset) | +| **ATK_DB_FILE** | `"./data/artalk.db"` | Database file (only for SQLite) | db.file (Database > Database file) | +| **ATK_DB_HOST** | `"localhost"` | Host address | db.host (Database > Host address) | +| **ATK_DB_NAME** | `"artalk"` | Database name | db.name (Database > Database name) | +| **ATK_DB_PASSWORD** | `""` | Database password | db.password (Database > Database password) | +| **ATK_DB_PORT** | `3306` | Host port | db.port (Database > Host port) | +| **ATK_DB_PREPARE_STMT** | `true` | Prepared Statement | db.prepare_stmt (Database > Prepared Statement) | +| **ATK_DB_SSL** | `false` | Enable SSL mode | db.ssl (Database > Enable SSL mode) | +| **ATK_DB_TABLE_PREFIX** | `""` | Table prefix (e.g. "atk_") | db.table_prefix (Database > Table prefix) | +| **ATK_DB_TYPE** | `"sqlite"` | Database type (可选:`["sqlite", "mysql", "pgsql", "mssql"]`) | db.type (Database > Database type) | +| **ATK_DB_USER** | `"root"` | Database user | db.user (Database > Database user) | + + +## Email + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_EMAIL_ALI_DM_ACCESS_KEY_ID** | `""` | AccessKeyId | email.ali_dm.access_key_id (Email > Aliyun mail push > AccessKeyId) | +| **ATK_EMAIL_ALI_DM_ACCESS_KEY_SECRET** | `""` | AccessKeySecret | email.ali_dm.access_key_secret (Email > Aliyun mail push > AccessKeySecret) | +| **ATK_EMAIL_ALI_DM_ACCOUNT_NAME** | `"noreply@example.com"` | AccountName | email.ali_dm.account_name (Email > Aliyun mail push > AccountName) | +| **ATK_EMAIL_ENABLED** | `false` | Enable email notification | email.enabled (Email > Enable email notification) | +| **ATK_EMAIL_MAIL_SUBJECT** | `"[{{site_name}}] You got a reply from @{{reply_nick}}"` | Email subject | email.mail_subject (Email > Email subject) | +| **ATK_EMAIL_MAIL_TPL** | `"default"` | Email template file (set to file path to use custom template) | email.mail_tpl (Email > Email template file) | +| **ATK_EMAIL_SEND_ADDR** | `"noreply@example.com"` | Email address of sender | email.send_addr (Email > Email address of sender) | +| **ATK_EMAIL_SEND_NAME** | `"{{reply_nick}}"` | Nick name of sender | email.send_name (Email > Nick name of sender) | +| **ATK_EMAIL_SEND_TYPE** | `"smtp"` | Send method (可选:`["smtp", "ali_dm", "sendmail"]`) | email.send_type (Email > Send method) | +| **ATK_EMAIL_SMTP_HOST** | `"smtp.qq.com"` | Email address of sender | email.smtp.host (Email > SMTP send > Email address of sender) | +| **ATK_EMAIL_SMTP_PASSWORD** | `""` | Password | email.smtp.password (Email > SMTP send > Password) | +| **ATK_EMAIL_SMTP_PORT** | `587` | Email port | email.smtp.port (Email > SMTP send > Email port) | +| **ATK_EMAIL_SMTP_USERNAME** | `"example@qq.com"` | Email address of sender | email.smtp.username (Email > SMTP send > Email address of sender) | + + +## UI Settings + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_FRONTEND_DARKMODE** | `"inherit"` | Dark mode (可选:`["inherit", "auto"]`) | frontend.darkMode (UI Settings > Dark mode) | +| **ATK_FRONTEND_EDITORTRAVEL** | `true` | Movable comment box | frontend.editorTravel (UI Settings > Movable comment box) | +| **ATK_FRONTEND_EMOTICONS** | `"https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json"` | Emoticons | frontend.emoticons (UI Settings > Emoticons) | +| **ATK_FRONTEND_FLATMODE** | `"auto"` | Flatten mode (可选:`["auto", "true", "false"]`) | frontend.flatMode (UI Settings > Flatten mode) | +| **ATK_FRONTEND_GRAVATAR_MIRROR** | `"https://www.gravatar.com/avatar/"` | API URL | frontend.gravatar.mirror (UI Settings > Gravatar > API URL) | +| **ATK_FRONTEND_GRAVATAR_PARAMS** | `"sha256=1&d=mp&s=240"` | API parameters | frontend.gravatar.params (UI Settings > Gravatar > API parameters) | +| **ATK_FRONTEND_HEIGHTLIMIT_CHILDREN** | `400` | Sub-comment area height limit (unit: px) | frontend.heightLimit.children (UI Settings > Content height limit > Sub-comment area height limit) | +| **ATK_FRONTEND_HEIGHTLIMIT_CONTENT** | `300` | Comment content height limit (unit: px) | frontend.heightLimit.content (UI Settings > Content height limit > Comment content height limit) | +| **ATK_FRONTEND_HEIGHTLIMIT_SCROLLABLE** | `false` | Scrollable (scrollable height limit area) | frontend.heightLimit.scrollable (UI Settings > Content height limit > Scrollable) | +| **ATK_FRONTEND_IMGLAZYLOAD** | `false` | Image lazy load (可选:`["false", "native", "data-src"]`) | frontend.imgLazyLoad (UI Settings > Image lazy load) | +| **ATK_FRONTEND_LISTSORT** | `true` | Comment sorting | frontend.listSort (UI Settings > Comment sorting) | +| **ATK_FRONTEND_NESTMAX** | `2` | Maximum nesting level | frontend.nestMax (UI Settings > Maximum nesting level) | +| **ATK_FRONTEND_NESTSORT** | `"DATE_ASC"` | Nesting comment sorting rules (可选:`["DATE_ASC", "DATE_DESC", "VOTE_UP_DESC"]`) | frontend.nestSort (UI Settings > Nesting comment sorting rules) | +| **ATK_FRONTEND_NOCOMMENT** | `""` | Text to display when there is | frontend.noComment (UI Settings > Text to display when there is) | +| **ATK_FRONTEND_PAGINATION_AUTOLOAD** | `true` | Scroll loading | frontend.pagination.autoLoad (UI Settings > Comment pagination > Scroll loading) | +| **ATK_FRONTEND_PAGINATION_PAGESIZE** | `20` | Number of comments per page | frontend.pagination.pageSize (UI Settings > Comment pagination > Number of comments per page) | +| **ATK_FRONTEND_PAGINATION_READMORE** | `true` | Load more mode (disabled to use pagination bar) | frontend.pagination.readMore (UI Settings > Comment pagination > Load more mode) | +| **ATK_FRONTEND_PLACEHOLDER** | `""` | Comment box placeholder | frontend.placeholder (UI Settings > Comment box placeholder) | +| **ATK_FRONTEND_PLUGINURLS** | `[]` | Plugins | frontend.pluginURLs (UI Settings > Plugins) | +| **ATK_FRONTEND_PREVIEW** | `true` | Editor real-time preview | frontend.preview (UI Settings > Editor real-time preview) | +| **ATK_FRONTEND_REQTIMEOUT** | `15000` | Request timeout (unit: ms) | frontend.reqTimeout (UI Settings > Request timeout) | +| **ATK_FRONTEND_SENDBTN** | `""` | Text of the send button | frontend.sendBtn (UI Settings > Text of the send button) | +| **ATK_FRONTEND_UABADGE** | `false` | User UA badge | frontend.uaBadge (UI Settings > User UA badge) | +| **ATK_FRONTEND_VERSIONCHECK** | `true` | Version check | frontend.versionCheck (UI Settings > Version check) | +| **ATK_FRONTEND_VOTE** | `true` | Vote button | frontend.vote (UI Settings > Vote button) | +| **ATK_FRONTEND_VOTEDOWN** | `false` | Dislike button | frontend.voteDown (UI Settings > Dislike button) | + + +## Web server + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_HTTP_BODY_LIMIT** | `100` | Body size limit (unit: MB) | http.body_limit (Web server > Body size limit) | +| **ATK_HTTP_PROXY_HEADER** | `""` | Proxy Header (fill `X-Forwarded-For` to get user real IP if behind a trusted reverse proxy or CDN) | http.proxy_header (Web server > Proxy Header) | + + +## Upload + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_IMG_UPLOAD_ENABLED** | `true` | Enable image upload | img_upload.enabled (Upload > Enable image upload) | +| **ATK_IMG_UPLOAD_MAX_SIZE** | `5` | Image size limit (unit: MB) | img_upload.max_size (Upload > Image size limit) | +| **ATK_IMG_UPLOAD_PATH** | `"./data/artalk-img/"` | Image storage | img_upload.path (Upload > Image storage) | +| **ATK_IMG_UPLOAD_PUBLIC_PATH** | `` | Image link base path (default: "/static/images/") | img_upload.public_path (Upload > Image link base path) | +| **ATK_IMG_UPLOAD_UPGIT_DEL_LOCAL** | `true` | Delete local image after upload success | img_upload.upgit.del_local (Upload > Upgit config > Delete local image after upload success) | +| **ATK_IMG_UPLOAD_UPGIT_ENABLED** | `false` | Enable Upgit | img_upload.upgit.enabled (Upload > Upgit config > Enable Upgit) | +| **ATK_IMG_UPLOAD_UPGIT_EXEC** | `"upgit -c UPGIT_CONF_FILE_PATH -t /artalk-img"` | Command line arguments | img_upload.upgit.exec (Upload > Upgit config > Command line arguments) | + + +## Logging + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_LOG_ENABLED** | `true` | Enable logging | log.enabled (Logging > Enable logging) | +| **ATK_LOG_FILENAME** | `"./data/artalk.log"` | Log file path | log.filename (Logging > Log file path) | + + +## Moderator + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_MODERATOR_AKISMET_KEY** | `""` | Akismet Key (Akismet anti-spam service, https://akismet.com) | moderator.akismet_key (Moderator > Akismet Key) | +| **ATK_MODERATOR_ALIYUN_ACCESS_KEY_ID** | `""` | AccessKeyId | moderator.aliyun.access_key_id (Moderator > Aliyun Content Security > AccessKeyId) | +| **ATK_MODERATOR_ALIYUN_ACCESS_KEY_SECRET** | `""` | AccessKeySecret | moderator.aliyun.access_key_secret (Moderator > Aliyun Content Security > AccessKeySecret) | +| **ATK_MODERATOR_ALIYUN_ENABLED** | `false` | 启用 | moderator.aliyun.enabled (Moderator > Aliyun Content Security > Enabled) | +| **ATK_MODERATOR_ALIYUN_REGION** | `"cn-shanghai"` | Region | moderator.aliyun.region (Moderator > Aliyun Content Security > Region) | +| **ATK_MODERATOR_API_FAIL_BLOCK** | `false` | Block when API request fails (set to false to let comments pass when API request fails) | moderator.api_fail_block (Moderator > Block when API request fails) | +| **ATK_MODERATOR_KEYWORDS_ENABLED** | `false` | Enable keyword filter | moderator.keywords.enabled (Moderator > Keyword filter > Enable keyword filter) | +| **ATK_MODERATOR_KEYWORDS_FILE_SEP** | `"\n"` | FileSep | moderator.keywords.file_sep (Moderator > Keyword filter > FileSep) | +| **ATK_MODERATOR_KEYWORDS_FILES** | `[./data/keywords_1.txt]` | Dictionary file (support multiple dictionary files) | moderator.keywords.files (Moderator > Keyword filter > Dictionary file) | +| **ATK_MODERATOR_KEYWORDS_PENDING** | `false` | Set to pending when match | moderator.keywords.pending (Moderator > Keyword filter > Set to pending when match) | +| **ATK_MODERATOR_KEYWORDS_REPLACE_TO** | `"x"` | ReplaceTo | moderator.keywords.replace_to (Moderator > Keyword filter > ReplaceTo) | +| **ATK_MODERATOR_PENDING_DEFAULT** | `false` | Default pending (new comments need to be approved by admin) | moderator.pending_default (Moderator > Default pending) | +| **ATK_MODERATOR_TENCENT_ENABLED** | `false` | 启用 | moderator.tencent.enabled (Moderator > Tencent Cloud Content Security > Enabled) | +| **ATK_MODERATOR_TENCENT_REGION** | `"ap-guangzhou"` | Region | moderator.tencent.region (Moderator > Tencent Cloud Content Security > Region) | +| **ATK_MODERATOR_TENCENT_SECRET_ID** | `""` | SecretId | moderator.tencent.secret_id (Moderator > Tencent Cloud Content Security > SecretId) | +| **ATK_MODERATOR_TENCENT_SECRET_KEY** | `""` | SecretKey | moderator.tencent.secret_key (Moderator > Tencent Cloud Content Security > SecretKey) | + + +## SSL + +| 环境变量 | 默认值 | 描述 | 路径 | +| --- | --- | --- | --- | +| **ATK_SSL_CERT_PATH** | `""` | Certificate file path (e.g. "/etc/letsencrypt/live/example.com/fullchain.pem") | ssl.cert_path (SSL > Certificate file path) | +| **ATK_SSL_ENABLED** | `false` | Enable SSL | ssl.enabled (SSL > Enable SSL) | +| **ATK_SSL_KEY_PATH** | `""` | Key file path (e.g. "/etc/letsencrypt/live/example.com/privkey.pem") | ssl.key_path (SSL > Key file path) | + + +
+ +## Developers + +Enable developer mode by setting `ATK_DEBUG=1`. + +This document is auto-generated by the Artalk developer tool. Run `make update-conf-docs` to update this page's content based on the template configuration file ([conf/artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/tree/master/conf/artalk.example.zh-CN.yml)). + +Related code can be found in the [@ArtalkJS/Artalk:/internal/config/](https://github.com/ArtalkJS/Artalk/tree/master/internal/config/) directory. diff --git a/docs/docs/en/guide/extras.md b/docs/docs/en/guide/extras.md new file mode 100644 index 000000000..a1446d5ca --- /dev/null +++ b/docs/docs/en/guide/extras.md @@ -0,0 +1,3 @@ +# 📚 Further reading + +【TODO】 diff --git a/docs/docs/en/guide/frontend/artalk-lite.md b/docs/docs/en/guide/frontend/artalk-lite.md new file mode 100644 index 000000000..4e0e5a2ce --- /dev/null +++ b/docs/docs/en/guide/frontend/artalk-lite.md @@ -0,0 +1,13 @@ +# ArtalkLite Overview + +ArtalkLite is a simplified version of Artalk, with the following differences compared to the standard version: + +- Smaller size and more streamlined. +- Emojis, voting, and UA badges are disabled by default. +- Removed the dependency on marked, but supports basic Markdown syntax. + +ArtalkLite is released alongside the standard version. You can obtain it by modifying the file name in the CDN address to ArtalkLite: + +> https://unpkg.com/artalk@2/dist/ArtalkLite.js +> +> https://unpkg.com/artalk@2/dist/ArtalkLite.css diff --git a/docs/docs/en/guide/frontend/auth.md b/docs/docs/en/guide/frontend/auth.md new file mode 100644 index 000000000..c798f3492 --- /dev/null +++ b/docs/docs/en/guide/frontend/auth.md @@ -0,0 +1,75 @@ +# Social Login + +By default, Artalk allows users to post comments by simply filling in their nickname and email without email verification. + +However, sometimes we want users to log in with their social accounts to reduce the time spent filling in information or to increase the authenticity of user information. This can be achieved by enabling social login. + +Currently, the following social login methods are supported: + +| Login Method | Integration Docs | Login Method | Integration Docs | Login Method | Integration Docs | +| ------------ | ---------------- | ------------ | ---------------- | ------------ | ---------------- | +| Google | [View](https://developers.google.com/identity/protocols/oauth2) | Microsoft | [View](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow) | Apple | [View](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/configuring_your_webpage_for_sign_in_with_apple) | +| Facebook | [View](https://developers.facebook.com/docs/facebook-login/) | Twitter | [View](https://developer.twitter.com/en/docs/basics/authentication/overview) | Discord | [View](https://discord.com/developers/docs/topics/oauth2) | +| Slack | [View](https://api.slack.com/authentication/oauth-v2) | GitHub | [View](https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/) | TikTok | [View](https://developers.tiktok.com/doc/login) | +| Steam | [View](https://partner.steamgames.com/doc/webapi_overview/auth) | WeChat | [View](https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html) | Line | [View](https://developers.line.biz/en/docs/line-login/integrate-line-login/) | +| GitLab | [View](https://docs.gitlab.com/ee/api/oauth2.html) | Gitea | [View](https://docs.gitea.io/en-us/oauth2-provider/) | Mastodon | [View](https://docs.joinmastodon.org/api/authentication/) | +| Patreon | [View](https://docs.patreon.com/#oauth) | Auth0 | [View](https://auth0.com/docs/connections/social/) | Email & Password | [View](#email-password-login) | + +To enable social login, simply find the "Social Login" option in the [Dashboard](./sidebar.md#settings), enable it, and fill in the corresponding configuration information. Alternatively, you can configure it through the [configuration file](../backend/config.md) or [environment variables](../env.md#social-login). + +## Email & Password Login + +![Email Login](/images/auth/email_login.png) + +After enabling email and password login, the nickname and email input fields at the top of the comment box will be hidden, and the send button will change to a login button. When the user clicks the login button, a login box will pop up, allowing the user to log in with their email and password. Once logged in, the user can post comments. Comments posted by the user will display a "Email Verified" badge. + +Email Verified Badge + +Users can register an account via email, and Artalk will send a verification code to their email. The verification code is valid for 10 minutes, and the frequency of sending verification codes is limited to once per minute. + +![Email Registration](/images/auth/email_register.png) + +You can customize the verification email template and subject. In the settings page of the Artalk Dashboard under social login, you can find options for "Email Verification Subject" and "Email Verification Template". In the configuration file, you can set them using `auth.email.verify_subject` and `auth.email.verify_tpl`: + +```yaml +auth: + enabled: true + email: + enabled: true + verify_subject: "Your verification code is - {{code}}" + verify_tpl: default +``` + +The default template is as follows: + +```html +Your verification code is: {{code}}. Please use it to verify your email and log in to Artalk. If you did not request this, please ignore this message. +``` + +![Skip Login](/images/auth/login_skip.png) + +After enabling email and password login, users can still skip email verification: the login popup will show a "Skip, do not verify" button at the bottom, which, when clicked, restores the original nickname, email, and website input fields at the top of the comment box. You can change this by selecting "Allow Anonymous Comments" in the settings. + +## Account Merging Tool + +If multiple accounts with different usernames but the same email are detected after logging in, an account merging tool will pop up. Users can choose to keep one username, and all comments and data associated with that email will be merged into the retained account. The original accounts will be deleted, and the displayed username on comments will change to the retained username. + +![Account Merging Tool](/images/auth/merge_accounts.png) + +## Multiple Login Methods + +Artalk supports enabling multiple login methods simultaneously, allowing users to choose any method to log in. + +![Multiple Login Methods](/images/auth/multi_login.png) + +If only one login method is enabled, such as GitHub login, the GitHub authorization login page will pop up directly. + +![GitHub Authorization Popup](/images/auth/github_login.png) + +For integrating GitHub login, refer to the documentation: [About Creating GitHub Apps](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app). After obtaining the Client ID and Client Secret, fill them in the "GitHub" option in the social login settings page of the Artalk Dashboard. + +## Plugin Development + +The social login feature of Artalk is implemented through an independent plugin developed using Solid.js. The code can be found in [@ArtalkJS/Artalk:ui/plugin-auth](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-auth). + +After enabling the social login feature in the Dashboard, the plugin will be automatically loaded on the front end. diff --git a/docs/docs/en/guide/frontend/config.md b/docs/docs/en/guide/frontend/config.md new file mode 100644 index 000000000..385ebff8a --- /dev/null +++ b/docs/docs/en/guide/frontend/config.md @@ -0,0 +1,520 @@ +# Interface Configuration + +You can modify the interface configuration in the "[Dashboard](./sidebar.md)" without changing the front-end code. Additionally, configuration files and environment variables are also supported. + +The priority of interface configuration is as follows: + +``` +Environment Variables > Configuration File = Dashboard > Front-end Code +``` + +## Configuring the Interface via `Artalk.init` + +When initializing with `Artalk.init` on the front-end page, pass parameters to configure the interface. Below are all the available configuration options. + +```js +const artalk = Artalk.init({ + el: '#Comments', + pageKey: '/post/1', + pageTitle: 'Page Title', + server: 'http://your_domain:8080', + site: 'Artalk Blog', +}) + +// Update configuration +artalk.update({ ... }) +``` + +- Default Configuration: [defaults.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/defaults.ts) +- Declaration File: [config.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/config.ts) + +## Basic Configuration (Required) + +### el + +**Mount Element** (Specify the element selector to bind) + +- Type: `String|HTMLElement` +- Default: `undefined` + +> Example: `#Comments` corresponds to the element `
` + +### pageKey + +**Page Address** (Relative path / full URL) + +- Type: `String` +- Default: `location.pathname` + +Leave empty to automatically get the relative path of the page. + +You can fill in the `permalink` generated by the blog system, but it is recommended to use the relative path for easier domain switching in the future. + +Reference: [Using Relative / Absolute Paths](../backend/relative-path.md) + +### pageTitle + +**Page Title** (Used for management list display, email notifications, etc.) + +- Type: `String` +- Default: `document.title` + +Leave empty to automatically get the value of the `` tag of the page. + +### server + +**Backend Program API Address** + +- Type: `String` +- Default: `undefined` + +Deploy the backend and ensure that the backend address is accessible from the front end. + +> Example: http://yourdomain.xxx + +### site + +**Site Name** + +- Type: `String` +- Default: `undefined` + +Artalk supports unified management of multiple sites, this item is used for site isolation. + +### useBackendConf + +**Refer to Backend Configuration** + +- Type: `Boolean` +- Default: `true` (enabled by default) + +You can define the front-end configuration in the backend configuration file, so that the front-end configuration always refers to the backend. + +## Internationalization (i18n) + +### locale + +**Language** + +- Type: `String|Object|"auto"` +- Default: `"zh-CN"` + +Following the Unicode BCP 47 standard, the default is "zh-CN" (Simplified Chinese). + +Feel free to submit a PR to help translate Artalk into multiple languages and contribute to the community! + +For details, see: [Localization](./i18n.md) + +### dateFormatter + +**Date Formatting Function** + +- Type: `(date: Date) => string` +- Default: `undefined` + +By default, it shows a few seconds ago, a few minutes ago, a few hours ago, a few days ago, and if it exceeds 7 days, it shows the specific date in the format `YYYY-MM-DD`. + +You can also customize the date formatting function. Below is an example using [toLocaleString](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) and [dayjs](https://day.js.org/) to format dates. + +```js +import dayjs from 'dayjs' + +Artalk.init({ + dateFormatter: (date) => { + // return date.toLocaleString() // '2024/8/28 17:51:31' + return dayjs(date).fromNow("MMMM D, YYYY h:mm A") // 'August 28, 2024 5:51 PM' + }, +}) +``` + +## Requests + +### reqTimeout + +**Request Timeout** + +- Type: `Number` +- Default: `15000` + +Automatically disconnects the request and reports an error if the request time exceeds this value (unit: milliseconds). + +## Emoticons + +### emoticons + +**Emoticons** + +- Type: `Object|Array|String|Boolean` +- Default: "[https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json](https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json)" + +For details: [Frontend · Emoticons](./emoticons.md) + +Now compatible with [OwO format](https://github.com/DIYgod/OwO), supports dynamic loading by URL. + +Set to `false` to disable the emoticon feature. + +## Interface + +### placeholder + +**Comment Box Placeholder Text** + +- Type: `String` +- Default: `"Type something..."` + +### noComment + +**Text Displayed When There Are No Comments** + +- Type: `String` +- Default: `"「Silence is golden」"` + +### sendBtn + +**Send Button Text** + +- Type: `String` +- Default: `"Post Comment"` + +### editorTravel + +**Comment Box Travel** + +- Type: `Boolean` +- Default: `true` + +Set to `true` to move the comment box to the position of the comment being replied to, instead of keeping it fixed. + +### darkMode + +**Dark Mode** + +- Type: `Boolean|"auto"` +- Default: `false` + +When Artalk is instantiated, it reads this value and chooses whether to enable dark mode (can be used with the blog theme). + +To dynamically modify darkMode: + +```js +artalk.setDarkMode(true) +``` + +> Reference code: “[index.html](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/index.html#L97-L150)” + +Set to `"auto"`, Artalk will listen to `(prefers-color-scheme: dark)` and automatically switch to dark mode based on the user's operating system settings. + +### flatMode + +**Flat Mode** + +- Type: `Boolean|"auto"` +- Default: `"auto"` + +By default, `"auto"` automatically enables "flat mode" on small screen devices (screen width < 768px). + +Set to `true` to display comments in "flat mode". + +Set to `false` to display comments in "nested mode". + +### nestMax + +**Maximum Nested Levels** + +- Type: `Number` +- Default: `2` + +Maximum nested levels for comments in "nested mode". + +### nestSort + +**Sorting Rules for Nested Comments** + +- Type: `"DATE_ASC"|"DATE_DESC"|"VOTE_UP_DESC"` +- Default: `"DATE_ASC"` + +By default, nested comments are sorted in ascending order by date (new comments at the end). + +## Features + +### pvEl + +**Page Views (PV) Binding Element** + +- Type: `String` +- Default: `".artalk-pv-count"` + +You can place an HTML tag anywhere on the page: `<span class="artalk-pv-count"></span>` + +When Artalk finishes loading, it displays the page views. + +This item specifies the selector of the binding element, defaulting to `.artalk-pv-count`. + +### countEl + +**Comment Count Binding Element** + +- Type: `String` +- Default: `".artalk-comment-count"` + +You can place an HTML tag anywhere on the page: `<span class="artalk-comment-count"></span>` to display the current page's comment count. + +::: tip + +Both pvEl and countEl element tags can set the `data-page-key` attribute to specify the statistics of a particular page, for example: `<span class="artalk-comment-count" data-page-key="/t/1.html"></span>` + +For details, see: [PV Statistics](./pv.md#Loading statistics for multiple pages simultaneously) + +::: + +### statPageKeyAttr + +**Statistical Component PageKey Attribute Name** + +- Type: `String` +- Default: `"data-page-key"` + +When querying comment counts and page views, Artalk's statistical component uses this attribute name to query the specified page, for example: `<span data-page-key="/t/1.html"></span>`. + +To facilitate theme adaptation, you can customize the attribute name as needed, for example, replacing it with `data-path`, the HTML tag would be `<span data-path="/t/1.html"></span>`. + +### vote + +**Voting Buttons** + +- Type: `Boolean` +- Default: `true` + +Enable the comment voting feature (upvote / downvote). + +### voteDown + +**Downvote Button** + +- Type: `Boolean` +- Default: `false` + +Downvote button (hidden by default). + +### uaBadge + +**Display User's UserAgent Information Badge** + +- Type: `Boolean` +- Default: `false` + +### listSort + +**Comment Sorting Feature** + +- Type: `Boolean` +- Default: `true` + +Hover over the "n comments" in the top left of the comment list to display a floating dropdown, allowing the comment list to be sorted and filtered according to "latest / hottest / earliest / author". + +### imgUpload + +**Image Upload Feature** + +- Type: `Boolean` +- Default: `true` + +This configuration item automatically follows the backend. When the backend image upload feature is disabled, only administrators will see the image upload button. + +### imgUploader + +**Image Uploader** + +- Type: `(file: File) => Promise<string>` +- Default: `undefined` + +Custom image uploader, for example: + +```js +Artalk.init({ + imgUploader: async (file) => { + const form = new FormData() + form.set('file', file) + + const imgUrl = await fetch('https://api.example.org/upload', { + method: 'POST', + body: form, + }) + + return imgUrl + }, +}) +``` + +### imgLazyLoad + +**Lazy Load Images** + +- Type: `"native"|"data-src"|Boolean` +- Default: `false` + +Enable lazy loading of images in comments. + +For details, see: [Lazy Load Images](./img-lazy-load.md) + +### preview + +**Editor Real-Time Preview Feature** + +- Type: `Boolean` +- Default: `true` + +Display the "Preview" button in the editor. + +## Avatars + +```js +gravatar: { + mirror: '<Gravatar Mirror URL>', + default: 'mp', +} +``` + +### gravatar.mirror + +**Gravatar Mirror URL** + +- Type: `String` +- Default: `"https://www.gravatar.com/avatar/"` + +If you find Gravatar avatar loading speed unsatisfactory, you can try replacing it. + +For example: + +> WeAvatar: https://weavatar.com/avatar/ +> +> Cravatar: https://cravatar.cn/avatar/ +> +> V2EX: https://cdn.v2ex.com/gravatar/ +> +> Geekzu: https://sdn.geekzu.org/avatar/ +> +> Loli: https://gravatar.loli.net/avatar/ + +### gravatar.params + +**Gravatar API Parameters** + +- Type: `String` +- Default: `"sha256=1&d=mp&s=240"` + +For example, you can set the default avatar (`d=mp`) and avatar size (`s=240`) through this configuration item. + +Reference: [Gravatar API Documentation](http://cn.gravatar.org/site/implement/images/) + +This configuration item is in HTTP Query format. + +::: warning Update Notice + +v2.8.7 supports generating Gravatar avatar links using the SHA256 encryption algorithm to enhance user privacy protection. Please include `sha256=1` in `params` to enable this encryption ([#874](https://github.com/ArtalkJS/Artalk/issues/874)). + +v2.5.5 deprecated the `gravatar.default` configuration item; please use `gravatar.params` instead. + +::: + +### avatarURLBuilder + +**Avatar URL Builder** + +- Type: `(comment: CommentData) => string` +- Default: `undefined` + +Custom user avatar image URL generator, for example: + +```js +Artalk.init({ + avatarURLBuilder: (comment) => { + return `/api/avatar?email=${comment.email_encrypted}` + }, +}) +``` + +## Comment Pagination + +```js +pagination: { + pageSize: 20, // Number of comments per page + readMore: true, // Load more or pagination + autoLoad: true, // Auto-load (load more) +} +``` + +### pagination.readMore + +**Load More Mode** + +- Type: `Boolean` +- Default: `true` + +Set to `true` for "Load More" mode. + +Set to `false` for "Pagination" mode. + +### pagination.autoLoad + +**Auto-Load on Scroll** + +- Type: `Boolean` +- Default: `true` + +(Must enable "Load More" mode by setting `readMore` to `true`) + +### pagination.pageSize + +**Number of Comments Per Request** + +- Type: `Number` +- Default: `20` + +## Content Height Limit + +Content exceeding the set height will be hidden, and a "Read More" button will be displayed. + +```js +heightLimit: { + content: 300, // Comment content height limit + children: 400, // Child comment area height limit + scrollable: false, // Height limit scrolling +} +``` + +### heightLimit.content + +**Comment Content Height Limit** + +- Type: `Number` +- Default: `300` + +> Set to 0 to disable height limit. + +### heightLimit.children + +**Child Comment Area Height Limit** + +- Type: `Number` +- Default: `400` + +### heightLimit.scrollable + +**Scrollable Height Limit Area** + +- Type: `Boolean` +- Default: `false` + +Allow height limit area to scroll. + +## Version Check + +### versionCheck + +**Version Check** + +- Type: `Boolean` +- Default: `true` + +Display a warning prompt when the front-end and back-end versions are incompatible. diff --git a/docs/docs/en/guide/frontend/emoticons.md b/docs/docs/en/guide/frontend/emoticons.md new file mode 100644 index 000000000..74bf81e78 --- /dev/null +++ b/docs/docs/en/guide/frontend/emoticons.md @@ -0,0 +1,180 @@ +# Emoticons + +You can modify this configuration in the settings interface of the [Dashboard](./sidebar.md#设置), or through [configuration files](../backend/config.md#界面配置-frontend) and [environment variables](../env.md#界面配置). + +In the configuration file, you can fill in the URL of the emoticon list under `frontend.emoticons`: + +```yaml +frontend: + emoticons: https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json +``` + +## Emoticon Presets + +The Artalk community offers many emoticon presets. You can choose a few favorite sets and easily add them to your comment system with simple configurations. Visit the repository: [@ArtalkJS/Emoticons](https://github.com/ArtalkJS/Emoticons). + +## Supported Formats + +### OwO Format + +[OwO](https://github.com/DIYgod/OwO) is an open-source JS plugin developed by [@DIYgod](https://github.com/DIYgod) that allows quick insertion of emoticons into the input box. + +Artalk's emoticon feature draws inspiration from its excellent design and natively supports and is compatible with OwO format emoticon data files, as shown below: + +```yaml +frontend: + emoticons: https://raw.githubusercontent.com/DIYgod/OwO/master/demo/OwO.json + # Directly use OwO format emoticons ↑↑ +``` + +The community also has many OwO format emoticon resources that can be used directly, for example: [@2X-ercha/Twikoo-Magic](https://github.com/2X-ercha/Twikoo-Magic). + +### Artalk Emoticon List File Standard Format + +In addition to supporting the OwO format, Artalk also natively supports a standard format for emoticon list files: + +```js +[ + { + name: 'Emoji', + type: 'emoticon', // Text type + items: [ + { key: 'Hi', val: '|´・ω・)ノ' }, + { key: 'Happy', val: 'ヾ(≧∇≦*)ゝ' }, + //... + ], + }, + { + name: 'Funny', + type: 'image', // Image type + items: [ + { + key: 'Original Funny', + val: '<Image URL>', + }, + //... + ], + }, +] +``` + +## Front-end Configuration + +To configure emoticon lists on the front end, for example: + +```js +Artalk.init({ + // Default emoticon list, dynamically imported ↓↓ + emoticons: + 'https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json', +}) +``` + +::: tip + +Configuration file and dashboard emoticon settings have a higher priority than front-end configuration. + +::: + +## Disabling Emoticons + +You can disable the emoticon feature by setting `emoticons` to `false`: + +```js +Artalk.init({ + emoticons: false, +}) +``` + +## Loading Methods + +### Dynamic Loading + +Set the `emoticons` attribute to the URL of the emoticon data file. When the emoticon list is opened, Artalk will dynamically import it. + +```js +Artalk.init({ + emoticons: '<Emoticon Data File URL>', +}) +``` + +Remote emoticon files support both Artalk and OwO formats, and support nested and mixed loading. + +### Static Loading + +Compared to dynamic importing, you can statically save the emoticon list object in the JS code of the page to avoid dynamic loading: + +```js +Artalk.init({ + emoticons: [ + { + name: 'Emoji', + type: 'emoticon', // Text type + items: [ + { key: 'Hi', val: '|´・ω・)ノ' }, + { key: 'Happy', val: 'ヾ(≧∇≦*)ゝ' }, + //... + ], + }, + { + name: 'Funny', + type: 'image', // Image type + items: [ + { + key: 'Original Funny', + val: '<Image URL>', + }, + //... + ], + }, + ], +}) +``` + +### Mixed Loading + +Artalk supports a mix of **dynamic** and **static** loading, for example: + +```js +Artalk.init({ + emoticons: [ + // Dynamic loading + 'https://raw.githubusercontent.com/DIYgod/OwO/master/demo/OwO.json', // OwO format emoticons + 'https://raw.githubusercontent.com/qwqcode/huaji/master/huaji.json', + // Static loading + { + name: 'Emoticon Name', + type: 'emoticon', // Text type + items: [ + { key: 'Go Master Ball', val: '(╯°A°)╯︵○○○' }, + //... + ], + }, + ], +}) +``` + +### Nested Import + +Artalk supports **nested import** of other emoticon resources within remote emoticon resources, for example: + +```js +Artalk.init({ + emoticons: ['https://example.org/emoticons.json'], +}) +``` + +Data in `emoticons.json`: + +```json +[ + "https://example.org/other-emoticons.json", + //... + { + // Artalk format, OwO format + //... + } +] +``` + +This allows you to efficiently manage and load multiple emoticon sets with minimal configuration. diff --git a/docs/docs/en/guide/frontend/i18n.md b/docs/docs/en/guide/frontend/i18n.md new file mode 100644 index 000000000..11b9f3fd0 --- /dev/null +++ b/docs/docs/en/guide/frontend/i18n.md @@ -0,0 +1,72 @@ +# Localization + +You can select the language in the settings page of the Artalk Dashboard, or set the language of Artalk through the environment variable `ATK_LOCALE` and the `locale` configuration item in the `artalk.yml` configuration file. + +```yml +locale: en-US +``` + +The `locale` configuration item follows the [Unicode BCP 47](https://www.techonthenet.com/js/language_tags.php) standard and defaults to "en-US" (English). + +--- + +Currently, Artalk supports the following languages: + +- "en" (English) +- "zh-CN" (简体中文) +- "zh-TW" (繁体中文) +- "ja" (日本語) +- "ko" (한국어) +- "fr" (Français) +- "ru" (Русский) + +## Contributing to Translations + +We welcome PRs to help translate Artalk into multiple languages and contribute to the community! + +| Translation Content | Language File Directory | Template File | +| ------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| Backend Program | [/i18n/[LANG].yml](https://github.com/ArtalkJS/Artalk/tree/master/i18n) | [zh-CN.yml](https://github.com/ArtalkJS/Artalk/blob/master/i18n/zh-CN.yml) | +| Frontend Interface | [/ui/artalk/src/i18n/[LANG].ts](https://github.com/ArtalkJS/Artalk/tree/master/ui/artalk/src/i18n) | [zh-CN.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/i18n/zh-CN.ts) | +| Backend Interface | [/ui/artalk-sidebar/src/i18n/[LANG].ts](https://github.com/ArtalkJS/Artalk/tree/master/ui/artalk-sidebar/src/i18n) | [zh-CN.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk-sidebar/src/i18n/zh-CN.ts) | +| Configuration Files | [/conf/artalk.example.[LANG].yml](https://github.com/ArtalkJS/Artalk/tree/master/conf) | [artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/blob/master/conf/artalk.example.zh-CN.yml) | +| Documentation | [/docs/[LANG]/\*\*/\*.md](https://github.com/ArtalkJS/Artalk/tree/master/docs) | [/docs/zh/\*\*/\*.md](https://github.com/ArtalkJS/Artalk/tree/master/docs) | + +For more details, refer to: [Development Documentation](../../develop/index.md) / [CONTRIBUTING.md](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md#translation) + +## Advanced Configuration + +### Temporarily Changing Language on the Frontend + +The frontend will use the backend's language configuration by default, but you can also set the language through the `locale` configuration item on the frontend: + +```js +Artalk.init({ + locale: 'en-US', +}) +``` + +### Automatically Switching Language on the Frontend + +You can set the front-end locale to `"auto"` to automatically switch the language based on the user's browser settings. If the language does not exist, it will default to "en-US". + +```js +Artalk.init({ + locale: 'auto', +}) +``` + +### Custom Frontend Locale Content + +You can pass an Object type to the frontend and customize the locale content according to the keys in the [template file](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/i18n/zh-CN.ts). + +```js +Artalk.init({ + locale: { + email: 'Eメール', + //... + }, +}) +``` + +By following these steps, you can easily configure and customize the language settings for Artalk to better suit your audience. diff --git a/docs/docs/en/guide/frontend/img-lazy-load.md b/docs/docs/en/guide/frontend/img-lazy-load.md new file mode 100644 index 000000000..e0e82a41c --- /dev/null +++ b/docs/docs/en/guide/frontend/img-lazy-load.md @@ -0,0 +1,55 @@ +# Image Lazy Loading + +Artalk supports adding lazy loading functionality to images within comments to reduce page load times. This feature is disabled by default. You can find the "Image Lazy Load" configuration item (frontend.imgLazyLoad) in the Dashboard under "Settings - Interface Configuration": + +| Configuration Value | Description | +| --- | --- | +| `native` | Use the browser's native image lazy loading | +| `data-src` | Use a lazy loading library for image lazy loading | +| `false` | Disable image lazy loading | + +## Native Browser Support + +When the image lazy loading is set to `native`, Artalk will use the browser's native image lazy loading feature, which adds the `loading="lazy"` attribute to the image tag. For example: + +```html +<img src="1.png" loading="lazy" /> +``` + +This method does not require additional libraries or code and is the simplest approach. However, some browsers may not support this attribute, or their lazy loading strategies may vary. For more details, refer to: [MDN - Lazy Loading](https://developer.mozilla.org/zh-CN/docs/Web/Performance/Lazy_loading). + +## Lazy Loading Library + +Using a lazy loading library ensures consistent behavior across different browsers and can offer additional features, such as image loading animations. If your blog theme comes with a lazy loading library, you can leverage it to enable lazy loading in Artalk as well. + +When the image lazy loading is set to `data-src`, Artalk will add the `class="lazyload"` and `data-src` attributes to the image tag. For example: + +```html +<img data-src="1.png" class="lazyload" /> +``` + +In this case, you need to include an additional image lazy loading library, such as [vanilla-lazyload](https://github.com/verlok/vanilla-lazyload). Add the following code to the `<head>` of your page: + +```html +<script src="https://unpkg.com/vanilla-lazyload/dist/lazyload.iife.min.js"></script> +``` + +Then, write the code to add an event listener before initializing Artalk. This listener will call the `update` method of the lazy loading library when the comment list is updated: + +```js +// Initialize the image lazy loading library +const lazyLoadInstance = new LazyLoad({ + elements_selector: '.lazyload', + threshold: 0, +}) + +// Listen to Artalk events +Artalk.use((ctx) => { + ctx.on('list-loaded', () => lazyLoadInstance.update()) +}) + +// Initialize Artalk +const artalk = Artalk.init({ /* ... */ }) +``` + +By following these steps, you can ensure that images within Artalk comments are efficiently lazy-loaded, improving the overall performance and user experience of your site. diff --git a/docs/docs/en/guide/frontend/ip-region.md b/docs/docs/en/guide/frontend/ip-region.md new file mode 100644 index 000000000..db6cbe230 --- /dev/null +++ b/docs/docs/en/guide/frontend/ip-region.md @@ -0,0 +1,46 @@ +# IP Region + +Artalk has a built-in feature to display the geolocation of user IPs, with adjustable precision levels: city or province. + +This feature is disabled by default. You can enable the IP region display feature in the Artalk Dashboard settings. + +## IP Region Database + +Before enabling the IP region display feature, you need to download a database file: + +- [GitHub Download](https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region.xdb) / [Mirror Download](https://gh-proxy.com/?q=https%3A%2F%2Fgithub.com%2Flionsoul2014%2Fip2region%2Fblob%2Fmaster%2Fdata%2Fip2region.xdb) (recommended within China) + +After downloading, manually place it in the `./data/` directory, and name the file: `ip2region.xdb`. + +## Precision Settings + +You can find this configuration item in the settings. + +| Precision Level | Description | Example | +| --------------- | ----------------- | ------------- | +| `province` | Province (default) | `Sichuan` | +| `city` | City | `Sichuan Chengdu` | +| `country` | Country/Region | `China` | + +Configuration file: + +```yaml +# IP Region +ip_region: + # Enable IP region display + enabled: false + # Data file path (.xdb format) + db_path: ./data/ip2region.xdb + # Display precision ["province", "city", "country"] + precision: province +``` + +## Obtaining the Correct IP Address + +If you are using a CDN or a trusted reverse proxy server like Nginx, you need to specify the request header field containing the user's real IP in the "Settings" - "Server" option - "Proxy Header Name (`http.proxy_header`)", such as `X-Real-IP` (for security, this field is empty by default). After modification, please manually restart the Artalk service to take effect. + +Otherwise, Artalk will not be able to obtain the user's real IP address (if using Docker, the IP obtained may always be 172.17.0.X, which is the IP of the Docker virtual network card). + +## Privacy Policy + +Artalk comments will record users' `IP` and `User-Agent` data. Since such data pertains to user privacy, please declare this in your website's privacy policy and inform users that privacy data will be collected when they comment. diff --git a/docs/docs/en/guide/frontend/latex.md b/docs/docs/en/guide/frontend/latex.md new file mode 100644 index 000000000..3be8a6299 --- /dev/null +++ b/docs/docs/en/guide/frontend/latex.md @@ -0,0 +1,41 @@ +# LaTeX + +For academic websites, LaTeX support is essential. You can use [Katex](https://katex.org/), a widely-used LaTeX syntax parser in the frontend, to implement this functionality. To maintain simplicity, Artalk does not natively include LaTeX syntax parsing capabilities. However, you can manually incorporate Katex and the Artalk Katex plugin into your page to enable LaTeX syntax support in the comment system. + +::: code-group + +```html [Browser Inclusion] +<!-- 1. Include Katex --> +<link rel="stylesheet" href="https://unpkg.com/katex@0.16.7/dist/katex.min.css" /> +<script src="https://unpkg.com/katex@0.16.7/dist/katex.min.js"></script> + +<!-- 2. Include Artalk --> +<link href="/lib/artalk/Artalk.css" rel="stylesheet" /> +<script src="/lib/artalk/Artalk.js"></script> + +<!-- 3. Include Artalk Katex Plugin --> +<script src="https://unpkg.com/@artalk/plugin-katex/dist/artalk-plugin-katex.js"></script> +``` + +```ts [Node Inclusion] +// pnpm add katex @artalk/plugin-katex +import Artalk from 'artalk' +import { ArtalkKatexPlugin } from '@artalk/plugin-katex' +import 'katex/dist/katex.min.css' + +Artalk.use(ArtalkKatexPlugin) +``` + +::: + +You can post a comment: + +```md +$$ +P(A|B_1, B_2, \ldots, B_n) = \frac{P(B_1, B_2, \ldots, B_n|A) \cdot P(A)}{P(B_1, B_2, \ldots, B_n)} +$$ +``` + +Check the result: + +![](/images/latex-support/1.png) diff --git a/docs/docs/en/guide/frontend/lightbox.md b/docs/docs/en/guide/frontend/lightbox.md new file mode 100644 index 000000000..fb62eb02b --- /dev/null +++ b/docs/docs/en/guide/frontend/lightbox.md @@ -0,0 +1,121 @@ +# Image Lightbox + +The Artalk Image Lightbox plugin seamlessly integrates your website's **existing image lightbox** functionality into Artalk. + +## Browser Environment + +In a browser environment, blog themes typically come with an image lightbox. The plugin will automatically detect the lightbox library in the `window` global object and integrate it into Artalk without additional configuration. + +```html +<!-- 1. Include the image lightbox dependency, such as LightGallery (usually provided by the blog theme, no need to re-include) --> +<script src="lightgallery.js"></script> + +<!-- 2. Include Artalk --> +<link href="/lib/artalk/Artalk.css" rel="stylesheet" /> +<script src="/lib/artalk/Artalk.js"></script> + +<!-- 3. Include the Artalk LightBox plugin --> +<script src="https://unpkg.com/@artalk/plugin-lightbox/dist/artalk-plugin-lightbox.js"></script> +``` + +If necessary, you can configure the lightbox library with the global variable `ATK_LIGHTBOX_CONF`: + +```html +<script> +// Config for LightGallery +window.ATK_LIGHTBOX_CONF = { + plugins: [lgZoom, lgThumbnail], + speed: 500, + licenseKey: 'your_license_key' +} +</script> +``` + +## Node Environment + +Install the image lightbox plugin: + +```bash +pnpm add @artalk/plugin-lightbox +``` + +Configure the plugin and dynamically import the lightbox library using `import`: + +::: code-group + +```ts [LightGallery] +import Artalk from 'artalk' +import { ArtalkLightboxPlugin } from '@artalk/plugin-lightbox' +import 'lightgallery/css/lightgallery.css' + +Artalk.use(ArtalkLightboxPlugin, { + lightGallery: { + lib: () => import('lightgallery'), + }, +}) +``` + +```ts [PhotoSwipe] +import Artalk from 'artalk' +import { ArtalkLightboxPlugin } from '@artalk/plugin-lightbox' +import 'photoswipe/style.css' + +Artalk.use(ArtalkLightboxPlugin, { + photoSwipe: { + lib: () => import('photoswipe/lightbox'), + pswpModule: () => import('photoswipe'), + }, +}) +``` + +```ts [LightBox] +import Artalk from 'artalk' +import { ArtalkLightboxPlugin } from '@artalk/plugin-lightbox' +import 'lightbox2/dist/css/lightbox.min.css' +import jQuery from 'jquery' + +window.$ = jQuery + +Artalk.use(ArtalkLightboxPlugin, { + lightBox: { + // @ts-ignore + lib: () => import('lightbox2'), + }, +}) +``` + +```ts [FancyBox] +import Artalk from 'artalk' +import { ArtalkLightboxPlugin } from '@artalk/plugin-lightbox' +import 'fancybox/dist/css/jquery.fancybox.css' +import jQuery from 'jquery' + +window.$ = jQuery + +Artalk.use(ArtalkLightboxPlugin, { + fancyBox: { + // @ts-ignore + lib: () => import('fancybox'), + }, +}) +``` + +::: + +In a Node environment, if additional configuration for the lightbox library is required, it can be done through the `config` option: + +```ts +Artalk.use(ArtalkLightboxPlugin, { + // ... + // Config for LightGallery + config: { + speed: 500, + }, +}) +``` + +--- + +Currently, the following libraries are supported for automatic integration: [LightGallery](https://github.com/sachinchoolur/lightGallery) • [FancyBox](https://github.com/fancyapps/fancybox) • [lightbox2](https://github.com/lokesh/lightbox2) • [PhotoSwipe](https://photoswipe.com/) + +Some lightbox libraries are not yet supported. Contributions are welcome 😉: [@artalk/plugin-lightbox](https://github.com/ArtalkJS/Artalk/blob/master/ui/plugin-lightbox/src/main.ts). diff --git a/docs/docs/en/guide/frontend/pv.md b/docs/docs/en/guide/frontend/pv.md new file mode 100644 index 000000000..c990d1651 --- /dev/null +++ b/docs/docs/en/guide/frontend/pv.md @@ -0,0 +1,81 @@ +# Page View Statistics + +Artalk integrates built-in page view and comment count statistics, allowing you to display the page's view count and comment count within the page. + +```html +Views: <span class="artalk-pv-count"></span> +Comments: <span class="artalk-comment-count"></span> +``` + +## Loading Placeholder + +Artalk requires some time to load. You can add a placeholder within the elements displaying the statistics: + +```html +<span class="artalk-pv-count">Loading...</span> +``` + +## Loading Statistics for Multiple Pages Simultaneously + +For instance, on an article list page, you can display the view count and comment count for each article. + +When on the article list page, simply call the `Artalk.loadCountWidget` function without `Artalk.init` (loading the comment list will increment the page view count by 1). + +<!-- prettier-ignore-start --> + +```js +Artalk.loadCountWidget({ + server: 'server address', + site: 'site name', + pvEl: '.artalk-pv-count', + countEl: '.artalk-comment-count', + statPageKeyAttr: 'data-page-key', +}) +``` + +<!-- prettier-ignore-end --> + +Then place multiple elements with the class `artalk-pv-count`, using the attribute `data-page-key` to specify the page to query: + +```html +<span class="artalk-pv-count" data-page-key="/test/1.html"></span> +<span class="artalk-pv-count" data-page-key="/test/2.html"></span> +<span class="artalk-pv-count" data-page-key="/test/3.html"></span> +``` + +The same applies for comment count queries: + +```html +<span class="artalk-comment-count" data-page-key="/test/1.html"></span> +<span class="artalk-comment-count" data-page-key="/test/2.html"></span> +<span class="artalk-comment-count" data-page-key="/test/3.html"></span> +``` + +## Custom Element Selectors + +You can specify element selectors for displaying page views and comment counts through the `pvEl` and `countEl` configuration options: + +```js +Artalk.init({ + pvEl: '.your_pv_count_element', // Selector for page view elements + countEl: '.your_comment_count_element', // Selector for comment count elements +}) +``` + +## Custom `data-page-key` Attribute Name + +The default value for the `statPageKeyAttr` configuration option is `data-page-key`. Artalk uses this attribute name to query the specified page. To facilitate adaptation with blog themes, you can customize the attribute name, for example, replacing it with `data-path`: + +```js +Artalk.loadCountWidget({ + statPageKeyAttr: 'data-path', +}) +``` + +In this case, the corresponding HTML code should be as follows: + +```html +<span class="artalk-pv-count" data-path="/test/1.html"></span> +``` + +Thus, the value of the `data-path` attribute will be used to query the specified page. diff --git a/docs/docs/en/guide/frontend/sidebar.md b/docs/docs/en/guide/frontend/sidebar.md new file mode 100644 index 000000000..8f4a17df7 --- /dev/null +++ b/docs/docs/en/guide/frontend/sidebar.md @@ -0,0 +1,45 @@ +# Sidebar + +The sidebar serves a dual purpose as both a **Notification Center** and a **Dashboard**. Once users fill in the "Nickname" and "Email" fields in the comment box, they can find the sidebar entry button at the bottom right corner of the comment box. + +<img src="/images/sidebar/1.png" width="650"> + +## Notification Center + +Artalk features an on-site messaging system. In addition to receiving email notifications, users can also view messages in the sidebar. + +The sidebar allows users to view comments related to them, categorized into: Mentions, All, Mine, and Pending Review. + +You can quickly locate comments and jump to the corresponding page. + +<img src="/images/sidebar/2.png" width="430"> + +When a user receives a message, a red dot indicator will appear. + +<img src="/images/sidebar/3.png" width="350"> + +Additionally, you can swiftly reply to messages in the sidebar without needing to switch to the comment page. + +<img src="/images/sidebar/4.png" width="400"> + +## Dashboard + +For administrator accounts, the sidebar will automatically upgrade from the "Notification Center" to the "Dashboard." + +After an administrator enters their "Nickname" and "Email," a password verification prompt will appear: + +<img src="/images/sidebar/5.png" width="600"> + +Once in the sidebar, you can manage comments, pages, sites, and other content. + +<img src="/images/sidebar/6.png" width="800"> + +By clicking the site icon in the top left corner, you can quickly switch between multiple sites. + +<img src="/images/sidebar/7.png" width="400"> + +## Settings + +Log into the administrator account to access the settings interface in the "Dashboard," where you can modify [Configuration](../backend/config.md) and [Appearance](./config.md) without editing complex configuration files. + +<img src="/images/sidebar/settings.png" width="700"> diff --git a/docs/docs/en/guide/intro.md b/docs/docs/en/guide/intro.md index 9d71e7b0e..673165238 100644 --- a/docs/docs/en/guide/intro.md +++ b/docs/docs/en/guide/intro.md @@ -20,36 +20,36 @@ Artalk's features include but are not limited to: * [Sidebar](https://artalk.js.org/guide/frontend/sidebar.html): Quick management, intuitive browsing * [Social Login](https://artalk.js.org/guide/frontend/auth.html): Fast login via social accounts * [Email Notification](https://artalk.js.org/guide/backend/email.html): Various sending methods, email templates -* [Multiple Push Notifications](https://artalk.js.org/guide/backend/admin_notify.html): Various push methods, notification templates -* [In-site Notifications](https://artalk.js.org/guide/frontend/sidebar.html): Red dot markers, mention lists -* [Captcha](https://artalk.js.org/guide/backend/captcha.html): Multiple verification types, frequency limits -* [Comment Moderation](https://artalk.js.org/guide/backend/moderator.html): Content detection, spam filtering -* [Image Upload](https://artalk.js.org/guide/backend/img-upload.html): Custom uploads, image hosting support -* [Markdown](https://artalk.js.org/guide/intro.html): Markdown syntax support -* [Emoticons](https://artalk.js.org/guide/frontend/emoticons.html): OwO compatibility, quick integration -* [Multi-site](https://artalk.js.org/guide/backend/multi-site.html): Site isolation, centralized management +* [Diverse Push](https://artalk.js.org/guide/backend/admin_notify.html): Multiple push methods, notification templates +* [Site Notification](https://artalk.js.org/guide/frontend/sidebar.html): Red dot marks, mention list +* [Captcha](https://artalk.js.org/guide/backend/captcha.html): Various verification types, frequency limits +* [Comment Moderation](https://artalk.js.org/guide/backend/moderator.html): Content detection, spam interception +* [Image Upload](https://artalk.js.org/guide/backend/img-upload.html): Custom upload, supports image hosting +* [Markdown](https://artalk.js.org/guide/intro.html): Supports Markdown syntax +* [Emoji Pack](https://artalk.js.org/guide/frontend/emoticons.html): Compatible with OwO, quick integration +* [Multi-Site](https://artalk.js.org/guide/backend/multi-site.html): Site isolation, centralized management * [Admin](https://artalk.js.org/guide/backend/multi-site.html): Password verification, badge identification -* [Page Management](https://artalk.js.org/guide/frontend/sidebar.html): Quick view, one-click title jump -* [Page Views](https://artalk.js.org/guide/frontend/pv.html): Easily track webpage views -* [Hierarchical Structure](https://artalk.js.org/guide/frontend/config.html#nestmax): Nested pagination lists, infinite scroll +* [Page Management](https://artalk.js.org/guide/frontend/sidebar.html): Quick view, one-click title navigation +* [Page View Statistics](https://artalk.js.org/guide/frontend/pv.html): Easily track page views +* [Hierarchical Structure](https://artalk.js.org/guide/frontend/config.html#nestmax): Nested paginated list, infinite scroll * [Comment Voting](https://artalk.js.org/guide/frontend/config.html#vote): Upvote or downvote comments -* [Comment Sorting](https://artalk.js.org/guide/frontend/config.html#listsort): Multiple sorting options -* [Comment Search](https://artalk.js.org/guide/frontend/sidebar.html): Quick search of comment content -* [Pinned Comments](https://artalk.js.org/guide/frontend/sidebar.html): Pin important messages -* [Author-only View](https://artalk.js.org/guide/frontend/config.html): Display only the author's comments -* [Comment Jump](https://artalk.js.org/guide/intro.html): Quick jump to referenced comments -* [Auto-save](https://artalk.js.org/guide/frontend/config.html): Prevent content loss +* [Comment Sorting](https://artalk.js.org/guide/frontend/config.html#listsort): Various sorting options, freely selectable +* [Comment Search](https://artalk.js.org/guide/frontend/sidebar.html): Quick comment content search +* [Comment Pinning](https://artalk.js.org/guide/frontend/sidebar.html): Pin important messages +* [View Author Only](https://artalk.js.org/guide/frontend/config.html): Show only the author's comments +* [Comment Jump](https://artalk.js.org/guide/intro.html): Quickly jump to quoted comment +* [Auto Save](https://artalk.js.org/guide/frontend/config.html): Content loss prevention * [IP Region](https://artalk.js.org/guide/frontend/ip-region.html): Display user's IP region -* [Data Migration](https://artalk.js.org/guide/transfer.html): Flexible migration, quick backup -* [Image Lightbox](https://artalk.js.org/guide/frontend/lightbox.html): Quick lightbox integration -* [Image Lazy Loading](https://artalk.js.org/guide/frontend/img-lazy-load.html): Delay image loading for a better experience -* [Latex](https://artalk.js.org/guide/frontend/latex.html): Latex formula parsing integration -* [Dark Mode](https://artalk.js.org/guide/frontend/config.html#darkmode): Toggle dark mode -* [Plugins](https://artalk.js.org/develop/plugin.html): Create more possibilities -* [Multi-language](https://artalk.js.org/guide/frontend/i18n.html): Switch languages -* [Command Line](https://artalk.js.org/guide/backend/config.html): Command line management -* [API Documentation](https://artalk.js.org/http-api.html): OpenAPI format documentation -* [Program Upgrade](https://artalk.js.org/guide/backend/update.html): Version checking, one-click upgrade +* [Data Migration](https://artalk.js.org/guide/transfer.html): Free migration, quick backup +* [Image Lightbox](https://artalk.js.org/guide/frontend/lightbox.html): Quick integration of image lightbox +* [Image Lazy Load](https://artalk.js.org/guide/frontend/img-lazy-load.html): Lazy load images, optimize experience +* [Latex](https://artalk.js.org/guide/frontend/latex.html): Integrate Latex formula parsing +* [Night Mode](https://artalk.js.org/guide/frontend/config.html#darkmode): Switch to night mode +* [Extension Plugin](https://artalk.js.org/develop/plugin.html): Create more possibilities +* [Multi-Language](https://artalk.js.org/guide/frontend/i18n.html): Switch between multiple languages +* [Command Line](https://artalk.js.org/guide/backend/config.html): Command line operation management +* [API Documentation](https://artalk.js.org/http-api.html): Provides OpenAPI format documentation +* [Program Upgrade](https://artalk.js.org/guide/backend/update.html): Version check, one-click upgrade <!-- /features --> We are not exhaustive; more exciting features await your discovery! diff --git a/docs/docs/en/guide/security.md b/docs/docs/en/guide/security.md new file mode 100644 index 000000000..6c0772cb0 --- /dev/null +++ b/docs/docs/en/guide/security.md @@ -0,0 +1,3 @@ +# Security + +【TODO】 diff --git a/docs/docs/en/guide/transfer.md b/docs/docs/en/guide/transfer.md new file mode 100644 index 000000000..45698d760 --- /dev/null +++ b/docs/docs/en/guide/transfer.md @@ -0,0 +1,214 @@ +# 🛬 Data Migration + +## Data Bundle + +The data bundle (Artrans = Art + Ran) is the Artalk persistent data storage standard format. + +::: details Artran Format Definition + +We define it as follows: each comment data (Object) is called an Artran, and multiple comment data together form Artrans (Array type). + +```json +{ + "id": "123", + "rid": "233", + "content": "Hello Artalk", + "ua": "Artalk/6.6", + "ip": "233.233.233.233", + "created_at": "2021-10-28 20:50:15 +0800", + "updated_at": "2021-10-28 20:50:15 +0800", + "is_collapsed": "false", + "is_pending": "false", + "vote_up": "666", + "vote_down": "0", + "nick": "qwqcode", + "email": "qwqcode@github.com", + "link": "https://qwqaq.com", + "password": "", + "badge_name": "Administrator", + "badge_color": "#FF716D", + "page_key": "https://artalk.js.org/guide/transfer.html", + "page_title": "Data Migration", + "page_admin_only": "false", + "site_name": "Artalk", + "site_urls": "http://localhost:3000/demo/,https://artalk.js.org" +} +``` + +We call a JSON array Artrans, and each Object item within the array is an Artran (without the s). + +::: + +## Conversion Tool + +Use the following tool to convert comment data from other formats to Artrans, and then import them into Artalk. [Open in a new window](https://artransfer.netlify.app) + +<Artransfer /> + +::: tip + +The following text provides various methods to obtain source data for reference; if you encounter any issues, please submit feedback via [issue](https://github.com/ArtalkJS/Artransfer/issues). + +::: + +## Data Import + +Data files converted to the `.artrans` format can be imported into Artalk: + +- **Dashboard Import**: You can find the "Migration" tab in the "[Dashboard](./frontend/sidebar.md#control-center)" and follow the prompts to import Artrans. +- **Command Line Import**: Refer to [Command Line Import](#command-line-import). + +## Obtaining Source Data + +### Typecho + +**Install Plugin to Obtain Artrans** + +We provide an Artrans export plugin: + +1. Click "[here](https://github.com/ArtalkJS/Artrans-Typecho/releases/download/v1.0.0/ArtransExporter.zip)" to download the plugin and "unzip" it into the Typecho directory `/usr/plugins/`. +2. Go to the Typecho backend "Console - Plugins" to enable the "ArtransExporter" plugin. +3. Go to "Console - Export Comments (Artrans)" to export all Typecho comments in Artrans format. + +**Direct Database Connection to Obtain Artrans** + +If your blog is no longer active but the database still exists, you can use our command line tool that supports direct connection to the Typecho database. + +[Download Artransfer-CLI](https://github.com/ArtalkJS/Artransfer-CLI/releases), unzip the package, and execute: + +```sh +./artransfer typecho \ + --db="mysql" \ + --host="localhost" \ + --port="3306" \ + --user="root" \ + --password="123456" \ + --name="typecho_database_name" +``` + +After execution, you will get a file in Artrans format: + +```sh +> ls +typecho-20220424-202246.artrans +``` + +Note: It supports connecting to various databases. For more details, refer to [here](https://github.com/ArtalkJS/Artransfer-CLI). + +### WordPress + +Go to the WordPress backend "Tools - Export", check "All Content", and export the file. You can then use the [conversion tool](#conversion-tool) for conversion. + +![](/images/transfer/wordpress.png) + +### Valine + +Go to the [LeanCloud backend](https://console.leancloud.cn/) to export the comment data file in JSON format, then use the [conversion tool](#conversion-tool) for conversion. + +![](/images/transfer/leancloud.png) + +### Waline + +Using the LeanCloud database, Waline can refer to the above method for Valine as their formats are similar. + +For independently deployed Waline, download [Artransfer-CLI](https://github.com/ArtalkJS/Artransfer-CLI/releases) to connect to the local database for export. Execute the command line: + +```bash +./artransfer waline \ + --db="mysql" \ + --host="localhost" \ + --port="3306" \ + --user="root" \ + --password="123456" \ + --name="waline_database_name" \ + --table-prefix="wl_" +``` + +You will obtain a data file in Artrans format, then [import into Artalk](#how-to-import-artrans). + +Note: It supports connecting to various databases. For more details, refer to [here](https://github.com/ArtalkJS/Artransfer-CLI). + +### Disqus + +Go to the [Disqus backend](https://disqus.com/admin), find "Moderation - Export" and click to export. Disqus will send a `.gz` compressed package to your email. After extracting, you will get a `.xml` data file, which you can then use the [conversion tool](#conversion-tool) to convert to Artrans. + +![](/images/transfer/disqus.png) + +### Commento + +You can export the data file in JSON format from the Commento backend, then use the [conversion tool](#conversion-tool) for conversion. + +[Image, to be supplemented...] + +### Twikoo + +[Twikoo](https://twikoo.js.org/) is a comment system developed based on Tencent Cloud. Go to the [Tencent Cloud backend](https://console.cloud.tencent.com/tcb) to export the comment data file in JSON format, then use the [conversion tool](#conversion-tool) for conversion. + +<img src="/images/transfer/tencent-tcb.png" style="max-width: 480px;"> + +### Artalk v1 (Old PHP Backend) + +[Artalk v1](https://github.com/ArtalkJS/ArtalkPHP) is the old backend of Artalk, written in PHP. The new backend has fully transitioned to Golang with a redesigned data table structure. Upgrading to the new version requires using the [conversion tool](#conversion-tool) for conversion. + +Old version data path: `/data/comments.data.json` + +## Command Line Import + +Execute `artalk import -h` to view the help documentation. + +```bash +./artalk import [parameters...] [filename] +``` + +Set import parameters via the `-p` flag on the command line: + +```bash +./artalk import -p '{ "target_site_name": "Site", "target_site_url": "https://xx.com", "json_file": "", "url_resolver": true }' ./artrans.json +``` + +If importing via the web backend, you can fill the JSON in the text box: + +```json +{ + "target_site_name": "Site", + "target_site_url": "https://xx.com", + "json_file": "path on the server", + "url_resolver": true +} +``` + +Artalk import parameters: + +| Parameter | Type | Description | +| :---------------------: | ------- | ---------------------------------------------------------------------------------------------------- | +| `target_site_name` | String | Name of the import site | +| `target_site_url` | String | URL of the import site | +| `url_resolver` | Boolean | URL resolver, default is off. Re-generates the `page_key` based on the `target_site_url` as the new `page_key` for comments | +| `url_keep_domain` | Boolean | Default is off. Whether to keep the original domain part of the URL. If off, removes the domain part of `pageKey`. When `url_resolver` is on, `url_keep_domain` is also enabled | +| `json_file` | String | Path to the JSON data file | +| `json_data` | String | Content of the JSON data string | +| `assumeyes` | Boolean | Execute directly without confirmation `y/n` | + +## Data Backup + +You can find the "Migration" tab in the "[Dashboard](./frontend/sidebar.md#dashboard)" on the front end, and export comment data in Artrans format. + +### Command Line Backup + +Export: `artalk export ./artrans` + +Import: `artalk import ./artrans` + +### Advanced Usage + +Execute `artalk export` to directly "standard output", and perform "pipe" or "output redirection" operations, for example: + +```bash +artalk export | gzip -9 | ssh username@remote_ip "cat > ~/backup/artrans.gz" +``` + +## Conclusion + +We currently support converting data from Typecho, WordPress, Valine, Waline, Disqus, Commento, Twikoo, etc., to Artrans. However, considering the diversity of comment systems, although we have adapted the above types of data, many are still not compatible. If you happen to be using an unsupported comment system, besides waiting for official Artalk support, you can also try to understand the Artrans data format and write your own tools for importing and exporting comment data. If you think your tool is well-written, we would be happy to include it, allowing us to create a tool that can freely switch between different comment systems together. + +Visit: [Artransfer Migration Tool Code Repository](https://github.com/ArtalkJS/Artransfer) diff --git a/docs/docs/develop/api-old.md b/docs/docs/zh/develop/api-old.md similarity index 100% rename from docs/docs/develop/api-old.md rename to docs/docs/zh/develop/api-old.md diff --git a/docs/docs/develop/api.md b/docs/docs/zh/develop/api.md similarity index 100% rename from docs/docs/develop/api.md rename to docs/docs/zh/develop/api.md diff --git a/docs/docs/develop/compatibility.md b/docs/docs/zh/develop/compatibility.md similarity index 100% rename from docs/docs/develop/compatibility.md rename to docs/docs/zh/develop/compatibility.md diff --git a/docs/docs/develop/contributing.md b/docs/docs/zh/develop/contributing.md similarity index 100% rename from docs/docs/develop/contributing.md rename to docs/docs/zh/develop/contributing.md diff --git a/docs/docs/develop/event.md b/docs/docs/zh/develop/event.md similarity index 100% rename from docs/docs/develop/event.md rename to docs/docs/zh/develop/event.md diff --git a/docs/docs/develop/fe-api.md b/docs/docs/zh/develop/fe-api.md similarity index 100% rename from docs/docs/develop/fe-api.md rename to docs/docs/zh/develop/fe-api.md diff --git a/docs/docs/develop/import-blog.md b/docs/docs/zh/develop/import-blog.md similarity index 100% rename from docs/docs/develop/import-blog.md rename to docs/docs/zh/develop/import-blog.md diff --git a/docs/docs/develop/import-framework.md b/docs/docs/zh/develop/import-framework.md similarity index 100% rename from docs/docs/develop/import-framework.md rename to docs/docs/zh/develop/import-framework.md diff --git a/docs/docs/develop/index.md b/docs/docs/zh/develop/index.md similarity index 100% rename from docs/docs/develop/index.md rename to docs/docs/zh/develop/index.md diff --git a/docs/docs/develop/plugin.md b/docs/docs/zh/develop/plugin.md similarity index 100% rename from docs/docs/develop/plugin.md rename to docs/docs/zh/develop/plugin.md diff --git a/docs/docs/develop/plugs.md b/docs/docs/zh/develop/plugs.md similarity index 100% rename from docs/docs/develop/plugs.md rename to docs/docs/zh/develop/plugs.md diff --git a/docs/docs/guide/about.md b/docs/docs/zh/guide/about.md similarity index 100% rename from docs/docs/guide/about.md rename to docs/docs/zh/guide/about.md diff --git a/docs/docs/guide/backend/admin_notify.md b/docs/docs/zh/guide/backend/admin_notify.md similarity index 100% rename from docs/docs/guide/backend/admin_notify.md rename to docs/docs/zh/guide/backend/admin_notify.md diff --git a/docs/docs/guide/backend/build.md b/docs/docs/zh/guide/backend/build.md similarity index 100% rename from docs/docs/guide/backend/build.md rename to docs/docs/zh/guide/backend/build.md diff --git a/docs/docs/guide/backend/captcha.md b/docs/docs/zh/guide/backend/captcha.md similarity index 97% rename from docs/docs/guide/backend/captcha.md rename to docs/docs/zh/guide/backend/captcha.md index 970f3458b..5c31511a8 100644 --- a/docs/docs/guide/backend/captcha.md +++ b/docs/docs/zh/guide/backend/captcha.md @@ -90,9 +90,9 @@ captcha: 图示: -<img src="../../images/captcha/cf-turnstile-1.png" width="400px"> +<img src="/images/captcha/cf-turnstile-1.png" width="400px"> -<img src="../../images/captcha/cf-turnstile-2.png" width="400px"> +<img src="/images/captcha/cf-turnstile-2.png" width="400px"> 对应配置文件如下: diff --git a/docs/docs/guide/backend/config.md b/docs/docs/zh/guide/backend/config.md similarity index 100% rename from docs/docs/guide/backend/config.md rename to docs/docs/zh/guide/backend/config.md diff --git a/docs/docs/guide/backend/daemon.md b/docs/docs/zh/guide/backend/daemon.md similarity index 100% rename from docs/docs/guide/backend/daemon.md rename to docs/docs/zh/guide/backend/daemon.md diff --git a/docs/docs/guide/backend/data.md b/docs/docs/zh/guide/backend/data.md similarity index 100% rename from docs/docs/guide/backend/data.md rename to docs/docs/zh/guide/backend/data.md diff --git a/docs/docs/guide/backend/docker.md b/docs/docs/zh/guide/backend/docker.md similarity index 100% rename from docs/docs/guide/backend/docker.md rename to docs/docs/zh/guide/backend/docker.md diff --git a/docs/docs/guide/backend/email.md b/docs/docs/zh/guide/backend/email.md similarity index 100% rename from docs/docs/guide/backend/email.md rename to docs/docs/zh/guide/backend/email.md diff --git a/docs/docs/guide/backend/fe-control.md b/docs/docs/zh/guide/backend/fe-control.md similarity index 100% rename from docs/docs/guide/backend/fe-control.md rename to docs/docs/zh/guide/backend/fe-control.md diff --git a/docs/docs/guide/backend/img-upload.md b/docs/docs/zh/guide/backend/img-upload.md similarity index 100% rename from docs/docs/guide/backend/img-upload.md rename to docs/docs/zh/guide/backend/img-upload.md diff --git a/docs/docs/guide/backend/install.md b/docs/docs/zh/guide/backend/install.md similarity index 100% rename from docs/docs/guide/backend/install.md rename to docs/docs/zh/guide/backend/install.md diff --git a/docs/docs/guide/backend/moderator.md b/docs/docs/zh/guide/backend/moderator.md similarity index 100% rename from docs/docs/guide/backend/moderator.md rename to docs/docs/zh/guide/backend/moderator.md diff --git a/docs/docs/guide/backend/multi-site.md b/docs/docs/zh/guide/backend/multi-site.md similarity index 100% rename from docs/docs/guide/backend/multi-site.md rename to docs/docs/zh/guide/backend/multi-site.md diff --git a/docs/docs/guide/backend/notify.md b/docs/docs/zh/guide/backend/notify.md similarity index 100% rename from docs/docs/guide/backend/notify.md rename to docs/docs/zh/guide/backend/notify.md diff --git a/docs/docs/guide/backend/relative-path.md b/docs/docs/zh/guide/backend/relative-path.md similarity index 100% rename from docs/docs/guide/backend/relative-path.md rename to docs/docs/zh/guide/backend/relative-path.md diff --git a/docs/docs/guide/backend/reverse-proxy.md b/docs/docs/zh/guide/backend/reverse-proxy.md similarity index 100% rename from docs/docs/guide/backend/reverse-proxy.md rename to docs/docs/zh/guide/backend/reverse-proxy.md diff --git a/docs/docs/guide/backend/update.md b/docs/docs/zh/guide/backend/update.md similarity index 100% rename from docs/docs/guide/backend/update.md rename to docs/docs/zh/guide/backend/update.md diff --git a/docs/docs/guide/cases.md b/docs/docs/zh/guide/cases.md similarity index 100% rename from docs/docs/guide/cases.md rename to docs/docs/zh/guide/cases.md diff --git a/docs/docs/guide/deploy.md b/docs/docs/zh/guide/deploy.md similarity index 100% rename from docs/docs/guide/deploy.md rename to docs/docs/zh/guide/deploy.md diff --git a/docs/docs/guide/env.md b/docs/docs/zh/guide/env.md similarity index 100% rename from docs/docs/guide/env.md rename to docs/docs/zh/guide/env.md diff --git a/docs/docs/guide/extras.md b/docs/docs/zh/guide/extras.md similarity index 100% rename from docs/docs/guide/extras.md rename to docs/docs/zh/guide/extras.md diff --git a/docs/docs/guide/frontend/artalk-lite.md b/docs/docs/zh/guide/frontend/artalk-lite.md similarity index 100% rename from docs/docs/guide/frontend/artalk-lite.md rename to docs/docs/zh/guide/frontend/artalk-lite.md diff --git a/docs/docs/guide/frontend/auth.md b/docs/docs/zh/guide/frontend/auth.md similarity index 92% rename from docs/docs/guide/frontend/auth.md rename to docs/docs/zh/guide/frontend/auth.md index 598474d1f..39136ca56 100644 --- a/docs/docs/guide/frontend/auth.md +++ b/docs/docs/zh/guide/frontend/auth.md @@ -20,15 +20,15 @@ Artalk 默认只需填写昵称和邮箱即可发表评论,无需验证邮箱 ## 邮箱密码登录 -![邮箱登录](../../images/auth/email_login.png) +![邮箱登录](/images/auth/email_login.png) 启用邮箱密码登录后,评论框顶部的昵称邮箱输入框将被隐藏,发送按钮将显示为登录按钮。用户点击登录按钮后,将会弹出一个登录框,用户可以输入邮箱和密码登录,登录成功后即可发表评论。并且,用户发表的评论将展示「邮箱已验证」的标识。 -<img src="../../images/auth/email_verified.png" width="550" alt="邮箱已验证标识"> +<img src="/images/auth/email_verified.png" width="550" alt="邮箱已验证标识"> 用户可以通过邮箱注册账号,Artalk 将向用户邮箱发送一封带有验证码的邮件。验证码有效期为 10 分钟,验证码发送频率限制为 1 分钟一次。 -![邮箱注册](../../images/auth/email_register.png) +![邮箱注册](/images/auth/email_register.png) 支持自定义验证码邮件模板和邮件标题,可在 Artalk 控制中心的设置页面的社交登录找到「邮箱验证邮件标题」、「邮箱验证邮件模板」选项进行设置。在配置文件中,可以通过 `auth.email.verify_subject` 和 `auth.email.verify_tpl` 进行设置: @@ -47,7 +47,7 @@ auth: 您的验证码是:{{code}}。请使用它来验证您的电子邮件并登录到 Artalk。如果您没有请求此操作,请忽略此消息。 ``` -![跳过登录](../../images/auth/login_skip.png) +![跳过登录](/images/auth/login_skip.png) 启用邮箱密码登录功能后,仍然可跳过邮箱验证:登录弹窗底部显示 “跳过,不验证” 按钮,点击后评论框顶部恢复为显示原有的昵称、邮箱、网址三个输入框。在设置中勾选「允许匿名评论」可以更改。 @@ -55,17 +55,17 @@ auth: 登录后如果检测到相同的邮箱下有多个不同用户名的账号,将会弹出账号合并工具,用户可以选择保留其中一个用户名,该邮箱下的所有评论等数据合并到保留的账号下。原有的账号将被删除,评论显示的用户名将会变更为保留的用户名。 -![账号合并工具](../../images/auth/merge_accounts.png) +![账号合并工具](/images/auth/merge_accounts.png) ## 多种登录方式 Artalk 支持同时启用多种登录方式,用户可以选择任意一种方式登录。 -![多种登录方式](../../images/auth/multi_login.png) +![多种登录方式](/images/auth/multi_login.png) 如果只启用了唯一一种登录,例如 GitHub 登录,将直接弹出 GitHub 的授权登录页面。 -![GitHub 授权弹窗](../../images/auth/github_login.png) +![GitHub 授权弹窗](/images/auth/github_login.png) 接入 GitHub 登录可参考文档:[关于创建 GitHub 应用](https://docs.github.com/zh/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps),得到 Client ID 和 Client Secret 后,填写到 Artalk 控制中心的设置页面的社交登录中的「GitHub」选项中即可。 diff --git a/docs/docs/guide/frontend/config.md b/docs/docs/zh/guide/frontend/config.md similarity index 100% rename from docs/docs/guide/frontend/config.md rename to docs/docs/zh/guide/frontend/config.md diff --git a/docs/docs/guide/frontend/emoticons.md b/docs/docs/zh/guide/frontend/emoticons.md similarity index 100% rename from docs/docs/guide/frontend/emoticons.md rename to docs/docs/zh/guide/frontend/emoticons.md diff --git a/docs/docs/guide/frontend/i18n.md b/docs/docs/zh/guide/frontend/i18n.md similarity index 100% rename from docs/docs/guide/frontend/i18n.md rename to docs/docs/zh/guide/frontend/i18n.md diff --git a/docs/docs/guide/frontend/img-lazy-load.md b/docs/docs/zh/guide/frontend/img-lazy-load.md similarity index 100% rename from docs/docs/guide/frontend/img-lazy-load.md rename to docs/docs/zh/guide/frontend/img-lazy-load.md diff --git a/docs/docs/guide/frontend/import-blog.md b/docs/docs/zh/guide/frontend/import-blog.md similarity index 100% rename from docs/docs/guide/frontend/import-blog.md rename to docs/docs/zh/guide/frontend/import-blog.md diff --git a/docs/docs/guide/frontend/import-framework.md b/docs/docs/zh/guide/frontend/import-framework.md similarity index 100% rename from docs/docs/guide/frontend/import-framework.md rename to docs/docs/zh/guide/frontend/import-framework.md diff --git a/docs/docs/guide/frontend/install.md b/docs/docs/zh/guide/frontend/install.md similarity index 100% rename from docs/docs/guide/frontend/install.md rename to docs/docs/zh/guide/frontend/install.md diff --git a/docs/docs/guide/frontend/ip-region.md b/docs/docs/zh/guide/frontend/ip-region.md similarity index 100% rename from docs/docs/guide/frontend/ip-region.md rename to docs/docs/zh/guide/frontend/ip-region.md diff --git a/docs/docs/guide/frontend/latex.md b/docs/docs/zh/guide/frontend/latex.md similarity index 100% rename from docs/docs/guide/frontend/latex.md rename to docs/docs/zh/guide/frontend/latex.md diff --git a/docs/docs/guide/frontend/lightbox.md b/docs/docs/zh/guide/frontend/lightbox.md similarity index 100% rename from docs/docs/guide/frontend/lightbox.md rename to docs/docs/zh/guide/frontend/lightbox.md diff --git a/docs/docs/guide/frontend/pv.md b/docs/docs/zh/guide/frontend/pv.md similarity index 100% rename from docs/docs/guide/frontend/pv.md rename to docs/docs/zh/guide/frontend/pv.md diff --git a/docs/docs/guide/frontend/sidebar.md b/docs/docs/zh/guide/frontend/sidebar.md similarity index 100% rename from docs/docs/guide/frontend/sidebar.md rename to docs/docs/zh/guide/frontend/sidebar.md diff --git a/docs/docs/guide/intro.md b/docs/docs/zh/guide/intro.md similarity index 100% rename from docs/docs/guide/intro.md rename to docs/docs/zh/guide/intro.md diff --git a/docs/docs/guide/security.md b/docs/docs/zh/guide/security.md similarity index 100% rename from docs/docs/guide/security.md rename to docs/docs/zh/guide/security.md diff --git a/docs/docs/guide/transfer.md b/docs/docs/zh/guide/transfer.md similarity index 100% rename from docs/docs/guide/transfer.md rename to docs/docs/zh/guide/transfer.md diff --git a/docs/docs/index.md b/docs/docs/zh/index.md similarity index 100% rename from docs/docs/index.md rename to docs/docs/zh/index.md diff --git a/docs/landing/scripts/update-readme.ts b/docs/landing/scripts/update-readme.ts index 00a7e18d3..fd133d472 100644 --- a/docs/landing/scripts/update-readme.ts +++ b/docs/landing/scripts/update-readme.ts @@ -3,23 +3,28 @@ import { writeFileSync, readFileSync } from 'node:fs' import { getFeatures } from '../src/features' import { initI18nSSR } from '../src/i18n' -const t = await initI18nSSR('zh-CN') +const build = async (lang: string, filenames: string[]) => { + const t = await initI18nSSR(lang) -const __dirname = new URL('.', import.meta.url).pathname -const features = getFeatures(t) - .map((o) => `* [${o.name}](${o.link}): ${o.desc}`) - .join('\n') + const __dirname = new URL('.', import.meta.url).pathname + const features = getFeatures(t) + .map((o) => `* [${o.name}](${o.link}): ${o.desc}`) + .join('\n') -const pathList = ['../../../README.md', '../../docs/guide/intro.md'] + filenames.forEach((p) => { + p = path.resolve(__dirname, p) -pathList.forEach((p) => { - p = path.resolve(__dirname, p) + const newReadme = readFileSync(p, 'utf-8').replace( + /<!-- features -->[\s\S]*<!-- \/features -->/, + `<!-- features -->\n${features}\n<!-- /features -->`, + ) + writeFileSync(p, newReadme) - const newReadme = readFileSync(p, 'utf-8').replace( - /<!-- features -->[\s\S]*<!-- \/features -->/, - `<!-- features -->\n${features}\n<!-- /features -->`, - ) - writeFileSync(p, newReadme) + console.log(`Updated ${p}`) + }) - console.log(`Updated ${p}`) -}) + console.log(`[DONE] locale "${lang}" finished.\n`) +} + +await build('en', ['../../../README.en.md', '../../docs/en/guide/intro.md']) +await build('zh-CN', ['../../../README.md', '../../docs/zh/guide/intro.md'])