Compare commits

..
185 Commits
Author SHA1 Message Date
github-actions[bot] 6135c7e911 chore: release v2.9.0 (#968)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-03 22:03:03 +08:00
qwqcode 1ff0c4c10f chore(deps): upgrade deps 2024-09-03 21:18:16 +08:00
qwqcode 9cc9a6d6ab feat(config): add site_url config option (#967) 2024-09-03 20:07:43 +08:00
qwqcode d2225d565b fix(anti_spam): handle empty referer variable in anti-spam check (#853) 2024-09-03 19:37:39 +08:00
qwqcode e61911027c fix(auth): correct email verification code send button 2024-09-03 11:44:37 +08:00
qwqcode f29d2f81eb chore(sidebar/icon): swap sensitive hidden on/off icon 2024-09-02 16:52:52 +08:00
qwqcode 4b5ec39b8e feat(auth): add user profile and password changing (#966) 2024-09-02 15:56:04 +08:00
qwqcode 5dc2752cc1 fix(validator): restrict to allow only HTTP protocol 2024-09-02 14:52:57 +08:00
qwqcode cf6e687a2d fix(plugin_kit): import source path case error on linux 2024-09-02 11:16:23 +08:00
qwqcode 69ea7de22e chore(deps): update peerDependencies for plugin-auth 2024-09-01 23:03:43 +08:00
qwqcode 8fb7027186 chore(ci): add plugin-kit to artalk build process 2024-08-31 22:15:46 +08:00
qwqcode 88615f9a88 perf(auth): correct verify button position in register form 2024-08-31 21:56:25 +08:00
qwqcode f104629b40 perf(auth): add loading skeleton for login methods list 2024-08-31 21:54:28 +08:00
qwqcode 2f6b30deaf perf(auth): enhance visibility of skip button (#863) 2024-08-31 21:53:25 +08:00
qwqcode 2f7b9fa816 perf(auth): perform optical adjustment for consistent icon sizing 2024-08-31 21:45:53 +08:00
qwqcode 6d1041dc69 docs(auth): set auth.anonymous to false as default 2024-08-31 21:43:48 +08:00
qwqcode 9fb191976c refactor(ui/types): add Layer interface 2024-08-31 17:05:30 +08:00
qwqcode f20454bd00 perf(plugin_kit): improve typescript diagnostics output 2024-08-31 16:53:42 +08:00
qwqcode 64854107ef fix(plugin_kit): fix typescript lib path retrieval on win 2024-08-30 22:41:58 +08:00
qwqcode ac54eae179 chore(docs): add docker mirror tips 2024-08-30 12:05:24 +08:00
qwqcode aa92a92961 fix(api/comment_add): improve the security of comment add api (#964)
* fix(api/comment_add): refactor and improve the security of comment add api

* update
2024-08-29 23:29:36 +08:00
qwqcode d54652264b feat(ui/sidebar): add dark mode toggle for dashboard (#790) 2024-08-29 20:59:19 +08:00
qwqcode d6ececd014 fix(ui/stat): fix invalid backward compatible strategy (#880) 2024-08-29 20:54:30 +08:00
qwqcode 04ef002da1 fix(sidebar): correct total item count for pagination in sidebar 2024-08-29 18:43:49 +08:00
qwqcode a6b559d682 chore(icon): fix icon in sidebar on desktop devices 2024-08-29 18:31:39 +08:00
qwqcode 67b37b4612 chore(deps): upgrade frontend deps 2024-08-29 14:25:06 +08:00
qwqcode 3e81b2a8f2 chore(docker): resolve dockerfile rule violations 2024-08-29 14:22:03 +08:00
qwqcode 8a9480d05a feat(ui/sidebar): add page search by keywords in sidebar (#603) 2024-08-29 13:42:41 +08:00
qwqcode b3ed639be7 perf(style/sidebar): modify font-family for sidebar 2024-08-29 12:46:03 +08:00
qwqcode 6a0e06ea75 docs(ui/i18n): add more locale support for sidebar 2024-08-29 12:43:53 +08:00
qwqcode 92484cfa66 perf(ui/sidebar): enhance i18n translations for sidebar 2024-08-29 12:42:31 +08:00
qwqcode 1b0eff9568 perf(ui/sidebar): optimize setup process and i18n lazy load (#962) 2024-08-29 12:33:51 +08:00
qwqcode 2efd34248d perf(i18n): auto-load frontend i18n locale js sources 2024-08-29 11:47:57 +08:00
qwqcode c0a3026890 docs(ui/i18n): add translations for French, Korean, and Russian 2024-08-29 11:45:56 +08:00
qwqcode 392b6b15cf refactor(ui/user): rename nick to name in LocalUser data structure (#961) 2024-08-28 23:28:36 +08:00
qwqcode 6b58fd8a9d feat(ui/sidebar): add user search by keywords in sidebar (#710) 2024-08-28 19:50:38 +08:00
qwqcode 80e5ca5dc7 perf(ui/sidebar): mask sensitive input values in sidebar settings (#494) 2024-08-28 19:04:15 +08:00
qwqcode 50e967f71c feat(ui/date): add dateFormatter config option (#940) 2024-08-28 18:01:43 +08:00
qwqcode cf58a545b5 chore(deps): upgrade deps 2024-08-28 16:12:43 +08:00
qwqcode 270558129f fix(ui/dark_mode): apply dark mode config option before mounting ui (#890) 2024-08-28 12:40:47 +08:00
qwqcode 059bac8b5f perf(api/auth): add more specific error messages for login failures 2024-08-28 11:26:31 +08:00
qwqcode f1a86d59ca fix(ui/sidebar): disable admin password check dialog in sidebar 2024-08-28 11:12:30 +08:00
qwqcode adcb75a2e2 feat(ui/dashboard): new dashboard ui refresh for desktop devices (#957)
* feat(ui/dashboard): new dashboard ui refresh on desktop device

* add z-index for login dialog layer
2024-08-20 04:10:17 +08:00
qwqcode 4d7e157ff0 fix(ui/sidebar): show env variables in sidebar settings ui (#946) (#956)
* fix(ui/sidebar): show env variables in sidebar settings ui (#946)

* fix unit test
2024-08-19 16:27:20 +08:00
qwqcode 528847de7b chore(docs): add SECURITY.md 2024-08-18 23:41:31 +08:00
qwqcode 2b9d6bb573 chore(deps): upgrade docs and sidebar deps 2024-08-18 22:53:51 +08:00
qwqcode 393224cdb1 refactor(plugin_katex): use tokenizer extension of marked (#955) 2024-08-18 22:44:58 +08:00
qwqcode a925806d29 refactor(ui/marked): replace pkg-level marked with new class instance (#954)
* refactor(ui/marked): replace pkg-level marked with new class instance

* fix sidebar
2024-08-18 20:10:02 +08:00
qwqcode b97167a718 chore(docs): update FUNDING.yml 2024-08-17 16:10:48 +08:00
qwqcode 587523f0df feat(go): upgrade golang to v1.22.6 and some deps 2024-08-17 15:43:15 +08:00
qwqcode 08f58cd38b chore(deps/ui): upgrade deps for frontend 2024-08-17 15:07:56 +08:00
qwqcode 0803e235a4 chore(docker): update docker-compose.yml file sample 2024-08-07 18:50:14 +08:00
qwqcode 125a66611f chore(deps/go): upgrade gorilla/websocket 2024-08-05 17:13:11 +08:00
qwqcode 92a0e23c85 chore(plugin/katex): add artalk to peerDependencies in package.json 2024-08-02 10:54:16 +08:00
qwqcode c75b630e8a chore(plugin/lightbox): upgrade version of plugin-lightbox 2024-07-25 16:35:31 +08:00
qwqcode d22d34c223 fix(plugin/lightbox): fix import for non-browser env (#931)
* fix(plugin_lightbox): fix lightbox plugin import for non-browser env

* add artalk as peerDependency

* using default object of import result

* test and fix photoSwipe, fancyBox

* add minimal reproducible example

* refine docs
2024-07-25 16:30:34 +08:00
qwqcode 6fe8ffd2c4 chore(docs): remove obsolete cdn links 2024-07-21 19:35:30 +08:00
qwqcode f4d33fcf24 chore(auth/icon): fix missing microsoft auth icon (#929) 2024-07-16 14:28:43 +08:00
qwqcode 640f9904fb chore(docs): update config.md 2024-07-13 14:58:16 +08:00
qwqcode df62de09f3 fix(api/auth): register issue due to unremoved auth records after user deletion (#919) 2024-07-12 14:12:15 +08:00
qwqcode 68bcdbe3e8 fix(api/auth): migrate auth_identities when account merging (#920) 2024-07-12 13:26:27 +08:00
qwqcode e663893fd1 perf(notify): improve error messages for notify (#943) 2024-07-11 13:12:12 +08:00
qwqcode b85d845b71 chore(docs): revise docker compose env variable config (#933) 2024-06-21 21:20:31 +08:00
qwqcode acf7480b91 fix(api/auth): fix missing Microsoft oauth provider configuration (#929) 2024-06-19 22:10:11 +08:00
qwqcode be0dcd6b59 feat(ui/plugin): make ui plugin configurable 2024-06-19 21:00:32 +08:00
qwqcode 4d9445c84c chore(docs): refine some docs 2024-06-19 20:46:02 +08:00
qwqcode 1337e81cd4 fix(ui/plugin-kit): fix typescript lib folder for api-extractor in monorepo 2024-06-19 20:43:36 +08:00
qwqcode d053b953a6 refactor(ui/deps): remove abortcontroller-polyfill (#923) 2024-06-10 17:00:56 +08:00
qwqcode 2549052558 perf(app/init): generate translated config file by env variable ATK_LOCALE 2024-06-09 22:45:23 +08:00
qwqcode b8da04e308 chore(docs): update import-framework.md 2024-06-09 22:18:35 +08:00
github-actions[bot] c4a7162302 chore: release v2.8.7 (#918)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-09 19:14:50 +08:00
qwqcode 6012993fe9 chore(deps): upgrade go deps 2024-06-09 18:36:13 +08:00
qwqcode d4ed7f64b2 refactor(ui): fix linter issues for ui and docs (#917)
* refactor(ui): fix linter issues for ui and docs

* fix ci
2024-06-09 18:31:04 +08:00
qwqcode 93e3b2f184 perf(ui/dev): bump eslint to v9 (#915)
* perf(ui/dev): bump eslint to version 9

* add react eslint plugin and replace import with import-x
2024-06-09 15:20:04 +08:00
qwqcode 0e75457499 chore(deps): upgrade node and pnpm 2024-06-08 16:55:20 +08:00
zarev b8151bb789 docs(i18n): revise French translation (#913) 2024-06-08 16:50:06 +08:00
qwqcode 67922f34ad fix(api/auth): include render mustache params for verification email subject (#910) 2024-06-08 16:40:35 +08:00
qwqcode 7093e7e1c5 perf(gravatar): support both sha256 and md5 hash for gravatar (#912) 2024-06-08 16:22:26 +08:00
qwqcode c3558b7beb perf(dao): add singleflight for no-cache db find func 2024-06-08 13:48:37 +08:00
qwqcode 5fdf3a27ce fix(auth): failed to register by social account on mysql database (#902) 2024-06-06 14:57:35 +08:00
qwqcode f8f509c0de perf(gravatar): convert email to lowercase before hashing for gravatar 2024-06-04 18:39:51 +08:00
qwqcode 437d943691 chore(docs): tidy up and update links 2024-06-02 15:33:09 +08:00
qwqcode 401cf5c21a perf(conf): add cache for config metadata to boost startup speed (#892) 2024-06-02 15:04:29 +08:00
qwqcode 77e9a687ac docs(dev): refine contributing.md and translate to chinese 2024-06-01 21:27:00 +08:00
qwqcode 85f88cbba5 perf(ui/conf): exclude conf pvEl, countEl and statPageKeyAttr from remove server (#905) 2024-06-01 21:25:29 +08:00
qwqcode efb34c23e5 chore(docs): revise katex import introduction (#897) 2024-05-31 19:30:35 +08:00
qwqcode 822a85c9e3 chore(plugins): fix window not defined issue for plugin-kit 2024-05-30 21:47:46 +08:00
qwqcode 630a3b1ff8 chore(docs): fix docs katex css 2024-05-30 20:14:18 +08:00
qwqcode ca6f8ed09c fix(plugin_katex): fix event issue causing katex integration failure (#897) 2024-05-30 20:03:02 +08:00
qwqcode a0b0a33862 feat(plugin_kit): add vite plugin for developing artalk plugins (#904) 2024-05-30 19:31:55 +08:00
qwqcode 4868cd9992 docs: refine documentation 2024-05-30 19:10:55 +08:00
qwqcode 2dfee533da fix(api/stats): fix site_pv response body and add unit tests (#896) 2024-05-29 10:57:14 +08:00
qwqcode dcaaefc71b refactor(dao): add date field to the page json entity 2024-05-29 10:52:25 +08:00
qwqcode 499a57213e chore(docs): fix edit link and update cases.md 2024-05-28 17:49:47 +08:00
Ever Fu b7fc86b3c6 chore(docs): add hexo-theme-solitude to cases.md (#893) 2024-05-28 17:35:50 +08:00
qwqcode 161ff8bfc3 fix(conf_env): enhance environment variable loading for config (#892)
* fix(conf_env): enhance environment variable loading for config

* improve NumberKeysMapToSlice func and fix unit tests

* auto-generate docs table
2024-05-27 20:03:18 +08:00
qwqcode 1e36d45ec3 chore(ci): remove arm/v7 docker build 2024-05-26 17:36:00 +08:00
qwqcode d2161cc0fb refactor(dao): improve QueryDBWithCache func and concurrent unit tests (#884) 2024-05-26 17:15:32 +08:00
qwqcode abbddfe9b4 feat(sync): add keyed rw-mutex 2024-05-26 17:05:45 +08:00
qwqcode 860dd698e7 feat(go): upgrade golang to v1.22.3 and some deps 2024-05-25 18:36:52 +08:00
guangwu acb087887c fix(api/transfer_upload): close temp file in transfer upload endpoint (#877) 2024-05-25 18:22:50 +08:00
qwqcode dbb3c55148 refactor(transfer): improve the reliability of the transfer (#883) 2024-05-25 18:00:27 +08:00
qwqcode fdfeef8042 fix(ui/sidebar): unable to logout if user is not admin in control center 2024-05-24 16:39:22 +08:00
qwqcode 824f122dcb refactor(ui/stat): use class selector for pageview elements by default (#880)
The statistics UI component has been updated. The default selectors for `pvEl` and `countEl` have changed from `#ArtalkPV` and `#ArtalkCount` to `.artalk-pv-count` and `.artalk-comment-count` (see #826 for more details). However, it remains backward compatible with the `#ArtalkPV` and `#ArtalkCount` elements for older versions, no HTML client updates are necessary.

In this PR, we also introduced a configuration option called `statPageKeyAttr` (value `"data-page-key"` by default) for customizing the attribute name that the statistics component uses to fetch the page key.
2024-05-23 13:47:07 +08:00
qwqcode 53d46d82b6 perf(gravatar): use sha256 hashing algorithm for gravatar (#874) 2024-05-22 21:14:43 +08:00
qwqcode bb218d0ba4 docs(ip_region): add instructions for obtaining accurate IP under proxy 2024-05-15 21:37:16 +08:00
qwqcode 984071d4b6 refactor(transfer): strip domain from page key by default (#873) 2024-05-15 20:58:53 +08:00
qwqcode 34b24a1f36 fix(ui/height_limit): height limit issue for collapsed comments (#865) 2024-05-15 15:43:26 +08:00
qwqcode 58657524cf fix(ui/types): remove marked dependency in dts (#868) 2024-05-11 22:29:40 +08:00
Kent Liao b5db161697 chore(docs): fix syntax error in import-blog (#864)
hexo example.
2024-05-10 09:15:47 +08:00
github-actions[bot] 4dd0ae40e2 chore: release v2.8.6 (#862)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-09 13:43:53 +08:00
qwqcode 5dea08a3f2 feat(ci): include frontend dist files in release (#860) 2024-05-09 13:24:50 +08:00
qwqcode 92464085e6 chore(pkg_manager): upgrade pnpm to v9.1.0 2024-05-09 11:52:08 +08:00
qwqcode 28f1fa11bd chore: remove console logs 2024-05-07 14:00:28 +08:00
qwqcode 3de1f11f47 chore(docs/landing): add animation for ocean wave 2024-05-06 20:36:23 +08:00
qwqcode dff1813fa5 chore(docs/landing): fix airplane animation 2024-05-06 20:35:30 +08:00
vybfi f4475830da chore(docs): fix vue example code (#856) 2024-05-06 16:42:06 +08:00
qwqcode 9c85a85153 docs: update introduction document 2024-05-04 21:17:38 +08:00
qwqcode 5a63d4c63d fix(sidebar/site): unable to edit the new site urls 2024-05-04 16:15:02 +08:00
qwqcode b8afcbb21a fix(cache/user): user id cache from email lookup not cleared 2024-05-04 09:48:06 +08:00
qwqcode 0c0a207068 chore(deps): upgrade go and ui deps 2024-05-03 23:25:41 +08:00
qwqcode be939816aa chore(ip_region): mute ipv6 invalid log 2024-05-03 23:25:11 +08:00
qwqcode 45d1bc1241 fix(api/pv): add mutex for page pv record endpoint 2024-05-03 23:25:10 +08:00
qwqcode ef5899e079 docs(auth): add social login feature (#854) 2024-05-03 23:25:10 +08:00
qwqcode 7187d0f058 feat(ui/auth): plugin-auth for integrating social login (#854) 2024-05-03 23:24:58 +08:00
qwqcode 88aec7e767 feat(auth): user accounts merge tool (#854) 2024-05-03 21:54:15 +08:00
qwqcode a09628c4e8 feat(auth): social login api endpoints (#854) 2024-05-03 21:54:06 +08:00
qwqcode 23d0d868de feat(sync): add keyed mutex 2024-05-03 21:25:31 +08:00
qwqcode f3e356e450 chore(template): tidy up template pkg naming 2024-05-02 17:19:40 +08:00
qwqcode 170db0fc2a feat(ui/img_lazyload): add support for lazy loading images (#850) 2024-05-02 11:03:34 +08:00
qwqcode c3f730b0e7 fix(ui/height_limit): height limit not working while loading images (#849) 2024-05-01 22:53:33 +08:00
qwqcode e132c31150 fix(ui/marked): optimize same origin link judgment logic 2024-04-30 16:18:32 +08:00
qwqcode fa6648ecf5 fix(db/migrate): fix root_id migrate for database lacking recursive CTE support (#848) (#846) 2024-04-30 14:40:27 +08:00
qwqcode a9331b426e fix(dao): ensure find and create functions thread safe (#845)
* fix(dao): ensure find and create functions thread safe

* feat(db/migrator): provide tool for merging duplicate page
2024-04-30 14:17:24 +08:00
qwqcode fbd1cd984d fix(ui/dark_mode): add support for configuring dark mode in backend (#790) 2024-04-27 19:57:09 +08:00
qwqcode accd10cef4 fix(ui/dark_mode): unable to toggle dark mode for sidebar in auto mode 2024-04-27 19:55:20 +08:00
qwqcode 690eb47eaa docs(i18n): add translation for Korean and Russian 2024-04-27 19:11:29 +08:00
qwqcode fc0dcee06c feat(i18n): add incremental updates feature for i18n code scan tool 2024-04-27 19:09:34 +08:00
qwqcode 895bfbd5e2 chore(multi_push): add response status code check 2024-04-27 19:06:26 +08:00
qwqcode e254350211 feat(multi_push/lark): add card mode for lark push (#839) 2024-04-27 19:05:30 +08:00
qwqcode f226d476e5 chore(typo): fix typo for moderator.keywords.replace in conf 2024-04-27 13:26:49 +08:00
qwqcode ee131fe6ef fix(comments_get): include site_name for isolation in associated query for comment's page 2024-04-26 16:42:35 +08:00
qwqcode 43e4c901b8 chore(db_logger): increase the slow SQL warning threshold 2024-04-26 16:35:52 +08:00
qwqcode bd5da20dd6 fix(db_migrate): drop fk_comments_user foreign key constraint of the users table 2024-04-26 16:34:40 +08:00
qwqcode 116d8f1919 chore(ci): fix build workflow 2024-04-25 00:01:51 +08:00
github-actions[bot]andqwqcode 99b71a15f8 chore: release v2.8.5 (#844)
* chore: release v2.8.5

* Update CHANGELOG.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: qwqcode <22412567+qwqcode@users.noreply.github.com>
2024-04-24 23:19:18 +08:00
qwqcode 3255cb4b66 chore(deps): upgrade go deps 2024-04-24 23:11:29 +08:00
qwqcode 35d5f778b2 fix(transfer): retrieve root_id for imported comment data 2024-04-24 23:04:10 +08:00
qwqcode 9375ef812a fix(dao): prevent potential infinite loop in FindCommentRootID 2024-04-24 23:04:10 +08:00
qwqcode 44742c149e fix(db/migrate): issue with root id generation 2024-04-24 23:04:09 +08:00
qwqcode a4d5135379 perf(i18n): add translation for 'parameter is required' 2024-04-24 23:04:09 +08:00
qwqcode ddfaa603ca feat(conf/http): add http.proxy_header config option 2024-04-24 23:03:58 +08:00
qwqcode 6e13152fc1 fix(upload): add config option to solve request entity too large issue (#834) 2024-04-18 18:30:51 +08:00
qwqcode 0b16c9627a fix(ui/upload): unable to upload image when file extension is uppercase 2024-04-18 18:25:25 +08:00
qwqcode b613a4368c fix(log): improve log system and fix memory leaks (#843) 2024-04-18 18:25:19 +08:00
qwqcode 3098a75a05 perf(ui/version_check): beautify version upgrade notice 2024-04-15 15:05:42 +08:00
qwqcode d71ac6d156 chore(docs): update daemon.md 2024-04-15 14:42:13 +08:00
qwqcode 6c9a7e3884 chore(deps): upgrade go deps 2024-04-15 14:38:03 +08:00
qwqcode 65b440416d chore(ci): release workflow allows manual custom version 2024-04-15 14:32:36 +08:00
qwqcode f9084cbfb4 chore(changelog): skip v2.8.4 2024-04-15 14:32:36 +08:00
qwqcode 3c7ad1d0ef fix(ui/sidebar): user list not refresh when data is modified 2024-04-15 14:32:31 +08:00
qwqcode 1930d842f2 fix(ui/comment): missing reply comment data when inserting (#838) 2024-04-15 13:55:51 +08:00
qwqcode 751e4a866f fix(ui/comment): incorrect reply comment data in nested mode (#771) (#837) 2024-04-15 13:09:20 +08:00
Big_Cake 01364d1ddc docs(extras): add deploy guide for Valaxy (#836) 2024-04-15 12:20:09 +08:00
qwqcode ec6d2b2e60 fix(db/migrator): remove foreign key constraints and better root_id generation (#835)
Add function to delete all foreign key constraints when migration.

Leave relationship maintenance to the program and reduce the difficulty of database management. Because there are many different DBs and the implementation of foreign keys may be different, and the DB may not support foreign keys, so don't rely on the foreign key function of the DB system.
2024-04-14 23:46:22 +08:00
qwqcode 915b5f48b4 refactor(ui/prettier): add prettier code formatter 2024-04-14 23:42:06 +08:00
Mr.Hopeandqwqcode 16527ec4f3 perf(ui/pkg): add shorter export names (#821)
* feat(artalk): add shorter export names

* chore: tweaks

* chore: mute attw

---------

Co-authored-by: qwqcode <qwqcode@gmail.com>
2024-04-08 14:51:32 +08:00
Mr.Hope a7af2b7aaa chore(ui/deps): update deps for ui (#820) 2024-04-08 14:42:24 +08:00
github-actions[bot] 3ff891be90 chore: release v2.8.4 (#818)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-07 21:51:42 +08:00
dependabot[bot] 7d6faf6431 chore(deps/ci): bump the deps group in /.github/workflows with 4 updates (#784)
Bumps the deps group in /.github/workflows with 4 updates: [pnpm/action-setup](https://github.com/pnpm/action-setup), [github/codeql-action](https://github.com/github/codeql-action), [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) and [peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch).


Updates `pnpm/action-setup` from 2 to 3
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v2...v3)

Updates `github/codeql-action` from 2 to 3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

Updates `peter-evans/create-pull-request` from 5 to 6
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v5...v6)

Updates `peter-evans/repository-dispatch` from 2 to 3
- [Release notes](https://github.com/peter-evans/repository-dispatch/releases)
- [Commits](https://github.com/peter-evans/repository-dispatch/compare/v2...v3)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: deps
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: deps
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: deps
- dependency-name: peter-evans/repository-dispatch
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-07 21:47:42 +08:00
qwqcode 73d8ea97ed perf(conf/upgit): disallow custom executable path of upgit for security (#817)
BREAKING CHANGE: For UpGit users: Due to security reasons, Artalk no longer allows configuring the executable file path (img_upload.upgit.exec) for upgit. Please add it to system environment variables instead.
2024-04-07 21:43:44 +08:00
qwqcode c482e19f19 chore(sidebar): fix build type issue when upgrade deps
https://github.com/posva/unplugin-vue-router/issues/353
2024-04-07 20:10:19 +08:00
qwqcode 8c3042cdb1 chore(ui/deps): bump deps for ui 2024-04-07 19:57:03 +08:00
qwqcode ed9a78472d chore(ui/dev): bump node to v20.12.1 2024-04-07 19:49:39 +08:00
qwqcode ae5543df52 feat(go): upgrade golang to v1.22.1 and some deps 2024-04-07 19:29:47 +08:00
qwqcode c2c5a80d8d refactor(comments_get): reduce api complexity by introducing LiteDB (#800)
* refactor(comments_get): reduce interface complexity by introducing LiteDB

* test: add unit test

* add more unit test case
2024-04-07 19:17:01 +08:00
Otstar Lin de5e1b4000 fix(ui/lifecycle): keep root element during destroy (#810) 2024-04-02 22:29:08 +08:00
qwqcode b60cb585b6 perf(db): optimize N+1 query in comment list (#799) 2024-03-17 21:01:42 +08:00
qwqcode 44bca8d2f4 fix(cmd/gen): ensure directory before saving in gen cmd (#612) 2024-03-16 16:07:20 +08:00
qwqcode 9103a923a6 chore(ci/nightly): build arm64 on M1 macOS runner
https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/
https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
2024-03-16 15:23:53 +08:00
thun888 e4242512f8 chore(docs): update case link (#793)
* Update cases.md

* Update extras.md
2024-03-16 01:37:47 +08:00
zarev 0ebd16a5db docs(i18n): add French translation (#797) 2024-03-16 01:24:13 +08:00
qwqcode 0eb75f612a chore(ci/nightly): build arm64 on M1 macOS runner
https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/
https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
2024-03-16 01:12:39 +08:00
qwqcode 18e6ae5b17 chore(ci/nightly): improve nightly build workflow 2024-03-15 17:57:17 +08:00
qwqcode 1ee3c41199 feat(ci/build): add nightly build workflow 2024-03-15 12:54:19 +08:00
635 changed files with 31988 additions and 15987 deletions

No files matched your search

+38 -38
View File
@@ -1,7 +1,7 @@
version: 2.1
orbs:
node: circleci/node@5.0.3
node: circleci/node@5.2.0
codecov: codecov/codecov@3.3.0
executors:
@@ -10,10 +10,10 @@ executors:
- image: cimg/base:stable
node:
docker:
- image: 'cimg/node:18.19.0'
- image: "cimg/node:20.17.0"
go:
docker:
- image: cimg/go:1.21.5
- image: cimg/go:1.22.6
parameters:
trigger-app:
@@ -26,43 +26,43 @@ parameters:
jobs:
## Backend
test_app:
executor: go
working_directory: ~/go/src/github.com/ArtalkJS/Artalk
environment:
GO111MODULE: "on"
steps:
- checkout
- run:
name: "Print the Go version"
command: >
go version
- restore_cache:
keys:
- go-mod-1.21.5-{{ checksum "go.sum" }}
- run:
name: Install Dependencies
command: go mod download
- save_cache:
key: go-mod-1.21.5-{{ checksum "go.sum" }}
paths:
- "~/go/pkg/mod"
- run:
name: Run tests
command: |
mkdir -p /tmp/test-reports
gotestsum --junitfile /tmp/test-reports/unit-tests.xml -- -coverprofile=/tmp/test-reports/coverage.out ./...
- store_test_results:
path: /tmp/test-reports
- codecov/upload:
flags: go
file: /tmp/test-reports/coverage.out
executor: go
working_directory: ~/go/src/github.com/ArtalkJS/Artalk
environment:
GO111MODULE: "on"
steps:
- checkout
- run:
name: "Print the Go version"
command: >
go version
- restore_cache:
keys:
- go-mod-1.22.6-{{ checksum "go.sum" }}
- run:
name: Install Dependencies
command: go mod download
- save_cache:
key: go-mod-1.22.6-{{ checksum "go.sum" }}
paths:
- "~/go/pkg/mod"
- run:
name: Run tests
command: |
mkdir -p /tmp/test-reports
gotestsum --junitfile /tmp/test-reports/unit-tests.xml -- -coverprofile=/tmp/test-reports/coverage.out ./...
- store_test_results:
path: /tmp/test-reports
- codecov/upload:
flags: go
file: /tmp/test-reports/coverage.out
all_projects:
executor: base
steps:
- run:
command: |
echo "all"
executor: base
steps:
- run:
command: |
echo "all"
workflows:
build-app:
+3 -1
View File
@@ -17,9 +17,11 @@ workflows:
mapping: |
(cmd|internal|server|pkg|test|conf)/.* trigger-app true
main.go|go.mod|go.sum trigger-app true
base-revision: master # git branch name
base-revision: master # git branch name
config-path: .circleci/conditional_config.yml
filters:
branches:
ignore:
- gh-pages
- /release\/.+/
- nightly
-14
View File
@@ -1,14 +0,0 @@
# don't ever lint node_modules
node_modules
# don't lint build output (make sure it's set to your correct build folder name)
dist
# don't lint nyc coverage output
coverage
vite*.config*
# ignore all js files
**/*.*js
# ignore all config files
*.config.ts
-50
View File
@@ -1,50 +0,0 @@
const path = require('node:path')
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
env: { browser: true },
parserOptions: {
project: ['./ui/*/tsconfig.json'],
tsconfigRootDir: __dirname,
},
extends: [
'airbnb-base',
'airbnb-typescript/base',
'prettier',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:compat/recommended',
],
plugins: ['@typescript-eslint', 'import'],
rules: {
'no-alert': 'warn',
'no-unused-vars': 0,
'no-plusplus': 0,
'no-param-reassign': 0,
'no-console': 0,
'no-underscore-dangle': 0,
'class-methods-use-this': 0,
'spaced-comment': 0,
'no-lonely-if': 0,
'prefer-destructuring': 0,
'import/prefer-default-export': 0,
'import/no-extraneous-dependencies': 0,
'@typescript-eslint/lines-between-class-members': 0,
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-use-before-define': 0,
'@typescript-eslint/naming-convention': 0,
'@typescript-eslint/no-useless-constructor': 0,
'@typescript-eslint/no-unused-expressions': 0, // for `func && func()` expressions
},
settings: {
'import/resolver': {
typescript: {
project: ['ui/artalk/tsconfig.json'].map((p) =>
path.resolve(__dirname, p),
),
},
},
polyfills: ['AbortController'],
},
}
+3 -2
View File
@@ -2,7 +2,8 @@
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: artalk # Replace with a single Open Collective username
open_collective: # Replace with a single Open Collective username
buy_me_a_coffee: artalk
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
@@ -11,4 +12,4 @@ issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
- https://afdian.net/a/artalk
- https://afdian.com/a/artalk
+2 -2
View File
@@ -4,8 +4,8 @@ info:
title: CHANGELOG
repository_url: https://github.com/ArtalkJS/Artalk
options:
tag_filter_pattern: '^v'
sort: "date"
tag_filter_pattern: "^v"
sort: date
commits:
filters:
Type:
+4 -4
View File
@@ -14,7 +14,7 @@ updates:
groups:
deps:
patterns:
- '*'
- "*"
open-pull-requests-limit: 15
- package-ecosystem: npm
@@ -39,7 +39,7 @@ updates:
groups:
deps:
patterns:
- '*'
- "*"
open-pull-requests-limit: 15
- package-ecosystem: docker
@@ -51,7 +51,7 @@ updates:
groups:
deps:
patterns:
- '*'
- "*"
open-pull-requests-limit: 15
- package-ecosystem: github-actions
@@ -63,5 +63,5 @@ updates:
groups:
deps:
patterns:
- '*'
- "*"
open-pull-requests-limit: 15
+4 -4
View File
@@ -11,7 +11,7 @@ on:
type: boolean
env:
GO_VERSION: 1.21.5
GO_VERSION: 1.22.6
PKG_NAME: github.com/ArtalkJS/Artalk
DOCKER_IMG: ghcr.io/goreleaser/goreleaser-cross
CACHE_DIR: /tmp/cache/docker-image
@@ -51,9 +51,9 @@ jobs:
- name: Setup git-chglog
run: |
curl -sL $(curl -s https://api.github.com/repos/git-chglog/git-chglog/releases/latest \
| grep -oP '"https://.+linux_amd64.tar.gz"' | tr -d \") | tar -C /usr/local/bin -xz git-chglog
git-chglog --version
curl -sL $(curl -s https://api.github.com/repos/git-chglog/git-chglog/releases/latest \
| grep -oP '"https://.+linux_amd64.tar.gz"' | tr -d \") | tar -C /usr/local/bin -xz git-chglog
git-chglog --version
- name: Pre Build
run: |-
+1 -1
View File
@@ -66,7 +66,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and Push
id: build
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
push: ${{ !inputs.dry_run }}
context: .
+361
View File
@@ -0,0 +1,361 @@
name: Build Nightly
run-name: Build Nightly
on:
schedule:
- cron: "0 10 * * *"
workflow_dispatch:
inputs:
dry_run:
description: "Dry run"
type: boolean
default: true
env:
DIST_DIR: /tmp/builds
DIGEST_DIR: /tmp/digests
DOCKER_IMG: artalk/artalk-go
DOCKER_BUILD_ARGS: |-
SKIP_UI_BUILD=true
jobs:
# Prepare check should run
prepare:
runs-on: ubuntu-latest
outputs:
skip: ${{ steps.check.outputs.skip }}
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Check should run
id: check
if: github.event_name == 'schedule'
run: |
if [[ "$(git log --since='24 hours ago' | wc -l)" -eq 0 ]] || \
[[ "$GITHUB_REPOSITORY" != "ArtalkJS/Artalk" ]]; then
echo "skip=true" >> $GITHUB_OUTPUT
fi
# Bulid UI first
# (build ui outside of docker to speed up cross-platform builds)
ui:
if: ${{ needs.prepare.outputs.skip != 'true' }}
needs: prepare
runs-on: macos-14
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.9.0
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20.x
registry-url: https://registry.npmjs.org/
cache: "pnpm"
- name: Get pnpm store directory
shell: bash
run: |
echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ env.PNPM_STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build UI
run: |
make build-frontend
- name: Pack UI
id: pack
run: |
SRC_FILE=$(pnpm pack -C ui/artalk --pack-destination ../.. | tail -n 1)
mkdir -p bin
PKG_FILE="bin/artalk_frontend_nigthly_$(date +'%Y%m%d').tar.gz"
mv $SRC_FILE $PKG_FILE
echo "pkg_file=$PKG_FILE" >> $GITHUB_OUTPUT
- name: Upload UI
uses: actions/upload-artifact@v4
with:
name: ui-src
path: |
public
ui/artalk/dist
if-no-files-found: error
retention-days: 1
- name: Upload UI package
uses: actions/upload-artifact@v4
with:
name: build-ui-pkg
path: ${{ steps.pack.outputs.pkg_file }}
retention-days: 1
#
# Build app on different platforms
#
build:
needs: ui
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
# - macos-14
# :(
# native Apple m1 arm64 is not supported nested virtualization yet, so docker qemu is not working.
# https://github.com/actions/runner-images/issues/9460
# https://docs.veertu.com/anka/anka-virtualization-cli/nested-virtualization/
#
# wait for arm64 linux runner support on github actions.
platform:
- linux/amd64
- linux/arm64
# exclude:
# # exclude build x86 on arm, and vice versa.
# - { os: macos-14, platform: linux/amd64 }
# - { os: ubuntu-latest, platform: linux/arm64 }
steps:
- name: Prepare
run: |
PF="${{ matrix.platform }}"
echo "PLATFORM_PAIR=${PF//\//_}" >> $GITHUB_ENV
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup docker on macos
if: startsWith(matrix.os, 'macos')
uses: crazy-max/ghaction-setup-docker@v3
- name: Gen docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.DOCKER_IMG }}
tags: type=raw,value=nightly
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Download UI before build
uses: actions/download-artifact@v4
with:
name: ui-src
- name: Build and push by digest
uses: docker/build-push-action@v6
id: build
with:
context: .
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
build-args: ${{ env.DOCKER_BUILD_ARGS }}
# The `type=image,push=true` must the last one,
# because the `build.outputs.digest` will output the last image's digest.
# The digests will be used in the merge step.
outputs: |
type=docker,name=${{ env.DOCKER_IMG }}
type=image,push=true,name=${{ env.DOCKER_IMG }},push-by-digest=true,name-canonical=true
- name: Export digest
run: |
mkdir -p $DIGEST_DIR
digest="${{ steps.build.outputs.digest }}"
touch "$DIGEST_DIR/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ env.DIGEST_DIR }}/*
if-no-files-found: error
retention-days: 1
# Export docker image
- name: Export Docker Image
id: docker
run: |
IMG_FILE="artalk_docker_nigthly_$(date +'%Y%m%d')_${PLATFORM_PAIR}.tar.gz"
docker save ${{ env.DOCKER_IMG }} | gzip > $IMG_FILE
echo "img_file=$IMG_FILE" >> $GITHUB_OUTPUT
# App
- name: Pack app
id: app
run: |
BASE_DIR="/tmp/app_pkg"
NAME="artalk_nigthly_$(date +'%Y%m%d')_${PLATFORM_PAIR}"
SUB_DIR="$BASE_DIR/$NAME"
PKG_FILE="$BASE_DIR/$NAME.tar.gz"
# bin file
mkdir -p $SUB_DIR
docker run --rm --entrypoint cat ${{ env.DOCKER_IMG }} /artalk > "$SUB_DIR/artalk"
chmod +x "$SUB_DIR/artalk"
# doc file
cp conf/artalk.example.yml "$SUB_DIR/artalk.yml"
cp README.md LICENSE CHANGELOG.md "$SUB_DIR"
# create package file
tar -czf $PKG_FILE -C $BASE_DIR $NAME
echo "app_pkg_file=$PKG_FILE" >> $GITHUB_OUTPUT
# Move build artifacts
- name: Move build artifacts
run: |
mkdir -p $DIST_DIR
mv ${{ steps.app.outputs.app_pkg_file }} $DIST_DIR
mv ${{ steps.docker.outputs.img_file }} $DIST_DIR
# Upload build artifacts
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ env.PLATFORM_PAIR }}
path: ${{ env.DIST_DIR }}/*
if-no-files-found: error
retention-days: 1
# Merge docker digests from different platforms
# Reference: https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
docker_merge:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: ${{ env.DIGEST_DIR }}
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.DOCKER_IMG }}
tags: type=raw,value=nightly
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create manifest list and push
working-directory: ${{ env.DIGEST_DIR }}
run: |
TAGS_ARG=$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON")
MINIFEST_SRCS=$(printf '${{ env.DOCKER_IMG }}@sha256:%s ' *)
docker buildx imagetools create ${TAGS_ARG} ${MINIFEST_SRCS}
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.DOCKER_IMG }}:${{ steps.meta.outputs.version }}
# Release
release:
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download builds
uses: actions/download-artifact@v4
with:
path: ${{ env.DIST_DIR }}
pattern: build-*
merge-multiple: true
# Generate CHANGELOG
- name: Generate Changelog
run: |
# install git-chglog
curl -sL $(curl -s https://api.github.com/repos/git-chglog/git-chglog/releases/latest \
| grep -oP '"https://.+linux_amd64.tar.gz"' | tr -d \") | tar -C /usr/local/bin -xz git-chglog
CHANGELOG=$(git-chglog --config .github/chglog/config.yml --next-tag nightly nightly)
MD_FILE="/tmp/changelog.md"
echo -e "$CHANGELOG" > $MD_FILE
echo -e "\n> [!NOTE]\n" \
"> The Nightly version, automatically built based on the latest code, " \
"is not yet released and may be unstable. Please use it with caution. " \
"Docker user can run \`docker pull artalk/artalk-go:nightly\` to get " \
"the nightly build." >> $MD_FILE
# checksums.txt
- name: Calculate checksums.txt
run: |
cd $DIST_DIR
sha256sum * > checksums.txt
# print checksums.txt
cat checksums.txt
FILES=$(find ${DIST_DIR} -type f -exec readlink -f {} \;)
echo -e "RELEASE_FILES<<EOF" >> $GITHUB_ENV
echo -e "$FILES" >> $GITHUB_ENV
echo -e "EOF" >> $GITHUB_ENV
- name: Create tag and push
env:
GH_TOKEN: ${{ github.token }}
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
gh release delete nightly --yes || true
git push origin :refs/tags/nightly || true
git tag -f nightly
git push -f origin nightly
- name: Release
uses: softprops/action-gh-release@v2
with:
prerelease: true
tag_name: nightly
name: 🧪 Nightly Version
body_path: /tmp/changelog.md
files: ${{ env.RELEASE_FILES }}
draft: false
+4 -3
View File
@@ -11,7 +11,7 @@ on:
type: number
outputs:
version:
description: 'Version'
description: "Version"
value: ${{ jobs.tagging.outputs.version }}
jobs:
@@ -22,8 +22,9 @@ jobs:
run: |
# `github.head_ref` only exists for pull_request events
REF="${{ github.head_ref || github.ref }}"
VERSION="${REF#release/}"
VERSION="${VERSION#refs/tags/}"
VERSION="${REF#refs/tags/}"
VERSION="${VERSION#refs/heads/}"
VERSION="${VERSION#release/}"
echo "Version: $VERSION"
echo "VERSION=$VERSION" >> $GITHUB_ENV
+4 -4
View File
@@ -21,16 +21,16 @@ jobs:
ref: ${{ inputs.version }}
- name: Use pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: 8
version: 9.9.0
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 20.x
registry-url: https://registry.npmjs.org/
cache: 'pnpm'
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
+4 -4
View File
@@ -9,13 +9,13 @@ on:
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run'
description: "Dry run"
type: boolean
default: true
build_items:
description: 'Build items'
description: "Build items"
type: string
default: 'ui,app,docker'
default: "ui,app,docker"
jobs:
# Tag the release version code before building
@@ -54,7 +54,7 @@ jobs:
# since docker push actions will override the previous images,
# so need to build `linux/amd64` and push first,
# then build `linux/amd64` twice with other archs (build very slow so keep it last).
target: ["linux/amd64", "linux/amd64,linux/arm64,linux/arm/v7"]
target: ["linux/amd64", "linux/amd64,linux/arm64"]
with:
version: ${{ needs.tagging.outputs.version }}
dry_run: ${{ inputs.dry_run || false }}
+36 -33
View File
@@ -9,16 +9,18 @@
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
name: CodeQL
on:
push:
branches: [ "master" ]
branches:
- master
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
branches:
- master
schedule:
- cron: '40 17 * * 4'
- cron: "40 17 * * 4"
jobs:
analyze:
@@ -32,43 +34,44 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'go', 'javascript' ]
language:
- go
- javascript
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
+7 -5
View File
@@ -2,8 +2,8 @@ name: Docs CN Mirror Deploy
on:
push:
branches: ['master']
paths: ['docs/**']
branches: ["master"]
paths: ["docs/**"]
jobs:
deploy:
@@ -14,13 +14,15 @@ jobs:
uses: actions/checkout@v4
- name: Use pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: 9.9.0
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 18
cache: "pnpm"
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
+17 -8
View File
@@ -12,8 +12,12 @@ on:
- minor
- major
required: true
custom_version:
description: Manual Custom Version (Special Purpose, v*)
type: string
required: false
dry_run:
description: 'Dry run?'
description: "Dry run?"
type: boolean
default: false
@@ -30,7 +34,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 20.x
registry-url: https://registry.npmjs.org/
- name: Setup semver
@@ -38,8 +42,13 @@ jobs:
- name: Handle Version Number
run: |
PREV_VERSION="$(git describe --tags --abbrev=0)"
NEXT_VERSION="v$(semver --increment ${{ inputs.semver }} ${PREV_VERSION})"
PREV_VERSION="$(git describe --tags --abbrev=0 --match 'v*')"
if [ -n "${{ inputs.custom_version }}" ]; then
NEXT_VERSION="${{ inputs.custom_version }}"
else
NEXT_VERSION="v$(semver --increment ${{ inputs.semver }} ${PREV_VERSION})"
fi
echo "PREV_VERSION=${PREV_VERSION}" >> $GITHUB_ENV
echo "VERSION=${NEXT_VERSION}" >> $GITHUB_ENV
@@ -49,9 +58,9 @@ jobs:
- name: Setup git-chglog
run: |
curl -sL $(curl -s https://api.github.com/repos/git-chglog/git-chglog/releases/latest \
| grep -oP '"https://.+linux_amd64.tar.gz"' | tr -d \") | tar -C /usr/local/bin -xz git-chglog
git-chglog --version
curl -sL $(curl -s https://api.github.com/repos/git-chglog/git-chglog/releases/latest \
| grep -oP '"https://.+linux_amd64.tar.gz"' | tr -d \") | tar -C /usr/local/bin -xz git-chglog
git-chglog --version
- name: Version Changelog
run: |
@@ -69,7 +78,7 @@ jobs:
run: git diff
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
if: ${{ !inputs.dry_run }}
with:
branch: "release/${{ env.VERSION }}"
+2 -2
View File
@@ -8,13 +8,13 @@ on:
type: string
description: Event Type
required: true
default: ''
default: ""
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v2
uses: peter-evans/repository-dispatch@v3
with:
event-type: ${{ inputs.event_type }}
+12 -7
View File
@@ -2,12 +2,12 @@ name: Test Docs
on:
push:
branches: ['*', '!release/*']
paths: ['docs/**']
tags-ignore: ['v*']
branches: ["*", "!release/*", "!nightly"]
paths: ["docs/**"]
tags-ignore: ["v*"]
pull_request:
paths: ['docs/**']
branches: ['*', '!release/*']
paths: ["docs/**"]
branches: ["*", "!release/*", "!nightly"]
jobs:
test_docs:
@@ -18,12 +18,14 @@ jobs:
uses: actions/checkout@v4
- name: Use pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v4
with:
version: 9.9.0
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
node-version: 20.x
cache: pnpm
- name: Install dependencies
@@ -31,3 +33,6 @@ jobs:
- name: Build Docs
run: pnpm build:docs
- name: Lint Docs
run: pnpm eslint docs && pnpm prettier --check docs
+19 -9
View File
@@ -2,12 +2,12 @@ name: Test Frontend
on:
push:
branches: ['*', '!release/*']
paths: ['ui/**']
tags-ignore: ['v*']
branches: ["*", "!release/*", "!nightly"]
paths: ["ui/**"]
tags-ignore: ["v*"]
pull_request:
paths: ['ui/**']
branches: ['*', '!release/*']
paths: ["ui/**"]
branches: ["*", "!release/*", "!nightly"]
jobs:
test_ui:
@@ -19,12 +19,18 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- if: matrix.os == 'windows-latest'
name: Set git to use LF (for Windows environment)
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checkout Code
uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: pnpm/action-setup@v4
with:
version: 8
version: 9.9.0
- name: Use Node.js ${{ matrix.node }}
uses: actions/setup-node@v4
@@ -41,6 +47,10 @@ jobs:
- name: Unit test
run: pnpm test
- name: Lint
run: pnpm eslint ui && pnpm prettier --check ui
# https://github.com/arethetypeswrong/arethetypeswrong.github.io
- name: 'arethetypeswrong test'
run: pnpm -F artalk attw
- name: "arethetypeswrong test"
if: runner.os == 'ubuntu-latest'
run: pnpm -F artalk test:attw || true
+8 -6
View File
@@ -14,9 +14,9 @@ env:
before:
hooks:
# install dependencies
- make install
- make build-frontend
# install dependencies
- make install
- make build-frontend
# build multi-platform
builds:
@@ -60,7 +60,7 @@ builds:
goarch:
- arm
goarm:
- '7'
- "7"
env:
- CC=arm-linux-gnueabihf-gcc
- CXX=arm-linux-gnueabihf-g++
@@ -118,7 +118,7 @@ builds:
# https://go-review.googlesource.com/c/go/+/224588/
# https://github.com/ArtalkJS/Artalk/issues/35
&win_common_flags |
-tags=timetzdata
-tags=timetzdata
# Win (arm_64)
- id: windows-arm64
@@ -156,7 +156,7 @@ archives:
- artalk.yml
checksum:
name_template: 'checksums.txt'
name_template: "checksums.txt"
snapshot:
name_template: "{{.Version}}-SNAPSHOT-{{.ShortCommit}}"
@@ -175,3 +175,5 @@ release:
name: Artalk
prerelease: auto
draft: false
extra_files:
- glob: ./local/release_includes/*
+18
View File
@@ -0,0 +1,18 @@
CHANGELOG.md
CHANGELOG.tpl.md
CDN.html
internal/template/notify_tpl/default.html
# generated files
# @link https://github.com/prettier/prettier/issues/3634
pnpm-lock.yaml
**/auto-imports.d.ts
**/components.d.ts
**/typed-router.d.ts
ui/artalk/src/api/v2.ts
docs/swagger/swagger.json
docs/swagger/swagger.yaml
docs/**
ui/artalk-sidebar/src/lib/md5.js
ui/artalk/src/lib/detect.ts
**/dist/**
+23 -3
View File
@@ -1,6 +1,26 @@
{
"semi": false,
"arrowParens": "always",
"bracketSpacing": true,
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"bracketSameLine": false,
"jsxSingleQuote": false,
"printWidth": 100,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": false,
"singleQuote": true,
"htmlWhitespaceSensitivity": "ignore"
}
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false,
"vueIndentScriptAndStyle": false,
"overrides": [
{
"files": ["*.yaml", "*.yml"],
"options": {
"singleQuote": false
}
}
]
}
+16 -12
View File
@@ -1,14 +1,18 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Artalk for Debugging",
"type": "go",
"request": "launch",
"mode": "exec",
"program": "${workspaceFolder}/bin/artalk",
"preLaunchTask": "Build for debugging",
"args": ["server", "-c", "${workspaceFolder}/data/artalk.yml"]
}
],
"version": "0.2.0",
"configurations": [
{
"name": "Launch Artalk for Debugging",
"type": "go",
"request": "launch",
"mode": "exec",
"program": "${workspaceFolder}/bin/artalk",
"preLaunchTask": "Build for debugging",
"env": {
"ATK_SITE_DEFAULT": "ArtalkDocs",
"ATK_TRUSTED_DOMAINS": "http://localhost:5173 http://localhost:23367"
},
"args": ["server", "-c", "${workspaceFolder}/artalk.yml"]
}
]
}
+61 -17
View File
@@ -1,19 +1,63 @@
{
"cSpell.words": [
"akismet",
"artalk",
"artran",
"artrans",
"artransfer",
"gomail",
"Goreleaser",
"gorm",
"ldflags",
"lfshook",
"Metas",
"pgsql",
"sendmail",
"sqlite",
"pkged"
]
// Enable the ESlint flat config support
"eslint.experimental.useFlatConfig": true,
// Disable the default formatter, use eslint instead
// "prettier.enable": false,
"editor.formatOnSave": false,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
"eslint.runtime": "node",
// Silent the stylistic rules in you IDE, but still auto fix them
"eslint.rules.customizations": [
{ "rule": "style/*", "severity": "off" },
{ "rule": "*-indent", "severity": "off" },
{ "rule": "*-spacing", "severity": "off" },
{ "rule": "*-spaces", "severity": "off" },
{ "rule": "*-order", "severity": "off" },
{ "rule": "*-dangle", "severity": "off" },
{ "rule": "*-newline", "severity": "off" },
{ "rule": "*quotes", "severity": "off" },
{ "rule": "*semi", "severity": "off" }
],
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"xml"
],
"cSpell.words": [
"akismet",
"artalk",
"artran",
"artrans",
"artransfer",
"gomail",
"Goreleaser",
"gorm",
"ldflags",
"lfshook",
"Metas",
"pgsql",
"sendmail",
"sqlite",
"pkged"
]
}
+12 -12
View File
@@ -1,14 +1,14 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build for debugging",
"type": "shell",
"command": "make build-debug",
"group": {
"kind": "build",
"isDefault": true
}
}
]
"version": "2.0.0",
"tasks": [
{
"label": "Build for debugging",
"type": "shell",
"command": "make build-debug",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
+192
View File
@@ -1,4 +1,196 @@
## [v2.9.0](https://github.com/ArtalkJS/Artalk/compare/v2.8.7...v2.9.0) (2024-09-03)
### Features
* **auth:** add user profile and password changing ([#966](https://github.com/ArtalkJS/Artalk/issues/966))
* **config:** add `site_url` config option ([#967](https://github.com/ArtalkJS/Artalk/issues/967))
* **go:** upgrade golang to v1.22.6 and some deps
* **ui/dashboard:** new dashboard ui refresh for desktop devices ([#957](https://github.com/ArtalkJS/Artalk/issues/957))
* **ui/date:** add `dateFormatter` config option ([#940](https://github.com/ArtalkJS/Artalk/issues/940))
* **ui/plugin:** make ui plugin configurable
* **ui/sidebar:** add dark mode toggle for dashboard ([#790](https://github.com/ArtalkJS/Artalk/issues/790))
* **ui/sidebar:** add page search by keywords in sidebar ([#603](https://github.com/ArtalkJS/Artalk/issues/603))
* **ui/sidebar:** add user search by keywords in sidebar ([#710](https://github.com/ArtalkJS/Artalk/issues/710))
### Bug Fixes
* **anti_spam:** handle empty `referer` variable in anti-spam check ([#853](https://github.com/ArtalkJS/Artalk/issues/853))
* **api/auth:** fix missing Microsoft oauth provider configuration ([#929](https://github.com/ArtalkJS/Artalk/issues/929))
* **api/auth:** migrate auth_identities when account merging ([#920](https://github.com/ArtalkJS/Artalk/issues/920))
* **api/auth:** register issue due to unremoved auth records after user deletion ([#919](https://github.com/ArtalkJS/Artalk/issues/919))
* **api/comment_add:** improve the security of comment add api ([#964](https://github.com/ArtalkJS/Artalk/issues/964))
* **auth:** correct email verification code send button
* **plugin/lightbox:** fix import for non-browser env ([#931](https://github.com/ArtalkJS/Artalk/issues/931))
* **plugin_kit:** fix typescript lib path retrieval on win
* **plugin_kit:** import source path case error on linux
* **sidebar:** correct total item count for pagination in sidebar
* **ui/dark_mode:** apply dark mode config option before mounting ui ([#890](https://github.com/ArtalkJS/Artalk/issues/890))
* **ui/plugin-kit:** fix typescript lib folder for api-extractor in monorepo
* **ui/sidebar:** disable admin password check dialog in sidebar
* **ui/sidebar:** show env variables in sidebar settings ui ([#946](https://github.com/ArtalkJS/Artalk/issues/946)) ([#956](https://github.com/ArtalkJS/Artalk/issues/956))
* **ui/stat:** fix invalid backward compatible strategy ([#880](https://github.com/ArtalkJS/Artalk/issues/880))
* **validator:** restrict to allow only HTTP protocol
### Performance Improvements
* **api/auth:** add more specific error messages for login failures
* **app/init:** generate translated config file by env variable `ATK_LOCALE`
* **auth:** add loading skeleton for login methods list
* **auth:** enhance visibility of skip button ([#863](https://github.com/ArtalkJS/Artalk/issues/863))
* **auth:** perform optical adjustment for consistent icon sizing
* **auth:** correct verify button position in register form
* **i18n:** auto-load frontend i18n locale js sources
* **notify:** improve error messages for notify ([#943](https://github.com/ArtalkJS/Artalk/issues/943))
* **plugin_kit:** improve typescript diagnostics output
* **style/sidebar:** modify font-family for sidebar
* **ui/sidebar:** enhance i18n translations for sidebar
* **ui/sidebar:** mask sensitive input values in sidebar settings ([#494](https://github.com/ArtalkJS/Artalk/issues/494))
* **ui/sidebar:** optimize setup process and i18n lazy load ([#962](https://github.com/ArtalkJS/Artalk/issues/962))
### Code Refactoring
* **plugin_katex:** use tokenizer extension of marked ([#955](https://github.com/ArtalkJS/Artalk/issues/955))
* **ui/deps:** remove `abortcontroller-polyfill` ([#923](https://github.com/ArtalkJS/Artalk/issues/923))
* **ui/marked:** replace pkg-level marked with new class instance ([#954](https://github.com/ArtalkJS/Artalk/issues/954))
* **ui/types:** add `Layer` interface
* **ui/user:** rename `nick` to `name` in `LocalUser` data structure ([#961](https://github.com/ArtalkJS/Artalk/issues/961))
### Documentation
* **auth:** set `auth.anonymous` to false as default
* **ui/i18n:** add more locale support for sidebar
* **ui/i18n:** add translations for French, Korean, and Russian
## [v2.8.7](https://github.com/ArtalkJS/Artalk/compare/v2.8.6...v2.8.7) (2024-06-09)
### Features
* **go:** upgrade golang to v1.22.3 and some deps
* **plugin_kit:** add vite plugin for developing artalk plugins ([#904](https://github.com/ArtalkJS/Artalk/issues/904))
* **sync:** add keyed rw-mutex
### Bug Fixes
* **api/auth:** include render mustache params for verification email subject ([#910](https://github.com/ArtalkJS/Artalk/issues/910))
* **api/stats:** fix `site_pv` response body and add unit tests ([#896](https://github.com/ArtalkJS/Artalk/issues/896))
* **api/transfer_upload:** close temp file in transfer upload endpoint ([#877](https://github.com/ArtalkJS/Artalk/issues/877))
* **auth:** failed to register by social account on mysql database ([#902](https://github.com/ArtalkJS/Artalk/issues/902))
* **conf_env:** enhance environment variable loading for config ([#892](https://github.com/ArtalkJS/Artalk/issues/892))
* **plugin_katex:** fix event issue causing katex integration failure ([#897](https://github.com/ArtalkJS/Artalk/issues/897))
* **ui/height_limit:** height limit issue for collapsed comments ([#865](https://github.com/ArtalkJS/Artalk/issues/865))
* **ui/sidebar:** unable to logout if user is not admin in control center
* **ui/types:** remove marked dependency in dts ([#868](https://github.com/ArtalkJS/Artalk/issues/868))
### Performance Improvements
* **conf:** add cache for config metadata to boost startup speed ([#892](https://github.com/ArtalkJS/Artalk/issues/892))
* **dao:** add singleflight for no-cache db find func
* **gravatar:** support both sha256 and md5 hash for gravatar ([#912](https://github.com/ArtalkJS/Artalk/issues/912))
* **gravatar:** convert email to lowercase before hashing for gravatar
* **gravatar:** use sha256 hashing algorithm for gravatar ([#874](https://github.com/ArtalkJS/Artalk/issues/874))
* **ui/conf:** exclude conf `pvEl`, `countEl` and `statPageKeyAttr` from remove server ([#905](https://github.com/ArtalkJS/Artalk/issues/905))
* **ui/dev:** bump eslint to v9 ([#915](https://github.com/ArtalkJS/Artalk/issues/915))
### Code Refactoring
* **dao:** add `date` field to the page json entity
* **dao:** improve `QueryDBWithCache` func and concurrent unit tests ([#884](https://github.com/ArtalkJS/Artalk/issues/884))
* **transfer:** improve the reliability of the transfer ([#883](https://github.com/ArtalkJS/Artalk/issues/883))
* **transfer:** strip domain from page key by default ([#873](https://github.com/ArtalkJS/Artalk/issues/873))
* **ui:** fix linter issues for ui and docs ([#917](https://github.com/ArtalkJS/Artalk/issues/917))
* **ui/stat:** use class selector for pageview elements by default ([#880](https://github.com/ArtalkJS/Artalk/issues/880))
### Documentation
* refine documentation
* **dev:** refine contributing.md and translate to chinese
* **i18n:** revise French translation ([#913](https://github.com/ArtalkJS/Artalk/issues/913))
* **ip_region:** add instructions for obtaining accurate IP under proxy
## [v2.8.6](https://github.com/ArtalkJS/Artalk/compare/v2.8.5...v2.8.6) (2024-05-09)
### Features
* **auth:** user accounts merge tool ([#854](https://github.com/ArtalkJS/Artalk/issues/854))
* **auth:** social login api endpoints ([#854](https://github.com/ArtalkJS/Artalk/issues/854))
* **ci:** include frontend dist files in release ([#860](https://github.com/ArtalkJS/Artalk/issues/860))
* **i18n:** add incremental updates feature for i18n code scan tool
* **multi_push/lark:** add card mode for lark push ([#839](https://github.com/ArtalkJS/Artalk/issues/839))
* **sync:** add keyed mutex
* **ui/auth:** plugin-auth for integrating social login ([#854](https://github.com/ArtalkJS/Artalk/issues/854))
* **ui/img_lazyload:** add support for lazy loading images ([#850](https://github.com/ArtalkJS/Artalk/issues/850))
### Bug Fixes
* **api/pv:** add mutex for page pv record endpoint
* **cache/user:** user id cache from email lookup not cleared
* **comments_get:** include `site_name` for isolation in associated query for comment's page
* **dao:** ensure find and create functions thread safe ([#845](https://github.com/ArtalkJS/Artalk/issues/845))
* **db/migrate:** fix root_id migrate for database lacking recursive CTE support ([#848](https://github.com/ArtalkJS/Artalk/issues/848)) ([#846](https://github.com/ArtalkJS/Artalk/issues/846))
* **db_migrate:** drop `fk_comments_user` foreign key constraint of the users table
* **sidebar/site:** unable to edit the new site urls
* **ui/dark_mode:** add support for configuring dark mode in backend ([#790](https://github.com/ArtalkJS/Artalk/issues/790))
* **ui/dark_mode:** unable to toggle dark mode for sidebar in auto mode
* **ui/height_limit:** height limit not working while loading images ([#849](https://github.com/ArtalkJS/Artalk/issues/849))
* **ui/marked:** optimize same origin link judgment logic
### Documentation
* update introduction document
* **auth:** add social login feature ([#854](https://github.com/ArtalkJS/Artalk/issues/854))
* **i18n:** add translation for Korean and Russian
## [v2.8.5](https://github.com/ArtalkJS/Artalk/compare/v2.8.3...v2.8.5) (2024-04-21)
### Features
* **ci/build:** add nightly build workflow
* **conf/http:** add `http.proxy_header` config option
* **go:** upgrade golang to v1.22.2 and some deps
### Bug Fixes
* **cmd/gen:** ensure directory before saving in `gen` cmd ([#612](https://github.com/ArtalkJS/Artalk/issues/612))
* **dao:** prevent potential infinite loop in `FindCommentRootID`
* **db/migrate:** issue with root id generation
* **db/migrator:** remove foreign key constraints and better `root_id` generation ([#835](https://github.com/ArtalkJS/Artalk/issues/835))
* **log:** improve log system and fix memory leaks ([#843](https://github.com/ArtalkJS/Artalk/issues/843))
* **transfer:** retrieve root_id for imported comment data
* **ui/comment:** missing reply comment data when inserting ([#838](https://github.com/ArtalkJS/Artalk/issues/838))
* **ui/comment:** incorrect reply comment data in nested mode ([#771](https://github.com/ArtalkJS/Artalk/issues/771)) ([#837](https://github.com/ArtalkJS/Artalk/issues/837))
* **ui/lifecycle:** keep root element during destroy ([#810](https://github.com/ArtalkJS/Artalk/issues/810))
* **ui/sidebar:** user list not refresh when data is modified
* **ui/upload:** unable to upload image when file extension is uppercase
* **upload:** add config option to solve request entity too large issue ([#834](https://github.com/ArtalkJS/Artalk/issues/834))
### Performance Improvements
* **conf/upgit:** disallow custom executable path of `upgit` for security ([#817](https://github.com/ArtalkJS/Artalk/issues/817))
* **db:** optimize N+1 query in comment list ([#799](https://github.com/ArtalkJS/Artalk/issues/799))
* **i18n:** add translation for 'parameter is required'
* **ui/pkg:** add shorter export names ([#821](https://github.com/ArtalkJS/Artalk/issues/821))
* **ui/version_check:** beautify version upgrade notice
### Code Refactoring
* **comments_get:** reduce api complexity by introducing `LiteDB` ([#800](https://github.com/ArtalkJS/Artalk/issues/800))
* **ui/prettier:** add prettier code formatter
### Documentation
* **extras:** add deploy guide for Valaxy ([#836](https://github.com/ArtalkJS/Artalk/issues/836))
* **i18n:** add French translation ([#797](https://github.com/ArtalkJS/Artalk/issues/797))
### BREAKING CHANGE
For UpGit users: Due to security reasons, Artalk no longer allows configuring the executable file path (img_upload.upgit.exec) for upgit. Please add it to system environment variables instead.
## [v2.8.3](https://github.com/ArtalkJS/Artalk/compare/v2.8.2...v2.8.3) (2024-03-04)
### Features
+253 -81
View File
@@ -1,126 +1,298 @@
# Developer Contributing Guide
This guide is for developers who want to contribute to the project.
This guide helps developers understand how to contribute code, documentation, tests, and feedback to the Artalk project. We welcome all forms of contributions, whether it's large feature development, small fixes, documentation improvements, or testing. We believe that every contribution is an important part of moving the project forward.
## Development Environment
This guide is available in multiple languages: [English](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md) • [简体中文](https://artalk.js.org/develop/contributing.html)
To develop Artalk, including the frontend and backend, you need to install the following tools:
## Setup
- [Node.js](https://nodejs.org/en/) (>= 18.12.0)
- [Go](https://golang.org/) (>= 1.21)
- [Docker](https://www.docker.com/) (>= 20.10.0) (optional)
- [Docker Compose](https://docs.docker.com/compose/) (>= 1.29.0) (optional)
Then we'll setup the development environment.
### Get the source code
Run the following command to clone the repository:
Clone the repository:
```sh
git clone https://github.com/ArtalkJS/Artalk
git clone https://github.com/ArtalkJS/Artalk.git
```
It is recommended to fork the repository first, and then clone the forked repository.
It's recommended to fork the repository first, and then clone the forked repository.
Enter the directory:
Navigate to the directory:
```sh
cd Artalk
```
### Build Backend
## Development Environment
First, you need to install the dependencies for the backend written in Go. Simply run the `make install` command to install the dependencies.
To develop Artalk, both frontend and backend, install the following tools:
Then, run the `make dev` to build and run `./bin/artalk`, and you can pass startup parameters to the program using `ARGS="version" make dev`.
- [Node.js](https://nodejs.org/en/) (>= 20.17.0)
- [PNPM](https://pnpm.io/) (>= 9.9.0)
- [Go](https://golang.org/) (>= 1.22)
- [Docker](https://www.docker.com/) (>= 20.10.0) (optional)
- [Docker Compose](https://docs.docker.com/compose/) (>= 1.29.0) (optional)
This will build the backend with debugging symbols. The binary file will be placed under the `./bin` directory.
## Development Workflow Overview
The backend program will run by default on port `23366`. You can access it through a browser at `http://localhost:23366`. It's recommended not to change this port number for testing the backend program.
The development workflow consists of the following steps:
### Build Frontend
1. **Set Up Complete Development Instance**:
First, you need to install the dependencies for the frontend. Simply run the `pnpm install` command to install the dependencies.
- Navigate to the Artalk Repo directory.
- Execute `make dev` to run the backend on port `23366`.
- Execute `pnpm dev` to run the frontend on port `5173`.
- Optionally, execute `pnpm dev:sidebar` to run the sidebar frontend on port `23367`.
Then, run the `pnpm dev` to build and run the frontend, and you can pass startup parameters to the program using `ARGS="--port 5173" pnpm dev`.
2. **Access Frontend for Development**:
The frontend program will run by default on port `5173`, and you can access it in a browser at `http://localhost:5173`. The frontend testing client will, by default, request the backend on port `23366`, so it's essential to keep the backend on this port.
- Open your browser and go to `http://localhost:5173` to perform your development and testing.
The frontend program is divided into the main program and a sidebar program, with the sidebar program running on a separate port, which is `23367`.
3. **Testing**:
### Development Workflow
- Run the backend unit tests using `make test`.
- Run the ui unit tests using `pnpm test`.
- Run the ui E2E tests using `make test-frontend-e2e`.
In most cases, to set up a complete development instance, you need to navigate to the Artalk Repo directory and then execute `make dev`. This will run the backend on port `23366`. Then, execute `pnpm dev`, which will run the frontend on port `5173`. You can optionally execute `pnpm dev:sidebar` to run the sidebar frontend on port `23367`. For frontend development, you need to access `http://localhost:5173` in your browser to perform your development and testing.
4. **Building Frontend Code**:
When you make changes to the frontend code, you can build the complete frontend program using `pnpm build:all`. The JavaScript and CSS code can be found in `ui/artalk/dist`.
- When you make changes to the frontend code, build the complete frontend program using `pnpm build:all`.
- The JavaScript and CSS code will be found in `ui/artalk/dist`.
- The frontend code is automatically deployed to NPM by GitHub Actions.
When you make changes to the backend code, running `make all` will build the complete backend program. Note that since the backend program also embeds the frontend code, the `scripts/build-frontend.sh` script will run during backend program building, which includes the embedded frontend main program and sidebar frontend program. If you are interested, you can explore the complete frontend build process in the `Makefile` code.
5. **Building Backend Code**:
Additionally, there is automated CI on GitHub for building. You can find the relevant code in the `.github/workflows` directory.
- When you make changes to the backend code, note that the backend program embeds the frontend code.
- Before building the backend, run `make build-frontend` (which runs `scripts/build-frontend.sh`). This will place the embedded frontend main program and sidebar frontend program in `/public`.
- Then, build the backend program using `make build`.
### Optional: Use a One-Key Script to Run a Demo Site
More exploration:
When you access `http://localhost:5173` during frontend development, you will get a minimalist interface that only contains the Artalk program interface and not a real blog environment. If you want to make testing closer to a real environment, you can create a demo blog site using the following steps.
- **Developing Artalk Plugins or Themes**:
Refer to the [Artalk Plugin Development Guide](https://artalk.js.org/develop/plugin.html).
Run the following command:
- **Makefile**:
You can explore the process and commands in the `Makefile`.
```sh
./scripts/setup-example-site.sh
```
- **Automated CI on GitHub**:
The automated CI pipeline on GitHub, located in the `.github/workflows` directory, builds the frontend, backend, and Docker images. It publishes Docker images to Docker Hub, handles npm package publishing, and creates GitHub Releases. And also testing the frontend and backend.
This script sets up a local example site for testing at `data` folder, with Artalk integrated into its theme.
After running this script, run:
```sh
./bin/artalk server -c ./data/artalk.yml
```
to start the artalk server.
And open <http://localhost:1313/> in your browser to view the example site.
Here is the default admin account (only created in test mode):
```yaml
name: "admin"
email: "admin@test.com"
password: "admin"
```
## Testing
The backend Go program can be tested by running `make test` for unit testing. The test results will be outputted in the terminal. You can also execute `test-coverage` to check the code test coverage.
Frontend testing is conducted using Playwright for end-to-end (E2E) testing. To start the E2E testing, run `make test-frontend-e2e`.
Both frontend and backend testing are automated and will be performed during Git pull requests and as part of the build process using CircleCI or GitHub Actions.
The following sections provide more detailed information on the development workflow.
## Project Structure
Artalk is a monorepo project, which means all the source code is in the same repository. However, the frontend and backend are separated. The frontend part is located in `./ui` directory.
Artalk is a monorepo project, meaning all the source code resides in a single repository. Despite this, the frontend and backend are kept separate. The frontend part is located in the `./ui` directory.
- `bin/` - The compiled binary files. This directory is ignored by git.
- `cmd/` - The source code for the command line tools.
- `conf/` - The sample configuration files.
- `docs/` - The documentation site source code.
- `i18n/` - The translation files.
- `internal/` - The internal packages.
- `data/` - The local data. This directory is ignored by git.
- `public/` - The static files. Built frontend files will be copied here.
- `scripts/` - The scripts for development.
- `server/` - The source code for the server.
- `ui/` - The source code for the frontend.
### Directory Overview
## Translation
- `bin/`: The compiled binary files. (This directory is ignored by git).
- `cmd/`: The source code for the command line tools.
- `conf/`: The sample configuration files.
- `data/`: The local data. (This directory is ignored by git).
- `docs/`: The documentation site source code.
- `i18n/`: The translation files.
- `local/`: The local files. (This directory is ignored by git).
- `internal/`: The Go source code for the internal packages.
- `public/`: The static files. Built frontend files will be copied here.
- `scripts/`: The scripts for development and building.
- `server/`: The Go source code for the backend.
- `ui/`: The UI source code for the frontend.
- `.github/`: The GitHub Actions workflows.
- `.vscode/`: The VSCode settings.
Artalk aims to be a multilingual project. If you would like to contribute to the translation, here are some tips:
## Backend Development
If you just write some new features or do some fixes/refactoring, use the following command to generate the translation template
### Run Backend
1. **Create Configuration File**:
- Copy `./conf/artalk.example.yml` to the root directory.
- Rename it to `artalk.yml`.
- Modify the file as needed.
2. **Start Backend Program**:
- Run `make dev` to start the backend on port `23366`.
- Access it via `http://localhost:23366`.
- It's recommended to keep the default port for testing.
- (Alternative) Use `ARGS="version" make dev` to pass startup parameters (default is `ARGS="server"`).
The `make dev` builds the backend with debugging symbols, which is convenient for debugging with GDB.
If you are using the VSCode, you can use the `F5` key (or RUN button) to start debugging the backend program directly.
### Build Backend
1. **Fetch Latest Git Tag**:
Execute `git fetch --tags` to get the latest git tag information. This tag will be used as the version number of the backend app. Alternatively, specify it using environment variables: `VERSION="v1.0.0"` and `COMMIT_HASH="66128e"`.
2. **Build Frontend**:
Run `make build-fronted` to build the frontend, as the backend app embeds the frontend code.
3. **Build Backend**:
Execute `make build` to build the backend program.
The built binary file will be located in the `./bin` directory.
## Frontend Development (UI)
### Run Frontend
1. **Install Dependencies**:
Run `pnpm install` to install all necessary dependencies.
2. **Start Development Server**:
Execute `pnpm dev --port 5173` to start the frontend development server.
3. **Access the Frontend**:
The frontend application will run on port `5173` by default. Access it in your browser at `http://localhost:5173`.
4. **Sidebar Development**:
To run the sidebar part of the frontend, use `pnpm dev:sidebar`.
The ports `5173` and `23367` are used for frontend development and testing. These ports are included in the `ATK_TRUSTED_DOMAINS` configuration of the backend program.
### Build Frontend
To build the frontend, run the following command:
```sh
go run ./internal/i18n/gen -w . -d .
make build-frontend
```
If you're not a programmer and would like to help us improve the translation, you can edit the translation files directly in the `.i18n' directory and then submit a pull request.
The compiled JavaScript and CSS files will be located in the `/public` directory, embedded into the backend program.
For more details, refer to the `scripts/build-frontend.sh` script.
## Docker Development
### Build Docker Image
To build the Docker image, run the following command:
```sh
docker build -t artalk:TAG .
```
Replace `TAG` with the desired tag name (e.g., `latest`).
### Skip Frontend Build
If you have already built the frontend outside the Docker container, you can skip the frontend build process inside the container to speed up the build. Use the following command:
```sh
docker build --build-arg SKIP_FRONTEND_BUILD=true -t artalk:latest .
```
For more details, refer to the `Dockerfile`.
## Testing
### Testing the Backend
To test the backend Go program, you can use the following commands:
- **Unit Testing**:
Run `make test` to execute unit tests. The results will be outputted in the terminal.
- **Test Coverage**:
Run `make test-coverage` to check the code test coverage.
- **HTML Coverage Report**:
Run `make test-coverage-html` to generate and browse the test coverage report in HTML format.
- **Run Specific Tests**:
To run specific tests, use the command with an environment variable:
```sh
TEST_PATHS="./server/..." make test
```
### Testing the Frontend
Frontend testing includes unit tests and end-to-end (E2E) tests.
- **Unit Testing**:
The unit tests for the frontend are conducted using Vitest. Run `pnpm test` to start the unit testing.
- **End-to-End Testing**:
E2E testing is conducted using Playwright. To start the E2E testing, run:
```sh
make test-frontend-e2e
```
### Continuous Integration for Testing
Both frontend and backend testing are automated and will be performed during Git pull requests and as part of the build process using CircleCI or GitHub Actions.
## Configurations
The template configuration files are located in the `/conf` directory, with templates annotated in multiple languages named in the format `artalk.example.[lang].yml` (e.g., `artalk.example.zh-CN.yml`). Artalk will parse these template configuration files to generate the settings interface, environment variable names, and documentation. To improve performance, some data will be cached during the program's runtime to eliminate parsing time.
In the `internal/config/config.go` file, there is a definition of the `Config` struct, which is used to parse the yml files into Go structs. This struct contains more precise type definitions. If you need to add, modify, or delete a configuration item, you must make changes to both the configuration file templates in `/conf` and the `Config` struct.
When you modify the configuration files, please run the following command to update the configuration data cache:
```sh
make update-conf
```
To update the environment variable documentation, you can run the command:
```sh
make update-conf-docs
```
## Documentations
The documentation consists of three parts, each associated with a specific package: **Guide documentation**, **Landing page**, and **Swagger API documentation**. Below is an organized summary of the relevant commands and their outputs for each package.
### Guide Documentation (`docs`)
- **Directory**: `docs/docs/guide`
- **Dev Command**: `pnpm -F docs dev:docs`
- **Build Command**: `pnpm -F docs build:docs`
- **Output Directory**: `docs/docs/.vitepress/dist`
### Landing Page (`docs-landing`)
- **Directory**: `docs/landing`
- **Dev Command**: `pnpm -F docs-landing dev:landing`
- **Build Command**: `pnpm -F docs-landing build:landing`
- **Output Directory**: `docs/landing/dist`
### Swagger API Documentation (`docs-swagger`)
- **Directory**: `docs/swagger`
- **Build Command**: `make update-swagger`
- **Output Directory**: `docs/swagger`
Swagger definitions are located in the backend code at `/server`. After modifying the Swagger definitions, running the build command will update the Swagger docs and generate HTTP client code at `/ui/artalk/src/api/v2.ts`.
### Combined Build
- **Command to Build All Packages**: `pnpm build:docs`
- **Combined Output Directory**: `docs/docs/.vitepress/dist`
This command builds and combines all three packages into a single directory, ready for publishing.
### Environment Variable Documentation
- **File**: `docs/docs/guide/env.md`
- **Command to Update**: `make update-conf-docs`
This command reads the configuration template file located in `/conf` to update the environment variable documentation. Run this command after modifying the configuration template file.
## Translation (i18n)
If you write new features or make fixes/refactoring, use the following command to incrementally generate the translation files by parsing the source code for `i18n.T` function calls:
```sh
make update-i18n
```
If you're not a programmer and would like to help improve the translation, you can edit the translation files directly in the `/i18n` directory and then submit a pull request.
## The End
Thank you for your patience in reading this and for your interest and support in Artalk. We understand that the success of an open-source project relies on the contributions of every developer. Whether through code, documentation, testing, or feedback, your participation is the driving force behind the project's continuous progress. We sincerely invite you to join us in improving and enhancing Artalk.
By collaborating, we can create a more robust and versatile platform that benefits the entire community. Your unique insights and expertise are invaluable, and together, we can achieve remarkable advancements. Whether you are a seasoned developer or just starting, there is always a place for your contributions in our project.
If you have any questions or need assistance, please feel free to ask in the issue section on our GitHub page: https://github.com/ArtalkJS/Artalk/issues. Thank you once again for your support, and we look forward to working with you.
+4 -4
View File
@@ -1,5 +1,5 @@
### build Artalk
FROM golang:1.21.5-alpine3.19 as builder
FROM golang:1.22.6-alpine3.20 AS builder
WORKDIR /source
@@ -22,7 +22,7 @@ ARG SKIP_UI_BUILD=false
RUN set -ex \
&& if [ "$SKIP_UI_BUILD" = "false" ]; then \
apk add --no-cache nodejs npm \
&& npm install -g pnpm@8.12.1 \
&& npm install -g pnpm@9.9.0 \
;fi
RUN set -ex \
@@ -40,13 +40,13 @@ RUN set -ex \
&& make build
### build final image
FROM alpine:3.19
FROM alpine:3.20
# we set the timezone `Asia/Shanghai` by default, you can be modified
# by `docker build --build-arg="TZ=Other_Timezone ..."`
ARG TZ="Asia/Shanghai"
ENV TZ ${TZ}
ENV TZ=${TZ}
COPY --from=builder /source/bin/artalk /artalk
+22 -13
View File
@@ -1,6 +1,6 @@
PKG_NAME := github.com/ArtalkJS/Artalk
BIN_NAME := ./bin/artalk
VERSION ?= $(shell git describe --tags --abbrev=0)
VERSION ?= $(shell git describe --tags --abbrev=0 --match 'v*')
COMMIT_HASH ?= $(shell git rev-parse --short HEAD)
HAS_RICHGO := $(shell which richgo)
@@ -12,6 +12,9 @@ all: install build
install:
go mod tidy
run: all
$(BIN_NAME) $(ARGS)
build:
go build \
-ldflags "-s -w -X $(PKG_NAME)/internal/config.Version=$(VERSION) \
@@ -22,9 +25,6 @@ build:
build-frontend:
./scripts/build-frontend.sh
run: all
$(BIN_NAME) $(ARGS)
build-debug:
@echo "Building Artalk $(VERSION) for debugging..."
@go build \
@@ -35,21 +35,32 @@ build-debug:
$(PKG_NAME)
dev: build-debug
ATK_SITE_DEFAULT="ArtalkDocs" \
ATK_TRUSTED_DOMAINS="http://localhost:5173 http://localhost:23367" \
$(BIN_NAME) $(ARGS)
test:
$(GOTEST) -timeout 20m ./internal/...
$(GOTEST) -timeout 20m $(or $(TEST_PATHS), ./...)
test-coverage:
$(GOTEST) -cover ./...
$(GOTEST) -cover $(or $(TEST_PATHS), ./...)
test-coverage-html:
$(GOTEST) -v -coverprofile=coverage.out ./...
$(GOTEST) -v -coverprofile=coverage.out $(or $(TEST_PATHS), ./...)
go tool cover -html=coverage.out
test-frontend-e2e:
./scripts/frontend-e2e-test.sh $(if $(REPORT), --show-report)
update-i18n:
go generate ./internal/i18n
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
update-swagger:
go install github.com/swaggo/swag/cmd/swag@latest
swag init -g server/server.go --output ./docs/swagger --requiredByDefault
@@ -61,9 +72,7 @@ docker-build:
docker-push:
./scripts/docker-build.sh --push
test-frontend-e2e:
./scripts/frontend-e2e-test.sh $(if $(REPORT), --show-report)
.PHONY: all install build build-frontend build-debug \
dev test test-coverage test-coverage-html update-i18n \
docker-build docker-push test-frontend-e2e;
.PHONY: all install run build build-frontend build-debug dev \
test test-coverage test-coverage-html test-frontend-e2e \
update-i18n update-conf update-conf-docs update-swagger \
docker-build docker-push;
+82 -91
View File
@@ -1,129 +1,120 @@
<p align="center">
<img src="https://user-images.githubusercontent.com/22412567/137740516-d9e97af0-fb3b-4dab-b331-671a9a2a3a63.png" alt="Artalk" width="100%">
<img src="https://user-images.githubusercontent.com/22412567/171680920-6e74b77c-c565-487b-bff1-4f94976ecbe7.png" alt="Artalk" width="100%">
</p>
# Artalk
[![npm 版本](https://img.shields.io/npm/v/artalk.svg?style=flat-square)](https://www.npmjs.com/package/artalk)
[![npm 下载量](https://img.shields.io/npm/dt/artalk.svg?style=flat-square)](https://www.npmjs.com/package/artalk)
[![尺寸](https://badgen.net/bundlephobia/minzip/artalk?style=flat-square)](https://bundlephobia.com/package/artalk)
[![CircleCI](https://circleci.com/gh/ArtalkJS/Artalk/tree/master.svg?style=svg)](https://circleci.com/gh/ArtalkJS/Artalk/tree/master)
[![npm version](https://img.shields.io/npm/v/artalk.svg?style=flat-square)](https://www.npmjs.com/package/artalk)
[![npm downloads](https://img.shields.io/npm/dt/artalk.svg?style=flat-square)](https://www.npmjs.com/package/artalk)
[![Docker Pulls](https://img.shields.io/docker/pulls/artalk/artalk-go?style=flat-square)](https://hub.docker.com/r/artalk/artalk-go)
[![Go Report Card](https://goreportcard.com/badge/github.com/ArtalkJS/Artalk?style=flat-square)](https://goreportcard.com/report/github.com/ArtalkJS/Artalk)
[![CircleCI](https://img.shields.io/circleci/build/gh/ArtalkJS/Artalk?style=flat-square)](https://circleci.com/gh/ArtalkJS/Artalk/tree/master)
[![Codecov](https://img.shields.io/codecov/c/gh/ArtalkJS/Artalk?style=flat-square)](https://codecov.io/gh/ArtalkJS/Artalk)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/artalk?style=flat-square)](https://bundlephobia.com/package/artalk)
> 🌌 A self-hosted comment system
[中文](./README.md) • [Official Website](https://artalk.js.org) • [Latest Release](https://github.com/ArtalkJS/Artalk/releases) • [Changelog](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md)
[简体中文](./README.md) / [Documentation](https://artalk.js.org) / [Releases](https://github.com/ArtalkJS/Artalk/releases) / [Artalk](https://github.com/ArtalkJS/Artalk)
🌌 Artalk is a simple yet feature-rich commenting system that you can deploy out of the box and integrate into any blog, website, or web application.
---
- 🍃 Lightweight (~30kB)
- 👨‍👧‍👦 Secure (Self-hosted)
- 🐳 Easy to use (Very Easy)
- 🍱 Golang backend (Fast and Cross Platform)
- 🌊 TypeScript × Vanilla × Vite (No Dependencies)
- 🍃 Frontend ~40KB, pure Vanilla JS
- 🍱 Backend Golang, efficient lightweight cross-platform
- 🐳 One-click deployment via Docker, convenient and fast
- 🌈 Open-source program, self-hosted, privacy-first
## Features
- Sidebar: Multi-site centralized management
- Notification Center: Red badge alert / Mark as read
- Verification: User Verification Badge / Password access
- Moderation: Anti-spam detection / Captcha frequency limit
- Emoticons: Insert emoji / Quickly import presets
- Email Notify: Template customization / Send to multi-admin
- Site Isolation: Multi-site management / Admin assignment
- Page Management: Provide page title / Easy to look up
- Image Upload: Upload to localhost / various remote image host
- Private Space Mode: Only visible to yourself / Message board
- Multiple Msg Pushers: Support Telegram / Slack / LINE
- Nested Comments: Switchable to Flat Mode
- Comment Vote: For or against comments
- Comment Sort: Sort by popularity or time
- Comment PIN: Pin important comments
- Track only author: Show only author's comments
- Asynchronous: Send comments without waiting
- Infinite Scrolling: Provide various comment content pagination custom
- AutoSave: A anti-lost editor
- AutoFill: Autofill user profile
- Preview: Real-time preview of markdown
- Dark Mode: Prevents eye disease damage
- Collapse Comment: I do not want you to see this comment
- Data Backup: Prevent comment data loss
- Data Migration: Switch back and forth between different commenting systems
- Multiple comments on one page: Multiple comment areas on one page (seems useless
- Markdown: Markdown syntax was supported by default
- LaTex support: Import KaTex plugin to integrate LaTex parser for artalk
- Using [Vite](https://github.com/vitejs/vite): The ultimate developer experience
<!-- prettier-ignore-start -->
## Getting Started
<!-- features -->
* [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
* [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
* [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
* [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 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
* [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
<!-- /features -->
Reference to:[**Documentation**](https://artalk.js.org/guide/deploy.html)
<!-- prettier-ignore-end -->
```sh
$ pnpm add artalk
## Installation
Deploy via Docker with one click:
```bash
docker run -d \
--name artalk \
-p 8080:23366 \
-v $(pwd)/data:/data \
-e "TZ=America/New_York" \
-e "ATK_LOCALE=en" \
-e "ATK_SITE_DEFAULT=Artalk Blog" \
-e "ATK_SITE_URL=https://example.com" \
artalk/artalk-go
```
```ts
import Artalk from 'artalk'
Integrate Artalk into your webpage:
<!-- prettier-ignore-start -->
```ts
Artalk.init({
el: '#Comments',
pageKey: 'http://your_domain/post/1', // Page Link
pageTitle: 'The title of your page', // Page Title
server: 'http://localhost:8080/api', // Server URL
site: 'Site Name',
locale: 'en'
el: '#Comments',
site: 'Artalk Blog',
server: 'https://artalk.example.com',
pageKey: '/2018/10/02/hello-world.html'
})
```
### Docker
<!-- prettier-ignore-end -->
```sh
docker run -d \
--name artalk \
-p 8080:23366 \
-v $(pwd)/data:/data \
artalk/artalk-go
```
[**Learn More →**](https://artalk.js.org/guide/deploy.html)
### Docker Compose
## For Developers
```sh
mkdir Artalk
cd Artalk
Pull requests are welcome!
vim docker-compose.yaml
```
```yaml
version: "3.5"
services:
artalk:
container_name: artalk
image: artalk/artalk-go
ports:
- 8080:23366
volumes:
- ./data:/data
```
```sh
docker-compose up -d
```
## Development
see [CONTRIBUTING.md](./CONTRIBUTING.md)
See [Development](https://artalk.js.org/develop/) and [Contributing](./CONTRIBUTING.md) for information on working with the codebase, getting a local development setup, and contributing changes.
## Contributors
Your contributions enrich the open-source community, fostering learning, inspiration, and innovation. We deeply value your involvement. Thank you for being a vital part of our community! 🥰
[![](https://contrib.rocks/image?repo=ArtalkJS/Artalk)](https://github.com/ArtalkJS/Artalk/graphs/contributors)
## Supporters
[![Stargazers repo roster for @ArtalkJS/Artalk](https://reporoster.com/stars/ArtalkJS/Artalk)](https://github.com/ArtalkJS/Artalk/stargazers)
## Feedback
## Repobeats Analytics
Thanks for the help and feedback provided by the community, if you have good suggestions or comments, please go to [issues](https://github.com/ArtalkJS/Artalk/issues) to let us know at any time.
![Alt](https://repobeats.axiom.co/api/embed/a9fc9191ac561bc5a8ee2cddc81e635ecaebafb6.svg 'Repobeats analytics image')
## Stargazers over time
+66 -174
View File
@@ -12,62 +12,78 @@
[![Codecov](https://img.shields.io/codecov/c/gh/ArtalkJS/Artalk?style=flat-square)](https://codecov.io/gh/ArtalkJS/Artalk)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/artalk?style=flat-square)](https://bundlephobia.com/package/artalk)
> 🌌 Golang 自托管评论系统
[English](./README.en.md) • [官方网站](https://artalk.js.org) • [最新版本](https://github.com/ArtalkJS/Artalk/releases) • [更新日志](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md)
[English](./README.en.md) / [官方文档](https://artalk.js.org) / [最新版本](https://github.com/ArtalkJS/Artalk/releases)
Artalk 是一款简单易用但功能丰富的评论系统,你可以开箱即用地部署并置入任何博客、网站、Web 应用。
---
- 🍃 轻量 (~30kB)
- 👨‍👧‍👦 安全 (自托管)
- 🐳 易上手 (防脱发)
- 🍱 Golang 后端 (快速 / 跨平台)
- 🌊 Vanilla × TypeScript × Vite (纯天然 / 无依赖)
- 🍃 前端 ~40KB,纯天然 Vanilla JS
- 🍱 后端 Golang,高效轻量跨平台
- 🐳 通过 Docker 一键部署,方便快捷
- 🌈 开源程序,自托管,隐私至上
## 特性
- 侧 边 栏 :支持多站点集中化管理
- 通知中心:红点的标记 / 提及列表
- 身份验证:徽标自定义 / 密码验证
- 评论审核:反垃圾检测 / 频率限制
- 表情符号:插入表情包 / 快速导入
- 邮件提醒:模版自定义 / 多管理员
- 站点隔离:管理员分配 / 多个站点
- 页面管理:标题可显示 / 快速跳转
- 图片上传:上传到本地 / 多种图床
- 多元推送:支持 钉钉 飞书 TG
- 无限层级:可切换为平铺模式
- 评论投票:赞同还是反对评论
- 评论排序:按热度或时间排序
- 评论置顶:重要消息置顶显示
- 只看作者:仅显示作者的评论
- 说说模式:仅自己可发布评论
- 异步处理:发送评论无需等待
- 滚动加载:评论内容分页处置
- 自动保存:用户输入防丢功能
- 自动填充:用户链接自动填充
- 实时预览:评论内容实时预览
- 夜间模式:防止眼部疾病伤害
- 评论折叠:这个不打算给你康
- 数据备份:防止评论数据丢失
- 数据迁移:快速切换评论系统
- Markdown:默认支持 MD 语法
- 支持 Latex:提供集成 Katex 插件
- 使用 [Vite](https://github.com/vitejs/vite):属于开发者的极致体验
<!-- prettier-ignore-start -->
更多内容请查看:[**介绍文档**](https://artalk.js.org/guide/intro.html)
<!-- features -->
* [侧边栏](https://artalk.js.org/guide/frontend/sidebar.html): 快速管理、直观浏览
* [社交登录](https://artalk.js.org/guide/frontend/auth.html): 通过社交账号快速登录
* [邮件通知](https://artalk.js.org/guide/backend/email.html): 多种发送方式、邮件模板
* [多元推送](https://artalk.js.org/guide/backend/admin_notify.html): 多种推送方式、通知模版
* [站内通知](https://artalk.js.org/guide/frontend/sidebar.html): 红点标记、提及列表
* [验证码](https://artalk.js.org/guide/backend/captcha.html): 多种验证类型、频率限制
* [评论审核](https://artalk.js.org/guide/backend/moderator.html): 内容检测、垃圾拦截
* [图片上传](https://artalk.js.org/guide/backend/img-upload.html): 自定义上传、支持图床
* [Markdown](https://artalk.js.org/guide/intro.html): 支持 Markdown 语法
* [表情包](https://artalk.js.org/guide/frontend/emoticons.html): 兼容 OwO,快速集成
* [多站点](https://artalk.js.org/guide/backend/multi-site.html): 站点隔离、集中管理
* [管理员](https://artalk.js.org/guide/backend/multi-site.html): 密码验证、徽章标识
* [页面管理](https://artalk.js.org/guide/frontend/sidebar.html): 快速查看、标题一键跳转
* [浏览量统计](https://artalk.js.org/guide/frontend/pv.html): 轻松统计网页浏览量
* [层级结构](https://artalk.js.org/guide/frontend/config.html#nestmax): 嵌套分页列表、滚动加载
* [评论投票](https://artalk.js.org/guide/frontend/config.html#vote): 赞同或反对评论
* [评论排序](https://artalk.js.org/guide/frontend/config.html#listsort): 多种排序方式,自由选择
* [评论搜索](https://artalk.js.org/guide/frontend/sidebar.html): 快速搜索评论内容
* [评论置顶](https://artalk.js.org/guide/frontend/sidebar.html): 重要消息置顶显示
* [仅看作者](https://artalk.js.org/guide/frontend/config.html): 仅显示作者的评论
* [评论跳转](https://artalk.js.org/guide/intro.html): 快速跳转到引用的评论
* [自动保存](https://artalk.js.org/guide/frontend/config.html): 输入内容防丢功能
* [IP 属地](https://artalk.js.org/guide/frontend/ip-region.html): 用户 IP 属地展示
* [数据迁移](https://artalk.js.org/guide/transfer.html): 自由迁移、快速备份
* [图片灯箱](https://artalk.js.org/guide/frontend/lightbox.html): 图片灯箱快速集成
* [图片懒加载](https://artalk.js.org/guide/frontend/img-lazy-load.html): 延迟加载图片,优化体验
* [Latex](https://artalk.js.org/guide/frontend/latex.html): Latex 公式解析集成
* [夜间模式](https://artalk.js.org/guide/frontend/config.html#darkmode): 夜间模式切换
* [扩展插件](https://artalk.js.org/develop/): 创造更多可能性
* [多语言](https://artalk.js.org/guide/frontend/i18n.html): 多国语言切换
* [命令行](https://artalk.js.org/guide/backend/config.html): 命令行操作管理能力
* [API 文档](https://artalk.js.org/develop/): 提供 OpenAPI 格式文档
* [程序升级](https://artalk.js.org/guide/backend/update.html): 版本检测,一键升级
<!-- /features -->
<!-- prettier-ignore-end -->
## 安装
参考:[**部署文档**](https://artalk.js.org/guide/deploy.html)
通过 Docker 一键部署:
```bash
npm install artalk
docker run -d \
--name artalk \
-p 8080:23366 \
-v $(pwd)/data:/data \
-e "TZ=Asia/Shanghai" \
-e "ATK_LOCALE=zh-CN" \
-e "ATK_SITE_DEFAULT=Artalk 的博客" \
-e "ATK_SITE_URL=https://example.com" \
artalk/artalk-go
```
```ts
import Artalk from 'artalk'
在网页中引入 Artalk:
<!-- prettier-ignore-start -->
```ts
Artalk.init({
el: '#Comments',
site: 'Artalk 的博客',
@@ -76,46 +92,20 @@ Artalk.init({
})
```
### Docker
<!-- prettier-ignore-end -->
```bash
docker run -d \
--name artalk \
-p 8080:23366 \
-v $(pwd)/data:/data \
--restart=always \
artalk/artalk-go
```
[**了解更多 →**](https://artalk.js.org/guide/deploy.html)
### Docker Compose
## For Developers
```bash
vim docker-compose.yaml
```
Pull requests are welcome!
```yaml
version: "3.5"
services:
artalk:
container_name: artalk
image: artalk/artalk-go
restart: always
ports:
- 8080:23366
volumes:
- ./data:/data
```
```bash
docker-compose up -d
```
## Development
see [CONTRIBUTING.md](./CONTRIBUTING.md)
See [Development](https://artalk.js.org/develop/) and [Contributing](./CONTRIBUTING.md) for information on working with the codebase, getting a local development setup, and contributing changes.
## Contributors
Your contributions enrich the open-source community, fostering learning, inspiration, and innovation. We deeply value your involvement. Thank you for being a vital part of our community! 🥰
[![](https://contrib.rocks/image?repo=ArtalkJS/Artalk)](https://github.com/ArtalkJS/Artalk/graphs/contributors)
## Supporters
@@ -124,105 +114,7 @@ see [CONTRIBUTING.md](./CONTRIBUTING.md)
## Repobeats Analytics
![Alt](https://repobeats.axiom.co/api/embed/a9fc9191ac561bc5a8ee2cddc81e635ecaebafb6.svg "Repobeats analytics image")
## 特别致谢
感谢社区提供的帮助与反馈,若有好的建议与意见欢迎前往 [ISSUES](https://github.com/ArtalkJS/Artalk/issues) 随时告知。
## TODOs
- [x] Golang 后端
- [x] 多数据库支持
- [x] SQLite
- [x] MySQL
- [x] Postgres
- [x] SQLServer
- [x] 多缓存数据库支持
- [x] In-memory (内建缓存)
- [x] Redis
- [x] Memcache
- [x] 多站点支持
- [x] 评论获取分页
- [x] 评论点赞投票
- [x] 浏览量统计
- [x] 评论分页加载
- [x] 评论置顶 / 精华
- [x] 评论排序 (热度 / 时间)
- [x] 通知中心
- [x] 提及
- [x] 全部
- [x] 我的
- [x] 待审
- [x] 管理员控制台
- [x] 评论
- [x] 页面
- [x] 站点
- [x] 用户
- [x] 设置 (GUI)
- [x] 数据导入 ([Artransfer](https://artalk.js.org/guide/transfer.html))
- [x] Artrans
- [x] WordPress
- [x] Typecho ([插件](https://github.com/ArtalkJS/Artrans-Typecho) / [Artransfer-CLI](https://github.com/ArtalkJS/Artransfer-CLI))
- [x] Valine
- [x] Disqus
- [x] Commento
- [x] Waline ([Artransfer-CLI](https://github.com/ArtalkJS/Artransfer-CLI))
- [x] Twikoo
- [x] Artalk v1 (PHP)
- [x] 数据导出
- [x] 邮件多种发送方式
- [x] SMTP
- [x] 阿里云邮件
- [x] 系统调用 sendmail
- [x] 邮件多模板自定义
- [x] 邮件异步队列发送
- [ ] 队列持久化
- [x] 用户已读标记
- [x] 验证码
- [x] 图片验证码
- [x] [Turnstile](https://www.cloudflare.com/products/turnstile/)
- [x] [ReCAPTCHA](https://www.google.com/recaptcha/about/)
- [x] [hCaptcha](https://www.hcaptcha.com/)
- [x] [极验](https://www.geetest.com/)滑动验证码
- [x] 反垃圾
- [x] [Akismet](https://akismet.com/)
- [x] [阿里云内容安全](https://help.aliyun.com/document_detail/28417.html)
- [x] [腾讯云内容安全](https://cloud.tencent.com/document/product/1124/64508)
- [x] 关键字过滤
- [x] 评论通知管理员 ([notify](https://github.com/nikoksr/notify))
- [x] Telegram Bot
- [x] 飞书 WebHook Bot
- [x] 钉钉
- [x] Bark
- [x] Slack
- [x] LINE
- [x] 自定义 HTTP 回调
- [ ] 命令行管理
- [ ] 博客邮件订阅
- [x] 用户鉴权机制
- [x] 跨域非法请求阻止
- [x] 全局验证码操作次数限制
- [x] JWT 登录状态验证
- [x] 时区自定义
- [x] 只看作者功能
- [x] 图片上传
- [x] 图片上传到图床 ([upgit](https://github.com/pluveto/upgit))
- [ ] 图片管理
- [ ] 附件上传 / 管理
- [ ] 表情包统一管理
- [ ] 导入表情包
- [ ] 表情包图片地址控制
- [ ] AT 提及 (@)
- [ ] 评论话题 (#)
- [ ] 评论标签分类系统
- [ ] 主题样式更换
- [ ] 规范化 API
- [ ] 扩展中心
- [ ] 开放用户注册
- [ ] 第三方登录接入
- [x] 多语言 / 国际化 (i18n)
- [x] 一键升级
![Alt](https://repobeats.axiom.co/api/embed/a9fc9191ac561bc5a8ee2cddc81e635ecaebafb6.svg 'Repobeats analytics image')
## Stargazers over time
+3
View File
@@ -0,0 +1,3 @@
# Reporting Security Issues
The features of Artalk are continuously being improved, and we are also striving to enhance security. However, potential issues may still exist. If you discover any security vulnerabilities in Artalk, please promptly contact us via [GitHub Issues](https://github.com/ArtalkJS/Artalk/issues) or email at artalkjs@gmail.com. We will make every effort to address the issue as quickly as possible. Thank you for your support!
+30 -9
View File
@@ -1,6 +1,7 @@
package cmd
import (
"encoding/json"
"errors"
"os"
@@ -16,24 +17,44 @@ func NewImportCommand(app *ArtalkCmd) *cobra.Command {
Aliases: []string{},
Short: "Artransfer import",
Long: "\n# Artransfer - Import\n\n See the documentation to learn more: https://artalk.js.org/guide/transfer.html",
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
parcelFile := args[0]
if _, err := os.Stat(parcelFile); errors.Is(err, os.ErrNotExist) {
log.Fatal(i18n.T("{{name}} not found", map[string]interface{}{"name": i18n.T("File")}))
// Prepare params
params := &artransfer.ImportParams{}
// Parse JSON parameters from flags
if jsonParams, _ := cmd.Flags().GetString("parameters"); jsonParams != "" {
if err := json.Unmarshal([]byte(jsonParams), params); err != nil {
log.Fatal("Failed to parse JSON parameters: ", err)
}
}
payload := args[1:]
payload = append(payload, "json_file:"+parcelFile)
// If JSON file or JSON data is not provided in flags, try to get it from arguments
if params.JsonFile == "" && params.JsonData == "" {
if len(args) == 0 {
log.Fatal(i18n.T("{{name}} is required", map[string]interface{}{"name": "FILENAME"}))
}
params.JsonFile = args[0]
}
// import Artrans
params := artransfer.ArrToImportParams(payload)
params.Assumeyes, _ = cmd.Flags().GetBool("assumeyes")
// Parse flags to params
if flagAssumeyes, err := cmd.Flags().GetBool("assumeyes"); err == nil {
params.Assumeyes = flagAssumeyes
}
// Check if file exists if JsonFile is provided
if params.JsonFile != "" {
if _, err := os.Stat(params.JsonFile); errors.Is(err, os.ErrNotExist) {
log.Fatal(i18n.T("{{name}} not found", map[string]interface{}{"name": i18n.T("File")}))
}
}
// Run import
artransfer.RunImportArtrans(app.Dao(), params)
},
}
flagPV(importCmd, "assumeyes", "y", false, "Automatically answer yes for all questions.")
flagPV(importCmd, "parameters", "p", "", "JSON format parameters for the import command.")
return importCmd
}
+2 -2
View File
@@ -32,7 +32,7 @@ func NewUpgradeCommand() *cobra.Command {
if !ignoreVersionCheck {
v := semver.MustParse(strings.TrimPrefix(config.Version, "v"))
if !found || latest.Version.LTE(v) {
log.Println(i18n.T("Current version is the latest") + " (v" + v.String() + ")")
log.Info(i18n.T("Current version is the latest") + " (v" + v.String() + ")")
return
}
}
@@ -49,7 +49,7 @@ func NewUpgradeCommand() *cobra.Command {
log.Fatal(i18n.T("Update failed")+" ", err)
}
log.Println(i18n.T("Update complete"))
log.Info(i18n.T("Update complete"))
fmt.Printf("\n"+
"-------------------------------\n"+
" v%s Release Note\n"+
+2
View File
@@ -0,0 +1,2 @@
ignore:
- "docs/*"
+114 -33
View File
@@ -2,33 +2,37 @@ host: "0.0.0.0"
port: 23366
app_key: ""
debug: false
locale: "en"
timezone: "Asia/Shanghai"
site_default: "Default Site"
locale: en
timezone: Asia/Shanghai
site_default: Default Site
site_url: ""
login_timeout: 259200
db:
type: "sqlite"
file: "./data/artalk.db"
type: sqlite
file: ./data/artalk.db
table_prefix: ""
name: "artalk"
host: "localhost"
name: artalk
host: localhost
port: 3306
user: "root"
user: root
password: ""
charset: "utf8mb4"
charset: utf8mb4
ssl: false
prepare_stmt: true
http:
body_limit: 100
proxy_header: ""
log:
enabled: true
filename: "./data/artalk.log"
filename: ./data/artalk.log
cache:
enabled: false
type: "builtin"
type: builtin
expires: 30
warm_up: false
server: ""
redis:
network: "tcp"
network: tcp
username: ""
password: ""
db: 0
@@ -45,23 +49,23 @@ moderator:
enabled: false
secret_id: ""
secret_key: ""
region: "ap-guangzhou"
region: ap-guangzhou
aliyun:
enabled: false
access_key_id: ""
access_key_secret: ""
region: "cn-shanghai"
region: cn-shanghai
keywords:
enabled: false
pending: false
files:
- "./data/keywords_1.txt"
- ./data/keywords_1.txt
file_sep: "\n"
replac_to: "x"
replace_to: x
captcha:
enabled: true
always: false
captcha_type: "image"
captcha_type: image
action_limit: 3
action_reset: 60
turnstile:
@@ -78,31 +82,31 @@ captcha:
captcha_key: ""
img_upload:
enabled: true
path: "./data/artalk-img/"
path: ./data/artalk-img/
max_size: 5
public_path: null
upgit:
enabled: false
exec: "./upgit -c UPGIT_CONF_FILE_PATH -t /artalk-img"
exec: upgit -c UPGIT_CONF_FILE_PATH -t /artalk-img
del_local: true
email:
enabled: false
send_type: "smtp"
send_type: smtp
send_name: "{{reply_nick}}"
send_addr: "noreply@example.com"
send_addr: noreply@example.com
mail_subject: "[{{site_name}}] You got a reply from @{{reply_nick}}"
mail_tpl: "default"
mail_tpl: default
smtp:
host: "smtp.qq.com"
host: smtp.qq.com
port: 587
username: "example@qq.com"
username: example@qq.com
password: ""
ali_dm:
access_key_id: ""
access_key_secret: ""
account_name: "noreply@example.com"
account_name: noreply@example.com
admin_notify:
notify_tpl: "default"
notify_tpl: default
notify_pending: false
noise_mode: false
email:
@@ -116,10 +120,11 @@ admin_notify:
- 7777777
bark:
enabled: false
server: "http://day.app/xxxxxxx/"
server: http://day.app/xxxxxxx/
lark:
enabled: false
webhook_url: ""
msg_type: "text"
webhook:
enabled: false
url: ""
@@ -139,25 +144,100 @@ admin_notify:
receivers:
- "USER_ID_1"
- "GROUP_ID_1"
auth:
enabled: false
anonymous: false
callback: "http://localhost:23366/api/v2/auth/{provider}/callback"
email:
enabled: true
verify_subject: "Your Code - {{code}}"
verify_tpl: default
github:
enabled: false
client_id: ""
client_secret: ""
gitlab:
enabled: false
client_id: ""
client_secret: ""
gitea:
enabled: false
client_id: ""
client_secret: ""
google:
enabled: false
client_id: ""
client_secret: ""
mastodon:
enabled: false
client_id: ""
client_secret: ""
twitter:
enabled: false
client_id: ""
client_secret: ""
facebook:
enabled: false
client_id: ""
client_secret: ""
discord:
enabled: false
client_id: ""
client_secret: ""
steam:
enabled: false
api_key: ""
apple:
enabled: false
client_id: ""
client_secret: ""
microsoft:
enabled: false
client_id: ""
client_secret: ""
wechat:
enabled: false
client_id: ""
client_secret: ""
tiktok:
enabled: false
client_id: ""
client_secret: ""
slack:
enabled: false
client_id: ""
client_secret: ""
line:
enabled: false
client_id: ""
client_secret: ""
patreon:
enabled: false
client_id: ""
client_secret: ""
auth0:
enabled: false
client_id: ""
client_secret: ""
domain: ""
frontend:
placeholder: ""
noComment: ""
sendBtn: ""
editorTravel: true
emoticons: "https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json"
emoticons: https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json
vote: true
voteDown: false
uaBadge: false
listSort: true
pvEl: "#ArtalkPV"
countEl: "#ArtalkCount"
preview: true
flatMode: "auto"
flatMode: auto
darkMode: inherit
nestMax: 2
nestSort: DATE_ASC
gravatar:
mirror: "https://www.gravatar.com/avatar/"
params: "d=mp&s=240"
mirror: https://www.gravatar.com/avatar/
params: sha256=1&d=mp&s=240
pagination:
pageSize: 20
readMore: true
@@ -166,6 +246,7 @@ frontend:
content: 300
children: 400
scrollable: false
imgLazyLoad: false
reqTimeout: 15000
versionCheck: true
pluginURLs: []
+154 -38
View File
@@ -10,16 +10,19 @@ app_key: ""
# Debug mode
debug: false
# Language (follow Unicode BCP 47) ["en", "zh-CN", "zh-TW", "jp"]
# Language (follow Unicode BCP 47) ["en", "zh-CN", "zh-TW", "ja", "fr", "ko", "ru"]
# -- see https://www.techonthenet.com/js/language_tags.php --
locale: "en"
locale: en
# Timezone (follow IANA Time Zone Database)
# -- see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones --
timezone: "Asia/Shanghai"
timezone: Asia/Shanghai
# Default site name (create when app is first launched)
site_default: "Default Site"
site_default: Default Site
# Default site url
site_url: ""
# Login timeout (in seconds)
login_timeout: 259200
@@ -27,42 +30,49 @@ login_timeout: 259200
# Database
db:
# Database type ["sqlite", "mysql", "pgsql", "mssql"]
type: "sqlite"
type: sqlite
# Database file (only for SQLite)
file: "./data/artalk.db"
file: ./data/artalk.db
# Table prefix (e.g. "atk_")
table_prefix: ""
# -- The following is not necessary for SQLite --
# Database name
name: "artalk"
name: artalk
# Host address
host: "localhost"
host: localhost
# Host port
port: 3306
# Database user
user: "root"
user: root
# Database password
password: ""
# Database charset
charset: "utf8mb4"
charset: utf8mb4
# Enable SSL mode
ssl: false
# Prepared Statement
prepare_stmt: true
# Web server
http:
# Body size limit (unit: MB)
body_limit: 100
# Proxy Header (fill `X-Forwarded-For` to get user real IP if behind a trusted reverse proxy or CDN)
proxy_header: ""
# Logging
log:
# Enable logging
enabled: true
# Log file path
filename: "./data/artalk.log"
filename: ./data/artalk.log
# Cache
cache:
# Enable cache
enabled: false
# Cache type ["redis", "memcache", "builtin"]
type: "builtin"
type: builtin
# Cache expiration time (in minutes)
expires: 30
# Cache warm up (warm up cache when program starts)
@@ -73,7 +83,7 @@ cache:
# Redis config
redis:
# Connection type ["tcp", "unix"]
network: "tcp"
network: tcp
# Redis username
username: ""
# Redis password
@@ -113,7 +123,7 @@ moderator:
enabled: false
secret_id: ""
secret_key: ""
region: "ap-guangzhou"
region: ap-guangzhou
# Aliyun Content Security
# (Auto review comments with Aliyun Content Security)
# -- see https://help.aliyun.com/document_detail/28417.html --
@@ -121,7 +131,7 @@ moderator:
enabled: false
access_key_id: ""
access_key_secret: ""
region: "cn-shanghai"
region: cn-shanghai
# Keyword filter (local offline dictionary)
keywords:
# Enable keyword filter
@@ -130,9 +140,9 @@ moderator:
pending: false
# Dictionary file (support multiple dictionary files)
files:
- "./data/keywords_1.txt"
- ./data/keywords_1.txt
file_sep: "\n"
replac_to: "x"
replace_to: x
# Captcha
captcha:
@@ -141,7 +151,7 @@ captcha:
# Captcha is required always
always: false
# Captcha type ["image", "turnstile", "recaptcha", "hcaptcha", "geetest"]
captcha_type: "image"
captcha_type: image
# Action limit
# (the number of actions required to activate captcha)
action_limit: 3
@@ -171,7 +181,7 @@ img_upload:
# Enable image upload
enabled: true
# Image storage
path: "./data/artalk-img/"
path: ./data/artalk-img/
# Image size limit (unit: MB)
max_size: 5
# Image link base path (default: "/static/images/")
@@ -181,7 +191,7 @@ img_upload:
# Enable Upgit
enabled: false
# Command line arguments
exec: "./upgit -c UPGIT_CONF_FILE_PATH -t /artalk-img"
exec: upgit -c UPGIT_CONF_FILE_PATH -t /artalk-img
# Delete local image after upload success
del_local: true
@@ -190,23 +200,23 @@ email:
# Enable email notification
enabled: false
# Send method ["smtp", "ali_dm", "sendmail"]
send_type: "smtp"
send_type: smtp
# Nick name of sender
send_name: "{{reply_nick}}"
# Email address of sender
send_addr: "noreply@example.com"
send_addr: noreply@example.com
# Email subject
mail_subject: "[{{site_name}}] You got a reply from @{{reply_nick}}"
# Email template file (set to file path to use custom template)
mail_tpl: "default"
mail_tpl: default
# SMTP send (set send method to "smtp" to enable)
smtp:
# Email address of sender
host: "smtp.qq.com"
host: smtp.qq.com
# Email port
port: 587
# Email address of sender
username: "example@qq.com"
username: example@qq.com
# Password
password: ""
# Aliyun mail push
@@ -214,12 +224,12 @@ email:
ali_dm:
access_key_id: ""
access_key_secret: ""
account_name: "noreply@example.com"
account_name: noreply@example.com
# Multi-Push
admin_notify:
# Notification template (set to file path to use custom template)
notify_tpl: "default"
notify_tpl: default
# Pending comment still send notification (notifications are still sent when comments are intercepted)
notify_pending: false
# Noise mode
@@ -244,14 +254,18 @@ admin_notify:
# Bark
bark:
enabled: false
server: "http://day.app/xxxxxxx/"
server: http://day.app/xxxxxxx/
# Lark
lark:
enabled: false
webhook_url: ""
# Message type ["text", "card"]
msg_type: "text"
# WebHook
webhook:
enabled: false
url: ""
# DingTalk
ding_talk:
enabled: false
token: ""
@@ -268,8 +282,110 @@ admin_notify:
channel_secret: ""
channel_access_token: ""
receivers:
- "USER_ID_1"
- "GROUP_ID_1"
- USER_ID_1
- GROUP_ID_1
# Social Login
auth:
# Enable Social Login
enabled: false
# Allow anonymous commenting (Allow skipping verification, only fill in an anonymous nickname and email)
anonymous: false
# Callback URL (https://example.com/api/v2/auth/{provider}/callback)
callback: "http://localhost:23366/api/v2/auth/{provider}/callback"
# Email
email:
# Enable email password login
enabled: true
# Verification email subject
verify_subject: "Your Code - {{code}}"
# Verification email template (set to file path to use custom template)
verify_tpl: default
# GitHub
github:
enabled: false
client_id: ""
client_secret: ""
# GitLab
gitlab:
enabled: false
client_id: ""
client_secret: ""
# Gitea
gitea:
enabled: false
client_id: ""
client_secret: ""
# Google
google:
enabled: false
client_id: ""
client_secret: ""
# Mastodon
mastodon:
enabled: false
client_id: ""
client_secret: ""
# Twitter
twitter:
enabled: false
client_id: ""
client_secret: ""
# Facebook
facebook:
enabled: false
client_id: ""
client_secret: ""
# Discord
discord:
enabled: false
client_id: ""
client_secret: ""
# Steam
steam:
enabled: false
api_key: ""
# Apple
apple:
enabled: false
client_id: ""
client_secret: ""
# Microsoft
microsoft:
enabled: false
client_id: ""
client_secret: ""
# WeChat
wechat:
enabled: false
client_id: ""
client_secret: ""
# Tiktok
tiktok:
enabled: false
client_id: ""
client_secret: ""
# Slack
slack:
enabled: false
client_id: ""
client_secret: ""
# Line
line:
enabled: false
client_id: ""
client_secret: ""
# Patreon
patreon:
enabled: false
client_id: ""
client_secret: ""
# Auth0
auth0:
enabled: false
client_id: ""
client_secret: ""
domain: ""
# UI Settings
frontend:
@@ -282,7 +398,7 @@ frontend:
# Movable comment box
editorTravel: true
# Emoticons
emoticons: "https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json"
emoticons: https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json
# Vote button
vote: true
# Dislike button
@@ -291,14 +407,12 @@ frontend:
uaBadge: false
# Comment sorting
listSort: true
# Page PV binding element
pvEl: "#ArtalkPV"
# Comment count binding element
countEl: "#ArtalkCount"
# Editor real-time preview
preview: true
# Flatten mode ["auto", true, false]
flatMode: "auto"
flatMode: auto
# Dark mode ["inherit", "auto"]
darkMode: inherit
# Maximum nesting level
nestMax: 2
# Nesting comment sorting rules ["DATE_ASC", "DATE_DESC", "VOTE_UP_DESC"]
@@ -306,9 +420,9 @@ frontend:
# Gravatar
gravatar:
# API URL
mirror: "https://www.gravatar.com/avatar/"
mirror: https://www.gravatar.com/avatar/
# API parameters
params: "d=mp&s=240"
params: sha256=1&d=mp&s=240
# Comment pagination
pagination:
# Number of comments per page
@@ -325,6 +439,8 @@ frontend:
children: 400
# Scrollable (scrollable height limit area)
scrollable: false
# Image lazy load [false, "native", "data-src"]
imgLazyLoad: false
# Request timeout (unit: ms)
reqTimeout: 15000
# Version check
+165 -48
View File
@@ -10,14 +10,17 @@ app_key: ""
# 调试模式
debug: false
# 语言 ["en", "zh-CN", "zh-TW", "jp"]
locale: "zh-CN"
# 语言 ["en", "zh-CN", "zh-TW", "ja", "fr", "ko", "ru"]
locale: zh-CN
# 时间区域
timezone: "Asia/Shanghai"
timezone: Asia/Shanghai
# 默认站点名
site_default: "默认站点"
site_default: 默认站点
# 默认站点地址
site_url: ""
# 登录有效时长 (单位:秒)
login_timeout: 259200
@@ -25,21 +28,21 @@ login_timeout: 259200
# 数据库
db:
# 数据库类型 ["sqlite", "mysql", "pgsql", "mssql"]
type: "sqlite"
type: sqlite
# 数据库文件 (仅 SQLite 数据库需填写)
file: "./data/artalk.db"
file: ./data/artalk.db
# 数据库名称
name: "artalk"
name: artalk
# 数据库地址
host: "localhost"
host: localhost
# 数据库端口
port: 3306
# 数据库账户
user: "root"
user: root
# 数据库密码
password: ""
# 编码格式
charset: "utf8mb4"
charset: utf8mb4
# 表前缀 (例如:"atk_")
table_prefix: ""
# 启用 SSL
@@ -47,19 +50,26 @@ db:
# 预编译语句
prepare_stmt: true
# 服务器
http:
# 请求体大小限制 (单位:MB)
body_limit: 100
# 代理标头名 (当使用 CDN 时填写 `X-Forwarded-For` 获取用户真实 IP)
proxy_header: ""
# 日志
log:
# 启用日志
enabled: true
# 日志文件路径
filename: "./data/artalk.log"
filename: ./data/artalk.log
# 缓存
cache:
# 启用缓存
enabled: false
# 缓存类型 ["redis", "memcache", "builtin"]
type: "builtin"
type: builtin
# 缓存过期时间 (单位:分钟)
expires: 30
# 缓存启动预热 (程序启动时预热缓存)
@@ -69,7 +79,7 @@ cache:
# Redis 配置
redis:
# 连接方式 ["tcp", "unix"]
network: "tcp"
network: tcp
# 用户名
username: ""
# 密码
@@ -78,7 +88,8 @@ cache:
db: 0
# 可信域名
trusted_domains: [] # 例如:["https://artalk.example.com:23366"]
# -- 例如:["https://artalk.example.com:23366"] --
trusted_domains: []
# SSL
ssl:
@@ -90,12 +101,14 @@ ssl:
key_path: ""
# 管理员账户
admin_users:
# - name: "admin"
# email: "admin@example.com"
# password: "" # 支持 bcrypt 或 md5 加密,如:"(md5)50c21190c6e4e5418c6a90d2b5031119"
# badge_name: "管理员"
# badge_color: "#0083FF"
# --
# - name: "admin"
# email: "admin@example.com"
# password: "" # 支持 bcrypt 或 md5 加密,如:"(bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm"
# badge_name: "管理员"
# badge_color: "#0083FF"
# --
admin_users: []
# 评论审核
moderator:
@@ -112,14 +125,14 @@ moderator:
enabled: false
secret_id: ""
secret_key: ""
region: "ap-guangzhou"
region: ap-guangzhou
# 阿里云内容安全
# (https://help.aliyun.com/document_detail/28417.html)
aliyun:
enabled: false
access_key_id: ""
access_key_secret: ""
region: "cn-shanghai"
region: cn-shanghai
# 关键词过滤 (本地离线词库)
keywords:
enabled: false
@@ -127,11 +140,11 @@ moderator:
pending: false
# 词库文件 (支持多个词库文件)
files:
- "./data/词库_1.txt"
- ./data/词库_1.txt
# 词库文件内容分割符 (例如填写 "\n" 文件中一行一个关键词)
file_sep: "\n"
# 替换字符
replac_to: "x"
replace_to: x
# 验证码
captcha:
@@ -140,7 +153,7 @@ captcha:
# 总是需要验证码
always: false
# 验证类型 ["image", "turnstile", "recaptcha", "hcaptcha", "geetest"]
captcha_type: "image"
captcha_type: image
# 激活验证码所需操作次数
action_limit: 3
# 重置操作计数器超时 (单位:s, 设为 -1 不重置)
@@ -169,16 +182,16 @@ ip_region:
# 启用 IP 属地展示
enabled: false
# 数据文件路径 (.xdb 格式)
db_path: "./data/ip2region.xdb"
db_path: ./data/ip2region.xdb
# 显示精度 ["province", "city", "country"]
precision: "province"
precision: province
# 图片上传
img_upload:
# 启用图片上传
enabled: true
# 图片存放路径
path: "./data/artalk-img/"
path: ./data/artalk-img/
# 图片大小限制 (单位:MB)
max_size: 5
# 图片链接基础路径 (默认为 "/static/images/")
@@ -189,7 +202,7 @@ img_upload:
# 启用 Upgit
enabled: false
# 命令行参数
exec: "./upgit -c <upgit配置文件路径> -t /artalk-img"
exec: upgit -c <upgit配置文件路径> -t /artalk-img
# 上传后删除本地的图片
del_local: true
@@ -198,23 +211,23 @@ email:
# 启用邮件通知
enabled: false
# 发送方式 ["smtp", "ali_dm", "sendmail"]
send_type: "smtp"
send_type: smtp
# 发信人昵称
send_name: "{{reply_nick}}"
# 发信人地址
send_addr: "noreply@example.com"
send_addr: noreply@example.com
# 邮件标题
mail_subject: "[{{site_name}}] 您收到了来自 @{{reply_nick}} 的回复"
# 邮件模板文件 (填入文件路径使用自定义模板)
mail_tpl: "default"
mail_tpl: default
# SMTP 发送 (启用请将发送方式设为 "smtp")
smtp:
# 发件地址
host: "smtp.qq.com"
host: smtp.qq.com
# 发件端口
port: 587
# 用户名
username: "example@qq.com"
username: example@qq.com
# 密码
password: ""
# 阿里云邮件推送
@@ -222,12 +235,12 @@ email:
ali_dm:
access_key_id: ""
access_key_secret: ""
account_name: "noreply@example.com"
account_name: noreply@example.com
# 多元推送
admin_notify:
# 通知模版 (填入文件路径使用自定义模板)
notify_tpl: "default"
notify_tpl: default
# 待审评论仍然发送通知 (当评论被拦截时仍然发送通知)
notify_pending: false
# 嘈杂模式
@@ -249,11 +262,13 @@ admin_notify:
# Bark
bark:
enabled: false
server: "http://day.app/xxxxxxx/"
server: http://day.app/xxxxxxx/
# 飞书
lark:
enabled: false
webhook_url: ""
# 消息类型 ["text", "card"]
msg_type: "text"
# WebHook
webhook:
enabled: false
@@ -268,15 +283,117 @@ admin_notify:
enabled: false
oauth_token: ""
receivers:
- "CHANNEL_ID"
- CHANNEL_ID
# LINE
line:
enabled: false
channel_secret: ""
channel_access_token: ""
receivers:
- "USER_ID_1"
- "GROUP_ID_1"
- USER_ID_1
- GROUP_ID_1
# 社交登录
auth:
# 启用社交登录
enabled: false
# 允许匿名评论 (允许跳过验证,仅填写匿名的昵称和邮箱)
anonymous: false
# 回调地址 (https://example.com/api/v2/auth/{provider}/callback)
callback: "http://localhost:23366/api/v2/auth/{provider}/callback"
# Email
email:
# 启用邮箱密码登录
enabled: true
# 邮箱验证邮件标题
verify_subject: "您的验证码是 - {{code}}"
# 邮箱验证邮件模板 (填入文件路径使用自定义模板)
verify_tpl: default
# GitHub
github:
enabled: false
client_id: ""
client_secret: ""
# GitLab
gitlab:
enabled: false
client_id: ""
client_secret: ""
# Gitea
gitea:
enabled: false
client_id: ""
client_secret: ""
# Google
google:
enabled: false
client_id: ""
client_secret: ""
# Mastodon
mastodon:
enabled: false
client_id: ""
client_secret: ""
# Twitter
twitter:
enabled: false
client_id: ""
client_secret: ""
# Facebook
facebook:
enabled: false
client_id: ""
client_secret: ""
# Discord
discord:
enabled: false
client_id: ""
client_secret: ""
# Steam
steam:
enabled: false
api_key: ""
# Apple
apple:
enabled: false
client_id: ""
client_secret: ""
# Microsoft
microsoft:
enabled: false
client_id: ""
client_secret: ""
# 微信
wechat:
enabled: false
client_id: ""
client_secret: ""
# Tiktok
tiktok:
enabled: false
client_id: ""
client_secret: ""
# Slack
slack:
enabled: false
client_id: ""
client_secret: ""
# Line
line:
enabled: false
client_id: ""
client_secret: ""
# Patreon
patreon:
enabled: false
client_id: ""
client_secret: ""
# Auth0
auth0:
enabled: false
client_id: ""
client_secret: ""
domain: ""
# 界面配置
frontend:
@@ -289,7 +406,7 @@ frontend:
# 评论框穿梭
editorTravel: true
# 表情包
emoticons: "https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json"
emoticons: https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json
# 投票按钮
vote: true
# 反对按钮
@@ -298,14 +415,12 @@ frontend:
uaBadge: false
# 评论排序功能
listSort: true
# 页面 PV 绑定元素
pvEl: "#ArtalkPV"
# 评论数绑定元素
countEl: "#ArtalkCount"
# 编辑器实时预览功能
preview: true
# 平铺模式 ["auto", true, false]
flatMode: "auto"
flatMode: auto
# 夜间模式 ["inherit", "auto"]
darkMode: inherit
# 最大嵌套层数
nestMax: 2
# 嵌套评论排序规则 ["DATE_ASC", "DATE_DESC", "VOTE_UP_DESC"]
@@ -313,9 +428,9 @@ frontend:
# 头像 Gravatar
gravatar:
# API 地址
mirror: "https://cravatar.cn/avatar/"
mirror: https://weavatar.com/avatar/
# API 参数
params: "d=mp&s=240"
params: sha256=1&d=mp&s=240
# 评论分页
pagination:
# 每页评论数
@@ -332,6 +447,8 @@ frontend:
children: 400
# 滚动限高 (允许限高区域滚动)
scrollable: false
# 图片懒加载 [false, "native", "data-src"]
imgLazyLoad: false
# 请求超时 (单位:毫秒)
reqTimeout: 15000
# 版本检测
+7 -1
View File
@@ -1,8 +1,9 @@
version: "3.5"
version: "3.8"
services:
artalk:
container_name: artalk
image: artalk/artalk-go
restart: unless-stopped
build:
context: ./
dockerfile: Dockerfile
@@ -10,3 +11,8 @@ services:
- 8080:23366
volumes:
- ./data:/data
environment:
- TZ=Asia/Shanghai
- ATK_LOCALE=zh-CN
- ATK_SITE_DEFAULT=Artalk 的博客
- ATK_SITE_URL=https://example.com
+2 -2
View File
@@ -14,11 +14,11 @@ if [ "$1" != 'gen' ] && ( [ ! -e /data/artalk.yml ] && [ ! -e /data/artalk-go.ym
upMsg+=$'# please unmount the config file volume from your container\n'
upMsg+=$'# and edit "/data/artalk.yml" for configuration.'
echo "$upMsg" > /conf.yml
echo "$(date) [info] Copy config file from '/conf.yml' to '/data/artalk.yml' for upgrade"
echo "$(date) [info][docker] Copy config file from '/conf.yml' to '/data/artalk.yml' for upgrade"
else
# Generate new config
artalk gen conf /data/artalk.yml
echo "$(date) [info] Generate new config file to '/data/artalk.yml'"
echo "$(date) [info][docker] Generate new config file to '/data/artalk.yml'"
fi
fi
+105 -136
View File
@@ -1,47 +1,22 @@
import { defineConfig } from "vitepress";
import iterator from "markdown-it-for-inline";
import * as Version from "../code/ArtalkVersion.json";
import { defineConfig } from 'vitepress'
import iterator from 'markdown-it-for-inline'
import * as Version from '../code/ArtalkVersion.json'
export default defineConfig({
title: "Artalk",
description: "一款简洁的自托管评论系统",
lang: "zh-CN",
title: 'Artalk',
description: '一款简洁的自托管评论系统',
lang: 'zh-CN',
head: [
["link", { rel: "icon", href: "/favicon.png" }],
['link', { rel: 'icon', href: '/favicon.png' }],
[
"meta",
'meta',
{
name: "viewport",
name: 'viewport',
content:
"width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi",
'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi',
},
],
// artalk
// ['link', { href: `https://npm.elemecdn.com/artalk@${Version.latest}/dist/Artalk.css`, rel: 'stylesheet' }],
// [
// "link",
// { href: `https://artalk.qwqaq.com/dist/Artalk.css`, rel: "stylesheet" },
// ],
// ['script', { src: ArtalkCDN.JS }],
// light gallery
[
"link",
{
href: "https://cdnjs.cloudflare.com/ajax/libs/lightgallery/2.3.0/css/lightgallery.css",
rel: "stylesheet",
},
],
[
"script",
{
src: "https://cdnjs.cloudflare.com/ajax/libs/lightgallery/2.3.0/lightgallery.min.js",
},
],
// katex
['link', { href: "https://unpkg.com/katex@0.15.3/dist/katex.min.css", rel: 'stylesheet' }],
['script', { src: 'https://unpkg.com/katex@0.15.3/dist/katex.min.js' }],
// ['script', { src: 'https://unpkg.com/@artalk/plugin-katex/dist/artalk-plugin-katex.js' }],
],
lastUpdated: true,
@@ -49,132 +24,126 @@ export default defineConfig({
markdown: {
// @link https://github.com/shikijs/shiki
theme: {
light: "github-light",
dark: "github-dark",
light: 'github-light',
dark: 'github-dark',
},
config: (md) => {
md.use(iterator, "artalk_version", "text", function (tokens, idx) {
md.use(iterator, 'artalk_version', 'text', function (tokens, idx) {
tokens[idx].content = tokens[idx].content.replace(
/:ArtalkVersion:/g,
Version.latest
);
});
md.use(iterator, "artalk_version_link", "link_open", (tokens, idx) => {
const href = tokens[idx].attrGet("href");
Version.latest,
)
})
md.use(iterator, 'artalk_version_link', 'link_open', (tokens, idx) => {
const href = tokens[idx].attrGet('href')
tokens[idx].attrSet(
"href",
href.replace(/:ArtalkVersion:/g, Version.latest)
);
});
'href',
href.replace(/:ArtalkVersion:/g, Version.latest),
)
})
},
},
locales: {
root: {
label: "简体中文",
lang: "zh",
link: "https://artalk.js.org/",
label: '简体中文',
lang: 'zh',
link: 'https://artalk.js.org/',
},
en: {
label: "English",
lang: "en",
link: "https://artalk-js-org.translate.goog/guide/intro?_x_tr_sl=auto&_x_tr_tl=en-US&_x_tr_hl=en-US&_x_tr_pto=wapp",
label: 'English',
lang: 'en',
link: 'https://artalk-js-org.translate.goog/guide/intro?_x_tr_sl=auto&_x_tr_tl=en-US&_x_tr_hl=en-US&_x_tr_pto=wapp',
},
},
themeConfig: {
sidebar: {
"/guide/": [
'/guide/': [
{
text: "快速开始",
text: '快速开始',
collapsed: false,
items: [
{ text: "项目介绍", link: "/guide/intro.md" },
{ text: "程序部署", link: "/guide/deploy.md" },
{ text: "数据迁移", link: "/guide/transfer.md" },
{ text: '项目介绍', link: '/guide/intro.md' },
{ text: '程序部署', link: '/guide/deploy.md' },
{ text: '数据迁移', link: '/guide/transfer.md' },
],
},
{
text: "核心指南",
text: '核心指南',
collapsed: false,
items: [
{ text: "侧边栏", link: "/guide/frontend/sidebar.md" },
{ text: "邮件通知", link: "/guide/backend/email.md" },
{ text: "多元推送", link: "/guide/backend/admin_notify.md" },
{ text: "评论审核", link: "/guide/backend/moderator.md" },
{ text: "验证码", link: "/guide/backend/captcha.md" },
{ text: "图片上传", link: "/guide/backend/img-upload.md" },
{ text: "账户与多站点", link: "/guide/backend/multi-site.md" },
{ text: "解析相对路径", link: "/guide/backend/relative-path.md" },
{ text: "如何配置界面", link: "/guide/backend/fe-control.md" },
{ text: "English (i18n)", link: "/guide/frontend/i18n.md" },
{ text: '侧边栏', link: '/guide/frontend/sidebar.md' },
{ text: '邮件通知', link: '/guide/backend/email.md' },
{ text: '多元推送', link: '/guide/backend/admin_notify.md' },
{ text: '社交登录', link: '/guide/frontend/auth.md' },
{ text: '评论审核', link: '/guide/backend/moderator.md' },
{ text: '验证码', link: '/guide/backend/captcha.md' },
{ text: '图片上传', link: '/guide/backend/img-upload.md' },
{ text: '账户与多站点', link: '/guide/backend/multi-site.md' },
{ text: '解析相对路径', link: '/guide/backend/relative-path.md' },
],
},
{
text: "进阶指南",
text: '进阶指南',
collapsed: false,
items: [
{ text: "表情包", link: "/guide/frontend/emoticons.md" },
{ text: "浏览量统计", link: "/guide/frontend/pv.md" },
{ text: "Latex", link: "/guide/frontend/latex.md" },
{ text: "图片灯箱", link: "/guide/frontend/lightbox.md" },
{ text: "IP 属地", link: "/guide/frontend/ip-region.md" },
{ text: "精简版本", link: "/guide/frontend/artalk-lite.md" },
{ text: "置入博客", link: "/guide/frontend/import-blog.md" },
{ text: "置入框架", link: "/guide/frontend/import-framework.md" },
{ text: "前端 API", link: "/develop/fe-api.md" },
{ text: "开发文档", link: "/develop/index.md" },
{ text: '表情包', link: '/guide/frontend/emoticons.md' },
{ text: '浏览量统计', link: '/guide/frontend/pv.md' },
{ text: 'LaTeX', link: '/guide/frontend/latex.md' },
{ text: '图片灯箱', link: '/guide/frontend/lightbox.md' },
{ text: '图片懒加载', link: '/guide/frontend/img-lazy-load.md' },
{ text: 'IP 属地', link: '/guide/frontend/ip-region.md' },
{ text: '多语言', link: '/guide/frontend/i18n.md' },
{ text: '开发文档', link: '/develop/index.md' },
],
},
{
text: "配置文档",
collapsed: true,
text: '配置文档',
collapsed: false,
items: [
{ text: "后端配置", link: "/guide/backend/config.md" },
{ text: "前端配置", link: "/guide/frontend/config.md" },
{ text: '环境变量', link: '/guide/env.md' },
{ text: '配置文件', link: '/guide/backend/config.md' },
{ text: '界面配置', link: '/guide/frontend/config.md' },
],
},
{
text: "部署说明",
text: '部署说明',
collapsed: true,
items: [
{ text: "守护进程", link: "/guide/backend/daemon.md" },
{ text: "反向代理", link: "/guide/backend/reverse-proxy.md" },
{ text: "编译构建", link: "/guide/backend/build.md" },
{ text: "程序升级", link: "/guide/backend/update.md" },
{ text: "Docker", link: "/guide/backend/docker.md" },
{ text: '守护进程', link: '/guide/backend/daemon.md' },
{ text: '反向代理', link: '/guide/backend/reverse-proxy.md' },
{ text: '编译构建', link: '/develop/contributing.md' },
{ text: '程序升级', link: '/guide/backend/update.md' },
{ text: 'Docker', link: '/guide/backend/docker.md' },
],
},
{
text: "更多内容",
text: '更多内容',
collapsed: true,
items: [
{ text: "安全防范", link: "/guide/security.md" },
{ text: "扩展阅读", link: "/guide/extras.md" },
{ text: "案例展示", link: "/guide/cases.md" },
{ text: "关于我们", link: "/guide/about.md" },
{ text: '安全防范', link: '/guide/security.md' },
{ text: '扩展阅读', link: '/guide/extras.md' },
{ text: '案例展示', link: '/guide/cases.md' },
{ text: '关于我们', link: '/guide/about.md' },
],
},
],
"/develop/": [
'/develop/': [
{
text: "开发文档",
text: '开发文档',
items: [
{ text: "开发说明", link: "/develop/index.md" },
{ text: "前端 API", link: "/develop/fe-api.md" },
{ text: "前端 Event", link: "/develop/event.md" },
{ text: "插件开发", link: "/develop/plugs.md" },
{ text: '开发说明', link: '/develop/index.md' },
{ text: '贡献指南', link: '/develop/contributing.md' },
{ text: '置入博客', link: '/develop/import-blog.md' },
{ text: '置入框架', link: '/develop/import-framework.md' },
{ text: '前端 API', link: '/develop/fe-api.md' },
{ text: '前端 Event', link: '/develop/event.md' },
{ text: '插件开发', link: '/develop/plugin.md' },
{ text: '兼容性', link: '/develop/compatibility.md' },
{
text: "🔬 HTTP API",
link: "https://artalk.js.org/http-api.html",
},
{
text: "📖 Contributing Guide",
link: "https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md",
},
{
text: "🔖 Code of Conduct",
link: "https://github.com/ArtalkJS/Artalk/blob/master/CODE_OF_CONDUCT.md",
text: 'HTTP API',
link: 'https://artalk.js.org/http-api.html',
},
],
},
@@ -184,36 +153,36 @@ export default defineConfig({
nav: [
// NavbarItem
{
text: "介绍",
link: "/guide/intro",
text: '介绍',
link: '/guide/intro',
},
{
text: "部署",
link: "/guide/deploy",
text: '部署',
link: '/guide/deploy',
},
{
text: "配置",
link: "/guide/backend/config",
text: '配置',
link: '/guide/backend/config',
},
{
text: "迁移",
link: "/guide/transfer",
text: '迁移',
link: '/guide/transfer',
},
{
text: "案例",
link: "/guide/cases",
text: '案例',
link: '/guide/cases',
},
{
text: "开发",
link: "/develop/",
text: '开发',
link: '/develop/',
},
// NavbarGroup
{
text: "传送",
text: '传送',
items: [
{
text: "代码仓库",
link: "https://github.com/ArtalkJS/Artalk",
text: '代码仓库',
link: 'https://github.com/ArtalkJS/Artalk',
},
// {
// text: "文档镜像 (国内)",
@@ -224,30 +193,30 @@ export default defineConfig({
],
socialLinks: [
{ icon: "github", link: "https://github.com/ArtalkJS/Artalk" },
{ icon: 'github', link: 'https://github.com/ArtalkJS/Artalk' },
],
search: {
provider: "algolia",
provider: 'algolia',
options: {
appId: "2WNJ32WVTY",
apiKey: "6c6ebc345a87b738264f19095b78c91c",
indexName: "artalk-js",
appId: '2WNJ32WVTY',
apiKey: '6c6ebc345a87b738264f19095b78c91c',
indexName: 'artalk-js',
searchParameters: {
facetFilters: ["lang:zh-CN"],
facetFilters: ['lang:zh-CN'],
},
},
},
editLink: {
pattern: "https://github.com/ArtalkJS/Artalk/edit/master/docs/:path",
text: "完善文档",
pattern: 'https://github.com/ArtalkJS/Artalk/edit/master/docs/docs/:path',
text: '完善文档',
},
},
vite: {
server: {
open: "/guide/intro.html",
open: '/guide/intro.html',
},
},
});
})
+28 -40
View File
@@ -1,11 +1,15 @@
<template>
<div ref="el" style="margin-top: 20px;"></div>
<div ref="el" style="margin-top: 20px"></div>
</template>
<script setup lang="ts">
import { watch, nextTick, ref, onMounted, onUnmounted } from 'vue'
import { useData, useRouter } from 'vitepress'
import Artalk from 'artalk'
import { ArtalkKatexPlugin } from '@artalk/plugin-katex'
import { ArtalkLightboxPlugin } from '@artalk/plugin-lightbox'
import 'lightgallery/css/lightgallery.css'
import 'katex/dist/katex.min.css'
import 'artalk/dist/Artalk.css'
const el = ref<HTMLElement | null>(null)
@@ -21,25 +25,32 @@ onMounted(() => {
})
})
watch(() => router.route.path, () => {
nextTick(() => {
artalk.update(getConfByPage())
artalk.reload()
})
})
watch(
() => router.route.path,
() => {
nextTick(() => {
artalk.update(getConfByPage())
artalk.reload()
})
},
)
onUnmounted(() => {
artalk.destroy()
})
function initArtalk(conf: any) {
Artalk.use(ArtalkKatexPlugin)
Artalk.use(ArtalkLightboxPlugin, {
lightGallery: {
lib: async () => (await import('lightgallery')).default
}
})
artalk = Artalk.init({
el: el.value,
el: el.value,
emoticons: '/assets/emoticons/default.json',
gravatar: {
mirror: 'https://cravatar.cn/avatar/'
},
...conf
...conf,
})
loadExtraFuncs()
@@ -47,32 +58,14 @@ function initArtalk(conf: any) {
function getConfByPage() {
return {
pageKey: 'https://artalk.js.org'+router.route.path,
pageTitle: page.value.title,
server: 'https://artalk.qwqaq.com',
site: 'ArtalkDocs',
pageKey: 'https://artalk.js.org' + router.route.path,
pageTitle: page.value.title,
server: 'https://artalk.qwqaq.com',
site: 'ArtalkDocs',
}
}
function loadExtraFuncs() {
// 图片灯箱插件
artalk.on('list-loaded', () => {
document.querySelectorAll('.atk-comment .atk-content').forEach(($content) => {
const imgEls = $content.querySelectorAll<HTMLImageElement>('img:not([atk-emoticon]):not([atk-lightbox])');
imgEls.forEach((imgEl) => {
imgEl.setAttribute('atk-lightbox', '')
const linkEl = document.createElement('a')
linkEl.setAttribute('class', 'atk-img-link')
linkEl.setAttribute('href', imgEl.src)
linkEl.setAttribute('data-src', imgEl.src)
linkEl.append(imgEl.cloneNode())
imgEl.replaceWith(linkEl)
})
// @ts-ignore
if (imgEls.length) lightGallery($content, { selector: '.atk-img-link' })
})
})
// 夜间模式
const darkMode = document.querySelector('html').classList.contains('dark')
artalk.setDarkMode(darkMode)
@@ -81,14 +74,9 @@ function loadExtraFuncs() {
mList.forEach((m) => {
if (m.attributeName !== 'class') return
// @ts-ignore
const darkMode = m.target.classList.contains('dark')
const darkMode = (<HTMLElement>m.target).classList.contains('dark')
artalk.setDarkMode(darkMode)
})
}).observe(document.querySelector('html'), { attributes: true })
}
</script>
<style>
</style>
+7 -8
View File
@@ -1,5 +1,9 @@
<template>
<iframe src="https://artransfer.netlify.app/?iframe=1" style="width: 100%;height: 520px;border: 0;" id="artransferIframe"></iframe>
<iframe
id="artransferIframe"
src="https://artransfer.netlify.app/?iframe=1"
style="width: 100%; height: 520px; border: 0"
></iframe>
</template>
<script lang="ts">
@@ -24,15 +28,10 @@ export default defineComponent({
mList.forEach((m) => {
if (m.attributeName !== 'class') return
// @ts-ignore
const darkMode = m.target.classList.contains('dark')
const darkMode = (<HTMLElement>m.target).classList.contains('dark')
setArtransferIframeDarkMode(darkMode)
})
}).observe(document.querySelector('html'), { attributes: true })
}
},
})
</script>
<style>
</style>
-3
View File
@@ -4,9 +4,6 @@ import { onMounted } from 'vue'
import './style.scss'
const { Layout } = DefaultTheme
onMounted(() => {
})
</script>
<template>
+2 -2
View File
@@ -1,8 +1,8 @@
import DefaultTheme from 'vitepress/theme'
import { Theme } from 'vitepress'
import Layout from './Layout.vue'
import Artalk from './Artalk.vue'
import Artransfer from './Artransfer.vue'
import { Theme } from 'vitepress'
export default {
...DefaultTheme,
@@ -16,5 +16,5 @@ export default {
// app is the Vue 3 app instance from `createApp()`.
// router is VitePress' custom router. `siteData` is
// a `ref` of current site-level metadata.
}
},
} as Theme
+29 -24
View File
@@ -8,7 +8,7 @@
--vp-c-divider: #dfe2e5;
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: linear-gradient(90deg,#0083ff, #37dfd9);
--vp-home-hero-name-background: linear-gradient(90deg, #0083ff, #37dfd9);
}
.dark {
@@ -38,9 +38,9 @@
background-color: #0083ff;
&:hover {
border-color: #007CF0;
border-color: #007cf0;
color: #fff;
background-color: #007CF0;
background-color: #007cf0;
}
}
@@ -48,52 +48,52 @@
.wave {
display: inline-block;
transform-origin: center bottom;
animation:upAnimation 2.33s ease .8s 3 both;
animation: upAnimation 2.33s ease 0.8s 3 both;
}
@keyframes upAnimation {
0% {
transform: rotate(0deg);
transition-timing-function:cubic-bezier(0.215, .61, .355, 1);
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
10% {
transform: rotate(-12deg);
transition-timing-function:cubic-bezier(0.215, .61, .355, 1);
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
20% {
transform: rotate(12deg);
transition-timing-function:cubic-bezier(0.215, .61, .355, 1);
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
28% {
transform: rotate(-10deg);
transition-timing-function:cubic-bezier(0.215, .61, .355, 1);
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
36% {
transform: rotate(10deg);
transition-timing-function:cubic-bezier(0.755, .5, .855, .06);
transition-timing-function: cubic-bezier(0.755, 0.5, 0.855, 0.06);
}
42% {
transform: rotate(-8deg);
transition-timing-function:cubic-bezier(0.755, .5, .855, .06);
transition-timing-function: cubic-bezier(0.755, 0.5, 0.855, 0.06);
}
48% {
transform: rotate(8deg);
transition-timing-function:cubic-bezier(0.755, .5, .855, .06);
transition-timing-function: cubic-bezier(0.755, 0.5, 0.855, 0.06);
}
52% {
transform: rotate(-4deg);
transition-timing-function:cubic-bezier(0.755, .5, .855, .06);
transition-timing-function: cubic-bezier(0.755, 0.5, 0.855, 0.06);
}
56% {
transform: rotate(4deg);
transition-timing-function:cubic-bezier(0.755, .5, .855, .06);
transition-timing-function: cubic-bezier(0.755, 0.5, 0.855, 0.06);
}
60% {
transform: rotate(0deg);
transition-timing-function:cubic-bezier(0.755, .5, .855, .06);
transition-timing-function: cubic-bezier(0.755, 0.5, 0.855, 0.06);
}
100% {
transform: rotate(0deg);
transition-timing-function:cubic-bezier(0.215, .61, .355, 1);
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
@@ -107,33 +107,38 @@ img[atk-emoticon] {
}
/* 由于 body 未添加一致的 transition,导致其他地方暗黑模式切换加 transition 比较怪 */
.vp-doc div[class*='language-'] { transition: none; }
.vp-doc :not(pre) > code { transition: none; }
.vp-doc div[class*='language-'] {
transition: none;
}
.vp-doc :not(pre) > code {
transition: none;
}
.vp-doc {
table {
border-collapse: collapse;
margin: 1rem 0;
display: block;
overflow-x: auto
overflow-x: auto;
}
td,th {
padding: .6em 1em;
td,
th {
padding: 0.6em 1em;
}
}
/* 侧边栏 */
.VPSidebar::-webkit-scrollbar {
width: 7px
width: 7px;
}
.VPSidebar::-webkit-scrollbar-track {
background-color: transparent
background-color: transparent;
}
.VPSidebar::-webkit-scrollbar-thumb {
background-color: var(--vp-c-divider)
background-color: var(--vp-c-divider);
}
// details block patch
@@ -146,5 +151,5 @@ img[atk-emoticon] {
}
.vp-code-group .tabs::after {
background-color: var(--vp-c-divider)
background-color: var(--vp-c-divider);
}
+3 -3
View File
@@ -1,5 +1,5 @@
declare module '*.vue' {
import { defineComponent } from 'vue';
const component: ReturnType<typeof defineComponent>;
export default component;
import { defineComponent } from 'vue'
const component: ReturnType<typeof defineComponent>
export default component
}
+1 -1
View File
@@ -1,3 +1,3 @@
{
"latest": "2.8.3"
"latest": "2.9.0"
}
+3 -3
View File
@@ -1,15 +1,15 @@
<!-- CSS -->
<link href="https://unpkg.com/artalk@2.4.4/dist/Artalk.css" rel="stylesheet">
<link href="http://localhost:8080/dist/Artalk.css" rel="stylesheet">
<!-- JS -->
<script src="https://unpkg.com/artalk@2.4.4/dist/Artalk.js"></script>
<script src="http://localhost:8080/dist/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments', // 绑定元素的 Selector
pageKey: '/post/1', // 固定链接 (留空自动获取)
pageKey: '/post/1', // 固定链接
pageTitle: '关于引入 Artalk 这档子事', // 页面标题 (留空自动获取)
server: 'http://localhost:8080', // 后端地址
site: 'Artalk 的博客', // 你的站点名
+273 -273
View File
@@ -6,11 +6,11 @@
::: tip 无特殊说明时 API 调用响应格式
| 字段名 | 类型 | 说明 |
| ----- | ------- | --- |
| `success` | Boolean | 接口调用结果 |
| `msg` | String | 返回消息,出错时此字段包含错误消息 |
| `data` | Any | 返回数据,可能为 Object / String / Array 类型 |
| 字段名 | 类型 | 说明 |
| --------- | ------- | --------------------------------------------- |
| `success` | Boolean | 接口调用结果 |
| `msg` | String | 返回消息,出错时此字段包含错误消息 |
| `data` | Any | 返回数据,可能为 Object / String / Array 类型 |
:::
@@ -22,42 +22,42 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `name` | String | 是 | 待新增评论者昵称 |
| `email` | String | 是 | 待新增评论者邮箱 |
| `link` | String | 否 | 待新增评论者链接 |
| `content` | String | 是 | 待新增评论内容 |
| `rid` | Number | 否 | 待新增评论为回复评论时传入父评论 `ID`,否则为 `0` |
| `page_key` | String | 是 | 待新增评论目标页面唯一标识符 |
| `page_title` | String | 否 | 待新增评论目标页面标题 |
| `token` | String | 否 | 评论请求 Token |
| `site_name` | String | 否 | 待新增评论目标站点名称 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------------ | -------- | :--: | ------------------------------------------------- |
| `name` | String | 是 | 待新增评论者昵称 |
| `email` | String | 是 | 待新增评论者邮箱 |
| `link` | String | 否 | 待新增评论者链接 |
| `content` | String | 是 | 待新增评论内容 |
| `rid` | Number | 否 | 待新增评论为回复评论时传入父评论 `ID`,否则为 `0` |
| `page_key` | String | 是 | 待新增评论目标页面唯一标识符 |
| `page_title` | String | 否 | 待新增评论目标页面标题 |
| `token` | String | 否 | 评论请求 Token |
| `site_name` | String | 否 | 待新增评论目标站点名称 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 评论新增成功 |
| `data.comment` | Object | - | 评论数据 |
| `data.comment.id` | Number | - | 评论 ID |
| `data.comment.content` | String | - | 评论正文 |
| `data.comment.nick` | String | - | 评论者昵称 |
| `data.comment.email_encrypted` | String | - | 评论者邮箱 MD5 加密值 |
| `data.comment.link` | String | - | 评论者链接 |
| `data.comment.ua` | String | - | 评论者 User-Agent |
| `data.comment.date` | String | - | 评论时间,格式为 `1970-01-01 00:00:00` |
| `data.comment.is_collapsed` | Boolean | - | 评论是否折叠 |
| `data.comment.is_pending` | Boolean | - | 评论是否待审 |
| `data.comment.is_allow_reply` | Boolean | - | 评论是否允许回复 |
| `data.comment.rid` | Number | `0` | 待新增评论为回复评论时返回父评论 `ID` |
| `data.comment.badge_name` | String | - | 评论者徽章文字 |
| `data.comment.badge_color` | String | - | 评论者徽章颜色 |
| `data.comment.visible` | Boolean | `true` | 评论是否可见 |
| `data.comment.vote_up` | Number | `0` | 评论赞同数 |
| `data.comment.vote_down` | Number | `0` | 评论反对数 |
| `data.comment.page_key` | String | - | 评论所在页面唯一标识符 |
| `data.comment.site_name` | String | - | 评论所在站点名称 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ------------------------------ | -------- | :----: | -------------------------------------- |
| `success` | Boolean | `true` | 评论新增成功 |
| `data.comment` | Object | - | 评论数据 |
| `data.comment.id` | Number | - | 评论 ID |
| `data.comment.content` | String | - | 评论正文 |
| `data.comment.nick` | String | - | 评论者昵称 |
| `data.comment.email_encrypted` | String | - | 评论者邮箱 SHA256 加密值 |
| `data.comment.link` | String | - | 评论者链接 |
| `data.comment.ua` | String | - | 评论者 User-Agent |
| `data.comment.date` | String | - | 评论时间,格式为 `1970-01-01 00:00:00` |
| `data.comment.is_collapsed` | Boolean | - | 评论是否折叠 |
| `data.comment.is_pending` | Boolean | - | 评论是否待审 |
| `data.comment.is_allow_reply` | Boolean | - | 评论是否允许回复 |
| `data.comment.rid` | Number | `0` | 待新增评论为回复评论时返回父评论 `ID` |
| `data.comment.badge_name` | String | - | 评论者徽章文字 |
| `data.comment.badge_color` | String | - | 评论者徽章颜色 |
| `data.comment.visible` | Boolean | `true` | 评论是否可见 |
| `data.comment.vote_up` | Number | `0` | 评论赞同数 |
| `data.comment.vote_down` | Number | `0` | 评论反对数 |
| `data.comment.page_key` | String | - | 评论所在页面唯一标识符 |
| `data.comment.site_name` | String | - | 评论所在站点名称 |
### 评论获取
@@ -65,51 +65,51 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `page_key` | String | 是 | 待获取评论页面的唯一标识符 |
| `limit` | Number | 否 | 待获取评论的数量限制 |
| `offset` | Number | 否 | 待获取评论的起始位置偏移 |
| `type` | String | 否 | 获取指定类型的评论 |
| `name` | String | 否 | 获取指定昵称的评论 |
| `email` | String | 否 | 获取指定邮箱的评论 |
| `site_name` | String | 否 | 获取指定站点名称的评论 |
| `flat_mode` | Boolean | 否 | 待获取评论是否平铺模式 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ----------- | -------- | :--: | -------------------------- |
| `page_key` | String | 是 | 待获取评论页面的唯一标识符 |
| `limit` | Number | 否 | 待获取评论的数量限制 |
| `offset` | Number | 否 | 待获取评论的起始位置偏移 |
| `type` | String | 否 | 获取指定类型的评论 |
| `name` | String | 否 | 获取指定昵称的评论 |
| `email` | String | 否 | 获取指定邮箱的评论 |
| `site_name` | String | 否 | 获取指定站点名称的评论 |
| `flat_mode` | Boolean | 否 | 待获取评论是否平铺模式 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 评论获取成功 |
| `data.comments` | Array | - | 页面评论数据 |
| `data.total` | Number | - | 页面评论总数(包括所有子评论) |
| `data.total_parents` | Number | - | 页面评论中父级评论总数 |
| `data.page` | Object | - | 页面数据 |
| `data.page.id` | Number | - | 页面 ID |
| `data.page.admin_only` | Boolean | - | 页面是否仅管理员可评论 |
| `data.page.key` | String | - | 页面唯一标识符 |
| `data.page.url` | String | - | 页面链接 |
| `data.page.title` | String | - | 页面标题 |
| `data.page.site_name` | String | - | 页面所在站点名称 |
| `data.page.vote_up` | Number | - | 页面赞同数 |
| `data.page.vote_down` | Number | - | 页面反对数 |
| `data.unread` | Array | - | 未读的评论提醒数据 |
| `data.unread_count` | Number | - | 未读的评论提醒数据总数 |
| `data.api_version` | Object | - | 目标 Artalk 后端版本数据 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ---------------------- | -------- | :----: | ------------------------------ |
| `success` | Boolean | `true` | 评论获取成功 |
| `data.comments` | Array | - | 页面评论数据 |
| `data.total` | Number | - | 页面评论总数(包括所有子评论) |
| `data.total_parents` | Number | - | 页面评论中父级评论总数 |
| `data.page` | Object | - | 页面数据 |
| `data.page.id` | Number | - | 页面 ID |
| `data.page.admin_only` | Boolean | - | 页面是否仅管理员可评论 |
| `data.page.key` | String | - | 页面唯一标识符 |
| `data.page.url` | String | - | 页面链接 |
| `data.page.title` | String | - | 页面标题 |
| `data.page.site_name` | String | - | 页面所在站点名称 |
| `data.page.vote_up` | Number | - | 页面赞同数 |
| `data.page.vote_down` | Number | - | 页面反对数 |
| `data.unread` | Array | - | 未读的评论提醒数据 |
| `data.unread_count` | Number | - | 未读的评论提醒数据总数 |
| `data.api_version` | Object | - | 目标 Artalk 后端版本数据 |
::: tip
- `data.comments` 数组中元素结构参考 [评论新增接口](#评论新增) `/api/add` 响应的 `data.comment`
- `data.unread` 数组中元素结构如下
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `id` | Number | - | 评论提醒 ID |
| `user_id` | Number | - | 评论提醒目标用户 ID |
| `comment_id` | Number | - | 评论提醒来源评论 ID |
| `is_read` | Boolean | - | 评论提醒是否已读 |
| `is_emailed` | Boolean | - | 评论提醒是否已发送邮件 |
| `read_link` | String | - | 评论提醒已读地址 |
- `data.api_version` 对象结构参考 [Artalk 版本接口](#artalk-版本) `/api/version` 响应
- `data.comments` 数组中元素结构参考 [评论新增接口](#评论新增) `/api/add` 响应的 `data.comment`
- `data.unread` 数组中元素结构如下
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `id` | Number | - | 评论提醒 ID |
| `user_id` | Number | - | 评论提醒目标用户 ID |
| `comment_id` | Number | - | 评论提醒来源评论 ID |
| `is_read` | Boolean | - | 评论提醒是否已读 |
| `is_emailed` | Boolean | - | 评论提醒是否已发送邮件 |
| `read_link` | String | - | 评论提醒已读地址 |
- `data.api_version` 对象结构参考 [Artalk 版本接口](#artalk-版本) `/api/version` 响应
:::
@@ -119,31 +119,31 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `name` | String | 否 | 待获取用户的昵称 |
| `email` | String | 否 | 待获取用户的邮箱 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------- | -------- | :--: | ---------------- |
| `name` | String | 否 | 待获取用户的昵称 |
| `email` | String | 否 | 待获取用户的邮箱 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 用户获取成功 |
| `data.user` | Object | `null` | 获取的用户数据,若用户不存在返回空 |
| `data.user.id` | Number | - | 用户 ID |
| `data.user.name` | String | - | 用户昵称 |
| `data.user.email` | String | - | 用户邮箱 |
| `data.user.link` | String | - | 用户链接 |
| `data.user.badge_name` | String | - | 用户徽章文字 |
| `data.user.badge_color` | String | - | 用户徽章颜色 |
| `data.user.is_admin` | Boolean | - | 用户是否管理员 |
| `data.is_login` | Boolean | - | 用户是否登录 |
| `data.unread` | Array | `[]` | 用户未读的评论提醒数据 |
| `data.unread_count` | Number | `0` | 用户未读的评论提醒数据总数 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ----------------------- | -------- | :----: | ---------------------------------- |
| `success` | Boolean | `true` | 用户获取成功 |
| `data.user` | Object | `null` | 获取的用户数据,若用户不存在返回空 |
| `data.user.id` | Number | - | 用户 ID |
| `data.user.name` | String | - | 用户昵称 |
| `data.user.email` | String | - | 用户邮箱 |
| `data.user.link` | String | - | 用户链接 |
| `data.user.badge_name` | String | - | 用户徽章文字 |
| `data.user.badge_color` | String | - | 用户徽章颜色 |
| `data.user.is_admin` | Boolean | - | 用户是否管理员 |
| `data.is_login` | Boolean | - | 用户是否登录 |
| `data.unread` | Array | `[]` | 用户未读的评论提醒数据 |
| `data.unread_count` | Number | `0` | 用户未读的评论提醒数据总数 |
::: tip
- `data.unread` 数组中元素结构参考 [评论获取接口](#评论获取) `/api/get` **TIP**
- `data.unread` 数组中元素结构参考 [评论获取接口](#评论获取) `/api/get` **TIP**
:::
@@ -153,18 +153,18 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `name` | String | 是 | 待登录用户的昵称 |
| `email` | String | 是 | 待登录用户的邮箱 |
| `password` | String | 是 | 待登录用户的密码(管理员身份验证) |
| 字段名 | 数据类型 | 必需 | 说明 |
| ---------- | -------- | :--: | ---------------------------------- |
| `name` | String | 是 | 待登录用户的昵称 |
| `email` | String | 是 | 待登录用户的邮箱 |
| `password` | String | 是 | 待登录用户的密码(管理员身份验证) |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 用户登录成功 |
| `data.token` | String | - | 登录的用户 Token |
| 字段名 | 数据类型 | 默认 | 说明 |
| ------------ | -------- | :----: | ---------------- |
| `success` | Boolean | `true` | 用户登录成功 |
| `data.token` | String | - | 登录的用户 Token |
### 提醒已读
@@ -172,19 +172,19 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `notify_key` | String | 否 | 评论提醒唯一标识符 |
| `name` | String | 否 | 评论提醒用户的昵称 |
| `email` | String | 否 | 评论提醒用户的邮箱 |
| `all_read` | Boolean | 否 | 评论提醒是否已读 |
| `site_name` | String | 否 | 评论提醒所在站点名称 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------------ | -------- | :--: | -------------------- |
| `notify_key` | String | 否 | 评论提醒唯一标识符 |
| `name` | String | 否 | 评论提醒用户的昵称 |
| `email` | String | 否 | 评论提醒用户的邮箱 |
| `all_read` | Boolean | 否 | 评论提醒是否已读 |
| `site_name` | String | 否 | 评论提醒所在站点名称 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 提醒已读成功 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------- | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 提醒已读成功 |
### 评论投票
@@ -192,20 +192,20 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `target_id` | Number | 是 | 待投票评论 ID |
| `type` | String | 否 | 待投票类型,前缀 `comment_`、`page_` 依次代表对评论投票、对页面投票,后缀 `_up`、`_down` 依次代表赞同、反对 |
| `name` | String | 否 | 投票用户昵称 |
| `email` | String | 否 | 投票用户邮箱 |
| `site_name` | String | 否 | 投票目标评论或页面所在站点名称 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ----------- | -------- | :--: | ----------------------------------------------------------------------------------------------------------- |
| `target_id` | Number | 是 | 待投票评论 ID |
| `type` | String | 否 | 待投票类型,前缀 `comment_`、`page_` 依次代表对评论投票、对页面投票,后缀 `_up`、`_down` 依次代表赞同、反对 |
| `name` | String | 否 | 投票用户昵称 |
| `email` | String | 否 | 投票用户邮箱 |
| `site_name` | String | 否 | 投票目标评论或页面所在站点名称 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 评论投票成功 |
| `data.vote_num` | Number | - | 目标评论或页面指定类型投票数据 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------------- | -------- | :----: | ------------------------------ |
| `success` | Boolean | `true` | 评论投票成功 |
| `data.vote_num` | Number | - | 目标评论或页面指定类型投票数据 |
### Artalk 版本
@@ -221,12 +221,12 @@
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `app` | String | `artalk` | Artalk 后端程序名 |
| `version` | String | - | Artalk 后端程序版本号 |
| `commit_hash` | String | - | Artalk 后端程序 Git 提交哈希值 |
| `fe_min_version` | String | - | Artalk 后端程序所需前端最低版本 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ---------------- | -------- | :------: | ------------------------------- |
| `app` | String | `artalk` | Artalk 后端程序名 |
| `version` | String | - | Artalk 后端程序版本号 |
| `commit_hash` | String | - | Artalk 后端程序 Git 提交哈希值 |
| `fe_min_version` | String | - | Artalk 后端程序所需前端最低版本 |
## Captcha API
@@ -238,10 +238,10 @@
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 验证码刷新成功 |
| `data.img_data` | String | - | 根据 IP 获取的验证码图片 Base64 编码 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------------- | -------- | :----: | ------------------------------------ |
| `success` | Boolean | `true` | 验证码刷新成功 |
| `data.img_data` | String | - | 根据 IP 获取的验证码图片 Base64 编码 |
### 验证码检验
@@ -249,16 +249,16 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `value` | String | 是 | 验证码 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------- | -------- | :--: | ------ |
| `value` | String | 是 | 验证码 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 验证码检验成功 |
| `data.img_data` | String | - | 新的验证码图片 Base64 编码,仅验证码检验出错时存在此字段 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------------- | -------- | :----: | -------------------------------------------------------- |
| `success` | Boolean | `true` | 验证码检验成功 |
| `data.img_data` | String | - | 新的验证码图片 Base64 编码,仅验证码检验出错时存在此字段 |
## Admin API
@@ -268,31 +268,31 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 待编辑评论 ID,**不可修改** |
| `site_name` | String | 否 | 待编辑评论所在站点名称,**不可修改** |
| `content` | String | 否 | 待编辑评论正文 |
| `page_key` | String | 否 | 待编辑评论所在页面唯一标识符 |
| `nick` | String | 否 | 待编辑评论所属用户昵称 |
| `email` | String | 否 | 待编辑评论所属用户邮箱 |
| `link` | String | 否 | 待编辑评论所属用户链接 |
| `rid` | String | 否 | 待编辑评论为回复评论时传入父评论 `ID`,否则为 `0` |
| `ua` | String | 否 | 待编辑评论所属用户 User-Agent |
| `ip` | String | 否 | 待编辑评论所属用户 IP |
| `is_collapsed` | Boolean | 否 | 待编辑评论是否折叠 |
| `is_pending` | Boolean | 否 | 待编辑评论是否待审 |
| 字段名 | 数据类型 | 必需 | 说明 |
| -------------- | -------- | :--: | ------------------------------------------------- |
| `id` | Number | 是 | 待编辑评论 ID,**不可修改** |
| `site_name` | String | 否 | 待编辑评论所在站点名称,**不可修改** |
| `content` | String | 否 | 待编辑评论正文 |
| `page_key` | String | 否 | 待编辑评论所在页面唯一标识符 |
| `nick` | String | 否 | 待编辑评论所属用户昵称 |
| `email` | String | 否 | 待编辑评论所属用户邮箱 |
| `link` | String | 否 | 待编辑评论所属用户链接 |
| `rid` | String | 否 | 待编辑评论为回复评论时传入父评论 `ID`,否则为 `0` |
| `ua` | String | 否 | 待编辑评论所属用户 User-Agent |
| `ip` | String | 否 | 待编辑评论所属用户 IP |
| `is_collapsed` | Boolean | 否 | 待编辑评论是否折叠 |
| `is_pending` | Boolean | 否 | 待编辑评论是否待审 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 评论编辑成功 |
| `data.comment` | Object | - | 编辑评论的新数据 |
| 字段名 | 数据类型 | 默认 | 说明 |
| -------------- | -------- | :----: | ---------------- |
| `success` | Boolean | `true` | 评论编辑成功 |
| `data.comment` | Object | - | 编辑评论的新数据 |
::: tip
- `data.comment` 对象结构参考 [评论新增接口](#评论新增) `/api/add` 响应的 `data.comment`
- `data.comment` 对象结构参考 [评论新增接口](#评论新增) `/api/add` 响应的 `data.comment`
:::
@@ -310,16 +310,16 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 待删除评论 ID |
| `site_name` | String | 是 | 待删除评论所在站点名称 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ----------- | -------- | :--: | ---------------------- |
| `id` | Number | 是 | 待删除评论 ID |
| `site_name` | String | 是 | 待删除评论所在站点名称 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 评论删除成功 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------- | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 评论删除成功 |
### 页面获取
@@ -327,22 +327,22 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `site_name` | String | 是 | 待获取页面目标站点名称 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ----------- | -------- | :--: | ---------------------- |
| `site_name` | String | 是 | 待获取页面目标站点名称 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 页面获取成功 |
| `data.pages` | Array | - | 目标站点的页面数据 |
| `data.sites` | Array | - | 所有站点数据 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ------------ | -------- | :----: | ------------------ |
| `success` | Boolean | `true` | 页面获取成功 |
| `data.pages` | Array | - | 目标站点的页面数据 |
| `data.sites` | Array | - | 所有站点数据 |
::: tip
- `data.pages` 数组中元素结构参考 [评论获取接口](#评论获取) `/api/get` 响应的 `data.page`
- `data.sites` 数组中元素结构参考 [站点编辑接口](#站点编辑) `/api/admin/site-edit` 响应的 `data.site`
- `data.pages` 数组中元素结构参考 [评论获取接口](#评论获取) `/api/get` 响应的 `data.page`
- `data.sites` 数组中元素结构参考 [站点编辑接口](#站点编辑) `/api/admin/site-edit` 响应的 `data.site`
:::
@@ -352,24 +352,24 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 待编辑页面 ID,**不可修改** |
| `site_name` | String | 否 | 待编辑页面所在站点名称,**不可修改** |
| `key` | String | 否 | 待编辑页面唯一标识符 |
| `title` | String | 否 | 待编辑页面标题 |
| `admin_only` | Boolean | 否 | 待编辑页面是否仅管理员可评论 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------------ | -------- | :--: | ------------------------------------ |
| `id` | Number | 是 | 待编辑页面 ID,**不可修改** |
| `site_name` | String | 否 | 待编辑页面所在站点名称,**不可修改** |
| `key` | String | 否 | 待编辑页面唯一标识符 |
| `title` | String | 否 | 待编辑页面标题 |
| `admin_only` | Boolean | 否 | 待编辑页面是否仅管理员可评论 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 页面编辑成功 |
| `data.page` | Object | - | 编辑页面的新数据 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ----------- | -------- | :----: | ---------------- |
| `success` | Boolean | `true` | 页面编辑成功 |
| `data.page` | Object | - | 编辑页面的新数据 |
::: tip
- `data.page` 对象结构参考 [评论获取接口](#评论获取) `/api/get` 响应的 `data.page`
- `data.page` 对象结构参考 [评论获取接口](#评论获取) `/api/get` 响应的 `data.page`
:::
@@ -387,16 +387,16 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `key` | String | 是 | 待删除页面唯一标识符 |
| `site_name` | String | 是 | 待删除页面所在站点名称 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ----------- | -------- | :--: | ---------------------- |
| `key` | String | 是 | 待删除页面唯一标识符 |
| `site_name` | String | 是 | 待删除页面所在站点名称 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 页面删除成功 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------- | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 页面删除成功 |
### 页面更新
@@ -404,20 +404,20 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 待更新页面 ID |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------ | -------- | :--: | ------------- |
| `id` | Number | 是 | 待更新页面 ID |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 页面更新成功 |
| `data.page` | Object | - | 更新页面的新数据 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ----------- | -------- | :----: | ---------------- |
| `success` | Boolean | `true` | 页面更新成功 |
| `data.page` | Object | - | 更新页面的新数据 |
::: tip
- `data.page` 对象结构参考 [评论获取接口](#评论获取) `/api/get` 响应的 `data.page`
- `data.page` 对象结构参考 [评论获取接口](#评论获取) `/api/get` 响应的 `data.page`
:::
@@ -429,14 +429,14 @@
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 站点获取成功 |
| `data.sites` | Array | - | 所有站点数据 |
| 字段名 | 数据类型 | 默认 | 说明 |
| ------------ | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 站点获取成功 |
| `data.sites` | Array | - | 所有站点数据 |
::: tip
- `data.sites` 数组中元素结构参考 [站点编辑接口](#站点编辑) `/api/admin/site-edit` 响应的 `data.site`
- `data.sites` 数组中元素结构参考 [站点编辑接口](#站点编辑) `/api/admin/site-edit` 响应的 `data.site`
:::
@@ -446,22 +446,22 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `name` | String | 是 | 待新增站点名称 |
| `urls` | String | 是 | 待新增站点链接,如有多个需以英文半角符号 `,` 分割 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------ | -------- | :--: | ------------------------------------------------- |
| `name` | String | 是 | 待新增站点名称 |
| `urls` | String | 是 | 待新增站点链接,如有多个需以英文半角符号 `,` 分割 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 站点新增成功 |
| `data.site` | Object | - | 新增站点的数据 |
| `data.site.id` | Number | - | 站点 ID |
| `data.site.name` | String | - | 站点名称 |
| `data.site.urls` | Array | - | 站点链接数组,元素为单个站点链接字符串 |
| `data.site.urls_raw` | String | - | 站点链接数组合并字符串,以英文半角符号 `,` 分割 |
| `data.site.first_url` | String | - | 站点第一链接 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------------------- | -------- | :----: | ----------------------------------------------- |
| `success` | Boolean | `true` | 站点新增成功 |
| `data.site` | Object | - | 新增站点的数据 |
| `data.site.id` | Number | - | 站点 ID |
| `data.site.name` | String | - | 站点名称 |
| `data.site.urls` | Array | - | 站点链接数组,元素为单个站点链接字符串 |
| `data.site.urls_raw` | String | - | 站点链接数组合并字符串,以英文半角符号 `,` 分割 |
| `data.site.first_url` | String | - | 站点第一链接 |
### 站点编辑
@@ -469,23 +469,23 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 待编辑站点 ID |
| `name` | String | 是 | 待编辑站点新名称 |
| `urls` | String | 是 | 待编辑站点新链接 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------ | -------- | :--: | ---------------- |
| `id` | Number | 是 | 待编辑站点 ID |
| `name` | String | 是 | 待编辑站点新名称 |
| `urls` | String | 是 | 待编辑站点新链接 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 站点编辑成功 |
| `data.site` | Object | - | 编辑站点的新数据 |
| `data.site.id` | Number | - | 站点 ID |
| `data.site.name` | String | - | 站点名称 |
| `data.site.urls` | Array | - | 站点链接数组,元素为单个站点链接字符串 |
| `data.site.urls_raw` | String | - | 站点链接数组合并字符串,以英文半角符号 `,` 分割 |
| `data.site.first_url` | String | - | 站点第一链接 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------------------- | -------- | :----: | ----------------------------------------------- |
| `success` | Boolean | `true` | 站点编辑成功 |
| `data.site` | Object | - | 编辑站点的新数据 |
| `data.site.id` | Number | - | 站点 ID |
| `data.site.name` | String | - | 站点名称 |
| `data.site.urls` | Array | - | 站点链接数组,元素为单个站点链接字符串 |
| `data.site.urls_raw` | String | - | 站点链接数组合并字符串,以英文半角符号 `,` 分割 |
| `data.site.first_url` | String | - | 站点第一链接 |
### 站点删除
@@ -501,16 +501,16 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 待删除站点 ID |
| `del_content` | Boolean | 否 | 是否删除站点所有数据,为 `false` 时仅删除站点配置而保留站点评论数据 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------------- | -------- | :--: | ------------------------------------------------------------------- |
| `id` | Number | 是 | 待删除站点 ID |
| `del_content` | Boolean | 否 | 是否删除站点所有数据,为 `false` 时仅删除站点配置而保留站点评论数据 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 站点删除成功 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------- | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 站点删除成功 |
### 设置获取
@@ -518,17 +518,17 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 管理员用户 ID |
| `name` | String | 否 | 管理员用户昵称 |
| `url` | String | 否 | 管理员用户链接 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------ | -------- | :--: | -------------- |
| `id` | Number | 是 | 管理员用户 ID |
| `name` | String | 否 | 管理员用户昵称 |
| `url` | String | 否 | 管理员用户链接 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 设置获取成功 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------- | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 设置获取成功 |
### 设置保存
@@ -536,17 +536,17 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `id` | Number | 是 | 管理员用户 ID |
| `name` | String | 否 | 管理员用户昵称 |
| `url` | String | 否 | 管理员用户链接 |
| 字段名 | 数据类型 | 必需 | 说明 |
| ------ | -------- | :--: | -------------- |
| `id` | Number | 是 | 管理员用户 ID |
| `name` | String | 否 | 管理员用户昵称 |
| `url` | String | 否 | 管理员用户链接 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 设置保存成功 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------- | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 设置保存成功 |
### 邮件发送
@@ -560,17 +560,17 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `subject` | String | 是 | 邮件主题 |
| `body` | String | 是 | 邮件正文 |
| `to_addr` | String | 是 | 邮件收件人 |
| 字段名 | 数据类型 | 必需 | 说明 |
| --------- | -------- | :--: | ---------- |
| `subject` | String | 是 | 邮件主题 |
| `body` | String | 是 | 邮件正文 |
| `to_addr` | String | 是 | 邮件收件人 |
**响应**
| 字段名 | 数据类型 | 默认 | 说明 |
| ----- | ------- | :-: | --- |
| `success` | Boolean | `true` | 邮件发送成功 |
| 字段名 | 数据类型 | 默认 | 说明 |
| --------- | -------- | :----: | ------------ |
| `success` | Boolean | `true` | 邮件发送成功 |
### Artrans 接口
@@ -584,9 +584,9 @@
**参数**
| 字段名 | 数据类型 | 必需 | 说明 |
| ----- | ------- | :---: | --- |
| `type` | String | 是 | 导入数据类型 |
| `payload` | String | 否 | 导入数据 |
| 字段名 | 数据类型 | 必需 | 说明 |
| --------- | -------- | :--: | ------------ |
| `type` | String | 是 | 导入数据类型 |
| `payload` | String | 否 | 导入数据 |
**响应** 无
+18
View File
@@ -0,0 +1,18 @@
# 兼容性
## 浏览器兼容性
Artalk 客户端生产环境代码的构建通过 esbuild 执行,构建目标为 `es2015`。但请注意,构建仅会处理语法转义遵循 `es2015` 标准,不会处理 API 的兼容性(不包含任何 polyfill)。
如果你的项目需要支持较旧的浏览器和设备,请考虑在捆绑应用程序中包含全局 polyfill。我们推荐使用 [Polyfill.io](https://polyfill.io/) 服务,它会根据用户的 User-Agent 动态返回所需的 polyfill。另外,你也可以使用 [core-js](https://github.com/zloirock/core-js) 或 [Babel](https://babeljs.io/) 来手动添加 polyfill。
以下是 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)
## 服务器兼容性
Artalk 服务端程序基于 Golang 开发,支持 Linux、Windows 和 macOS 等操作系统。当前 Artalk 的 Golang 版本可通过 [go.mod](https://github.com/ArtalkJS/Artalk/blob/master/go.mod#L3) 查看。关于 Golang 的最低操作系统要求,可参考 [Go Wiki](https://go.dev/wiki/MinimumRequirements)。
+298
View File
@@ -0,0 +1,298 @@
# 开发者贡献指南
本指南帮助开发者了解如何在 Artalk 项目中贡献代码、文档、测试和反馈。我们欢迎所有形式的贡献,无论是大型功能开发、小型修复、文档改进还是测试。我们相信每一个贡献都是推动项目前进的重要一环。
本指南包含多语言版本:[English](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md) • [简体中文](https://artalk.js.org/develop/contributing.html)
## 克隆仓库
克隆仓库:
```sh
git clone https://github.com/ArtalkJS/Artalk.git
```
建议您先 fork 仓库,然后克隆 fork 后的仓库。
导航到目录:
```sh
cd Artalk
```
## 开发环境
为了开发 Artalk 的前端和后端,请安装以下工具:
- [Node.js](https://nodejs.org/en/) (>= 20.17.0)
- [PNPM](https://pnpm.io/) (>= 9.9.0)
- [Go](https://golang.org/) (>= 1.22)
- [Docker](https://www.docker.com/) (>= 20.10.0)(可选)
- [Docker Compose](https://docs.docker.com/compose/) (>= 1.29.0)(可选)
## 开发工作流程概述
开发工作流程包括以下步骤:
1. **搭建完整的开发实例**:
- 导航到 Artalk 仓库目录。
- 执行 `make dev` 在端口 `23366` 上运行后端。
- 执行 `pnpm dev` 在端口 `5173` 上运行前端。
- 可选地,执行 `pnpm dev:sidebar` 在端口 `23367` 上运行侧边栏前端。
2. **访问前端进行开发**:
- 打开浏览器,访问 `http://localhost:5173` 进行开发和测试。
3. **测试**:
- 使用 `make test` 运行后端单元测试。
- 使用 `pnpm test` 运行 UI 单元测试。
- 使用 `make test-frontend-e2e` 运行 UI 端到端测试。
4. **构建前端代码**:
- 当您对前端代码进行更改后,使用 `pnpm build:all` 构建完整的前端程序。
- JavaScript 和 CSS 代码将在 `ui/artalk/dist` 目录中找到。
- 前端代码由 GitHub Actions 自动部署到 NPM。
5. **构建后端代码**:
- 当您对后端代码进行更改后,注意后端程序会嵌入前端代码。
- 在构建后端之前,运行 `make build-frontend`(它运行 `scripts/build-frontend.sh`)。这将把嵌入的前端主程序和侧边栏前端程序放入 `/public` 目录。
- 然后,使用 `make build` 构建后端程序。
更多探索:
- **开发 Artalk 插件或主题**:
请参考 [Artalk 插件开发指南](https://artalk.js.org/develop/plugin.html)。
- **Makefile**:
您可以探索 `Makefile` 中的过程和命令。
- **GitHub 上的自动化 CI**:
GitHub 上的自动化 CI 流水线位于 `.github/workflows` 目录中,负责构建前端、后端和 Docker 镜像,发布 Docker 镜像到 Docker Hub,处理 npm 包发布,并创建 GitHub Releases,同时测试前端和后端。
以下部分提供了更详细的开发工作流程信息。
## 项目结构
Artalk 是一个 monorepo 项目,这意味着所有源代码都在一个仓库中。尽管如此,前端和后端保持分离。前端部分位于 `./ui` 目录中。
### 目录概览
- `bin/`:编译的二进制文件。(此目录被 git 忽略)
- `cmd/`:命令行工具的源代码。
- `conf/`:示例配置文件。
- `data/`:本地数据。(此目录被 git 忽略)
- `docs/`:文档站点的源代码。
- `i18n/`:翻译文件。
- `local/`:本地文件。(此目录被 git 忽略)
- `internal/`:内部包的 Go 源代码。
- `public/`:静态文件。构建的前端文件将被复制到这里。
- `scripts/`:开发和构建的脚本。
- `server/`:后端的 Go 源代码。
- `ui/`:前端的 UI 源代码。
- `.github/`:GitHub Actions 工作流。
- `.vscode/`:VSCode 设置。
## 后端开发
### 运行后端
1. **创建配置文件**:
- 将 `./conf/artalk.example.yml` 复制到根目录。
- 重命名为 `artalk.yml`。
- 根据需要修改文件。
2. **启动后端程序**:
- 运行 `make dev` 启动后端,端口为 `23366`。
- 通过 `http://localhost:23366` 访问。
- 建议保留默认端口进行测试。
- (替代)使用 `ARGS="version" make dev` 传递启动参数(默认是 `ARGS="server"`)。
`make dev` 命令会带有调试符号构建后端,这方便使用 GDB 进行调试。
如果您使用 VSCode,可以使用 `F5` 键(或运行按钮)直接启动调试后端程序。
### 构建后端
1. **获取最新的 Git 标签**:
执行 `git fetch --tags` 获取最新的 Git 标签信息。此标签将用作后端应用程序的版本号。或者,通过环境变量指定:`VERSION="v1.0.0"` 和 `COMMIT_HASH="66128e"`。
2. **构建前端**:
运行 `make build-frontend` 构建前端,因为后端应用程序会嵌入前端代码。
3. **构建后端**:
执行 `make build` 构建后端程序。
构建的二进制文件将位于 `./bin` 目录中。
## 前端开发(UI)
### 运行前端
1. **安装依赖**:
运行 `pnpm install` 安装所有必要的依赖。
2. **启动开发服务器**:
执行 `pnpm dev --port 5173` 启动前端开发服务器。
3. **访问前端**:
前端应用程序默认将在端口 `5173` 上运行。在浏览器中访问 `http://localhost:5173`。
4. **侧边栏开发**:
要运行侧边栏部分的前端,请使用 `pnpm dev:sidebar`。
端口 `5173` 和 `23367` 用于前端开发和测试。这些端口被包括在后端程序的 `ATK_TRUSTED_DOMAINS` 配置中。
### 构建前端
要构建前端,请运行以下命令:
```sh
make build-frontend
```
编译的 JavaScript 和 CSS 文件将位于 `/public` 目录中,嵌入到后端程序中。
更多详细信息,请参考 `scripts/build-frontend.sh` 脚本。
## Docker 开发
### 构建 Docker 镜像
要构建 Docker 镜像,请运行以下命令:
```sh
docker build -t artalk:TAG .
```
将 `TAG` 替换为所需的标签名(例如 `latest`)。
### 跳过前端构建
如果您已经在 Docker 容器外部构建了前端,可以跳过容器内的前端构建过程以加快构建速度。使用以下命令:
```sh
docker build --build-arg SKIP_FRONTEND_BUILD=true -t artalk:latest .
```
更多详细信息,请参考 `Dockerfile`。
## 测试
### 测试后端
要测试后端 Go 程序,可以使用以下命令:
- **单元测试**:
运行 `make test` 执行单元测试。结果将输出在终端。
- **测试覆盖率**:
运行 `make test-coverage` 检查代码测试覆盖率。
- **HTML 覆盖率报告**:
运行 `make test-coverage-html` 生成并浏览 HTML 格式的测试覆盖率报告。
- **运行特定测试**:
要运行特定测试,请使用带有环境变量的命令:
```sh
TEST_PATHS="./server/..." make test
```
### 测试前端
前端测试包括单元测试和端到端(E2E)测试。
- **单元测试**:
前端的单元测试使用 Vitest 进行。运行 `pnpm test` 开始单元测试。
- **端到端测试**:
E2E 测试使用 Playwright 进行。要启动 E2E 测试,运行:
```sh
make test-frontend-e2e
```
### 持续集成测试
前端和后端的测试都是自动化的,并将在 Git pull 请求和构建过程中使用 CircleCI 或 GitHub Actions 执行。
## 配置
模板配置文件位于 `/conf` 目录中,模板以多种语言注释,命名格式为 `artalk.example.[lang].yml`(例如,`artalk.example.zh-CN.yml`)。Artalk 将解析这些模板配置文件以生成设置界面、环境变量名称和文档。为了提高性能,程序运行期间将缓存部分数据以消除解析时间。
在 `internal/config/config.go` 文件中,有一个名为 `Config` 的结构体定义,该结构体用于将 yml 文件解析为 Go 结构体。该结构体包含更精确的类型定义。如果需要添加、修改或删除配置项,必须同时修改 `/conf` 目录中的配置文件模板和 `Config` 结构体。
当您修改配置文件后,请运行以下命令以更新配置数据缓存:
```sh
make update-conf
```
要更新环境变量文档,可以运行以下命令:
```sh
make update-conf-docs
```
## 文档
文档由三个部分组成,每个部分与特定包相关:**指南文档**、**着陆页**和 **Swagger API 文档**。下面是每个包的相关命令及其输出的总结。
### 指南文档 (`docs`)
- **目录**:`docs/docs/guide`
- **开发命令**:`pnpm -F docs dev:docs`
- **构建命令**:`pnpm -F docs build:docs`
- **输出目录**:`docs/docs/.vitepress/dist`
### 着陆页 (`docs-landing`)
- **目录**:`docs/landing`
- **开发命令**:`pnpm -F docs-landing dev:landing`
- **构建命令**:`pnpm -F docs-landing build:landing`
- **输出目录**:`docs/landing/dist`
### Swagger API 文档 (`docs-swagger`)
- **目录**:`docs/swagger`
- **构建命令**:`make update-swagger`
- **输出目录**:`docs/swagger`
Swagger 定义位于后端代码的 `/server` 目录中。修改 Swagger 定义后,运行构建命令将更新 Swagger 文档并在 `/ui/artalk/src/api/v2.ts` 生成 HTTP 客户端代码。
### 综合构建
- **构建所有包的命令**:`pnpm build:docs`
- **综合输出目录**:`docs/docs/.vitepress/dist`
此命令构建并组合所有三个包到单个目录中,准备发布。
### 环境变量文档
- **文件**:`docs/docs/guide/env.md`
- **更新命令**:`make update-conf-docs`
此命令读取位于 `/conf` 的配置模板文件以更新环境变量文档。在修改配置模板文件后运行此命令。
## 翻译 (i18n)
如果您编写了新功能或进行了修复/重构,请使用以下命令通过解析源代码中的 `i18n.T` 函数调用来增量生成翻译文件:
```sh
make update-i18n
```
如果您不是程序员,但希望帮助改进翻译,可以直接编辑 `/i18n` 目录中的翻译文件,然后提交 pull 请求。
## 结尾
感谢您耐心阅读本指南,并感谢您对 Artalk 的兴趣和支持。我们深知,一个开源项目的成功依赖于每一位开发者的贡献。无论是通过代码、文档、测试还是反馈,您的参与是推动项目持续进步的动力。我们诚挚邀请您加入我们,共同改进和增强 Artalk。
通过合作,我们可以创建一个更加健壮和多功能的平台,造福整个社区。您的独特见解和专业知识是无价的,只有共同努力,我们才能实现显著的进步。无论您是经验丰富的开发者,还是刚刚起步的新手,我们的项目中总有您可以贡献的一席之地。
如果您有任何问题或需要帮助,请随时在我们的 GitHub 页面上的 issue 部分提问:<https://github.com/ArtalkJS/Artalk/issues>。再次感谢您的支持,我们期待与您合作。
+28 -27
View File
@@ -1,33 +1,32 @@
# Event
# Frontend Event
## 基本事件
|事件名|描述|
|-|-|
| `created` | 初始化后 |
| `mounted` | 数据加载后 |
| `updated` | 数据更新后 |
| `unmounted` | 销毁后 |
| `list-fetch` | 评论列表请求时 |
| `list-fetched` | 评论列表请求后 |
| `list-load` | 评论装载前 |
| `list-loaded` | 评论装载后 |
| `list-failed` | 评论加载错误时 |
| `list-goto-first` | 评论列表归位时 |
| 事件名 | 描述 |
| ------------------- | -------------------- |
| `created` | 初始化后 |
| `mounted` | 数据加载后 |
| `updated` | 数据更新后 |
| `unmounted` | 销毁后 |
| `list-fetch` | 评论列表请求时 |
| `list-fetched` | 评论列表请求后 |
| `list-load` | 评论装载前 |
| `list-loaded` | 评论装载后 |
| `list-failed` | 评论加载错误时 |
| `list-goto-first` | 评论列表归位时 |
| `list-reach-bottom` | 评论列表滚动到底部时 |
| `comment-inserted` | 评论插入后 |
| `comment-updated` | 评论更新后 |
| `comment-deleted` | 评论删除后 |
| `comment-rendered` | 评论节点渲染后 |
| `notifies-updated` | 未读消息变更时 |
| `list-goto` | 评论跳转时 |
| `page-loaded` | 页面数据更新后 |
| `editor-submit` | 编辑器提交时 |
| `editor-submitted` | 编辑器提交后 |
| `user-changed` | 本地用户数据变更时 |
| `sidebar-show` | 侧边栏显示 |
| `sidebar-hide` | 侧边栏隐藏 |
| `comment-inserted` | 评论插入后 |
| `comment-updated` | 评论更新后 |
| `comment-deleted` | 评论删除后 |
| `comment-rendered` | 评论节点渲染后 |
| `notifies-updated` | 未读消息变更时 |
| `list-goto` | 评论跳转时 |
| `page-loaded` | 页面数据更新后 |
| `editor-submit` | 编辑器提交时 |
| `editor-submitted` | 编辑器提交后 |
| `user-changed` | 本地用户数据变更时 |
| `sidebar-show` | 侧边栏显示 |
| `sidebar-hide` | 侧边栏隐藏 |
事件声明代码:[@ArtalkJS/Artalk - src/types/event.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/event.ts)
@@ -42,7 +41,9 @@ artalk.on('list-loaded', () => {
## 解除事件监听
```js
let foo = function() { /* do something */ }
let foo = function () {
/* do something */
}
artalk.on('list-loaded', foo)
artalk.off('list-loaded', foo)
+7 -3
View File
@@ -14,6 +14,8 @@ npm install artalk
调用该函数将创建并得到一个 Artalk 的实例化对象,可用于后续操作。
<!-- prettier-ignore-start -->
```js
import Artalk from 'artalk'
@@ -26,6 +28,8 @@ const artalk = Artalk.init({
})
```
<!-- prettier-ignore-end -->
调用该函数会异步地向后端发起请求:
1. 获取前端配置
@@ -35,7 +39,7 @@ const artalk = Artalk.init({
评论列表加载完毕后会触发 `list-loaded` 事件。
注:前端界面配置可能会被覆盖,详情见:[在后端控制前端](../guide/backend/fe-control.md)。
> 注:前端界面配置可能会被覆盖,详情见:[界面配置](../guide/frontend/config.md)。
## 释放资源 `destroy`
@@ -145,7 +149,7 @@ Artalk.use((ctx) => {
const artalk = Artalk.init({ ... })
```
详情见:[插件开发](./plugs.md)
详情见:[插件开发](./plugin.md)
## 夜间模式 `setDarkMode`
@@ -162,7 +166,7 @@ artalk.setDarkMode(true)
```js
const artalk = Artalk.init({
// ...其他配置
darkMode: 'auto',
darkMode: 'auto',
})
```
+175
View File
@@ -0,0 +1,175 @@
# 置入博客
## 通用方法
<<< @/code/quick-start/cdn.html
#### 什么时候执行 `Artalk.init({})`?
- 可以在任意位置引入 JS 和 CSS 资源,但需确保 JS 引入在执行 `Artalk.init({})` 前。
- 执行 `Artalk.init({ el: '#artalk' })` 前需要确保 `<div id="artalk"></div>` 在页面当中。
## Hugo
创建模板文件 `/主题目录/layouts/partials/comment/artalk.html`:
<!-- prettier-ignore-start -->
```html
<link href="/lib/artalk/Artalk.css" rel="stylesheet" />
<script src="/lib/artalk/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments',
pageKey: '{{ .Permalink }}',
pageTitle: '{{ .Title }}',
server: '{{ $.Site.Params.artalk.server }}',
site: '{{ $.Site.Params.artalk.site }}',
// ...你的其他配置
})
</script>
```
<!-- prettier-ignore-end -->
文章页模板 `/主题目录/layouts/_default/single.html` 合适的位置添加:
```html
<div class="article-comments">{{- partial "comment/artalk" . -}}</div>
```
修改 Hugo 配置文件:
::: code-group
```toml [config.toml]
[params.artalk]
server = 'https://artalk.example.org'
site = '你的站点名'
```
```yaml [config.yaml]
params:
artalk:
server: 'https://artalk.example.org'
site: '你的站点名'
```
:::
## Hexo
创建 `/主题目录/layout/comment/artalk.ejs`:
```html
<link href="/lib/artalk/Artalk.css" rel="stylesheet" />
<script src="/lib/artalk/Artalk.js"></script>
<div id="Comments"></div>
<script>
var artalk = Artalk.init({
el: '#Comments',
pageKey: '<%= page.permalink %>',
pageTitle: '<%= page.title %>',
server: '<%= theme.comment.artalk.server %>',
site: '<%= theme.comment.artalk.site %>',
})
</script>
```
修改文章模板文件,例如 `/主题目录/layout/post.ejs`:
```html
<div class="article-comments"><%- partial('comment/artalk') %></div>
```
编辑主题配置 `/主题目录/_config.example.yml`:
```yaml
comment:
artalk:
site: '你的站点名'
server: 'https://artalk.example.org'
```
::: tip
NexT 主题可以安装 [Hexo NexT 主题的 Artalk 插件](https://github.com/leirock/hexo-next-artalk)
:::
## VitePress
可参考:[docs/.vitepress](https://github.com/ArtalkJS/Artalk/tree/master/docs/docs/.vitepress)
- `config.ts` 修改配置引入 CSS 资源
- `theme/Artalk.vue` 创建组件
- `theme/index.ts` 注册组件
- `theme/Layout.vue` 使用组件
参考代码:[docs/.vitepress/theme/Artalk.vue](https://github.com/ArtalkJS/Artalk/blob/master/docs/docs/.vitepress/theme/Artalk.vue)
## VuePress
(待补充)
::: tip 提示
可参考:[置入框架](./import-framework.md)
:::
## Typecho
修改主题文章模板文件,例如 `post.php`:
```php
<!-- CSS -->
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<!-- JS -->
<script src="/lib/artalk/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments',
pageKey: '<?php $this->permalink() ?>',
pageTitle: '<?php $this->title() ?>',
server: '<后端地址>',
site: '<?php $this->options->title() ?>',
// ...你的其他配置
})
</script>
```
## WordPress
修改主题文章模板文件,例如 `single.php`:
```php
<!-- CSS -->
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<!-- JS -->
<script src="/lib/artalk/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments',
pageKey: '<?= addslashes(get_permalink()) ?>',
pageTitle: '<?= addslashes(get_the_title()) ?>',
server: '<后端地址>',
site: '<?= addslashes(get_bloginfo('name')) ?>',
// ...你的其他配置
})
</script>
```
+227
View File
@@ -0,0 +1,227 @@
# 置入框架
## 安装 Artalk
通过包管理工具引入 Artalk,推荐使用 [pnpm](https://pnpm.io/zh/)
```bash
pnpm add artalk
```
## Vue
::: code-group
```vue [Vue 3]
<script lang="ts" setup>
import Artalk from 'artalk'
import { onMounted, onBeforeUnmount, ref } from 'vue'
import 'artalk/dist/Artalk.css'
const el = ref<HTMLElement>()
let artalk: Artalk
onMounted(() => {
artalk = Artalk.init({
el: el.value,
pageKey: location.pathname,
pageTitle: `${document.title}`,
server: 'http://localhost:8080',
site: 'Artalk 的博客',
// ...
})
})
onBeforeUnmount(() => {
artalk.destroy()
})
</script>
<template>
<view ref="el"></view>
</template>
```
```vue [Vue 3 + Vue Router]
<script lang="ts" setup>
import Artalk from 'artalk'
import { onMounted, onBeforeUnmount, ref, watch, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import 'artalk/dist/Artalk.css'
const el = ref<HTMLElement>()
const router = useRouter()
let artalk: Artalk
onMounted(() => {
artalk = Artalk.init({
el: el.value,
pageKey: router.route.path,
pageTitle: document.title,
server: 'http://localhost:8080',
site: 'Artalk 的博客',
// ...
})
})
watch(
() => router.route.path,
(path) => {
nextTick(() => {
artalk.update({
pageKey: path,
pageTitle: document.title,
})
artalk.reload()
})
}
)
onBeforeUnmount(() => {
artalk.destroy()
})
</script>
<template>
<view ref="el"></view>
</template>
```
:::
## 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<HTMLDivElement>(null)
const location = useLocation()
const artalk = useRef<Artalk>()
useEffect(() => {
artalk.current = Artalk.init({
el: container.current!,
pageKey: location.pathname,
pageTitle: document.title,
server: 'http://localhost:8080',
site: 'Artalk 的博客',
// ...
})
return () => {
artalk.current?.destroy()
}
}, [container, location.pathname])
return <div ref={container}></div>
}
export default ArtalkComment
```
```jsx [React Class]
import React, { createRef } from 'react'
import 'artalk/dist/Artalk.css'
import Artalk from 'artalk'
export default class Artalk 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 的博客',
// ...
})
}
componentWillUnmount() {
this.artalk?.destroy()
}
render() {
return <div ref={this.el} />
}
}
```
:::
## 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 的博客',
// ...
})
onCleanup(() => {
artalk.destroy()
})
})
return <div ref={el} />
}
```
## Svelte
```html
<script>
import Artalk from 'artalk'
import { onMount, onDestroy } from 'svelte'
import 'artalk/dist/Artalk.css'
let el
let artalk
onMount(() => {
artalk = Artalk.init({
el: el,
pageKey: location.pathname,
pageTitle: document.title,
server: 'http://localhost:8080',
site: 'Artalk 的博客',
// ...
})
onDestroy(() => {
if (artalk) {
artalk.destroy()
}
})
})
</script>
<div bind:this="{el}"></div>
```
+28 -17
View File
@@ -1,28 +1,39 @@
# 开发说明
# 开发文档
## 参考资源
欢迎来到 Artalk 官方开发文档,这里提供了构建 Artalk 插件和主题的指南。如果你需要搭建 Artalk 的开发环境,可以阅读 [开发者贡献指南](./contributing.md)。
📖 <a href="https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md" target="_blank">开发者贡献指南 (CONTRIBUTING.md)</a>
感谢对 Artalk 的关注和支持。我们深知开源项目的成功离不开每一位开发者的贡献,无论是代码、文档、测试还是意见反馈,您的参与都是推动项目不断前进的动力。诚挚地邀请您加入我们,共同完善和提升 Artalk。
🔬 <a href="/http-api.html" target="_blank">HTTP API 文档 (OpenAPI)</a>
## 索引
🔖 <a href="https://github.com/ArtalkJS/Artalk/blob/master/CODE_OF_CONDUCT.md" target="_blank">贡献者契约行为准则 (CODE_OF_CONDUCT.md)</a>
- [开发者贡献指南](./contributing.md) ⭐️
**前端界面**
## 配置文档
- [后端配置](../guide/backend/config.md)
- [置入博客](./import-blog.md)
- [置入框架](./import-framework.md)
- [前端 API 文档](./fe-api.md)
- [前端 Event](./event.md)
- [前端配置](../guide/frontend/config.md)
## 补充说明
**插件开发**
由于 Artalk 正处于开发阶段,使用此文档中 `API`、`Event` 前请务必检查时效性。
- [插件开发](./plugin.md)
- [插件开发 Vite 集成](https://github.com/ArtalkJS/Artalk/blob/master/ui/plugin-kit/README.md)
- `API` 部分参考源码
* [@ArtalkJS/Artalk - src/api/](https://github.com/ArtalkJS/Artalk/tree/master/ui/artalk/src/api)
* [@ArtalkJS/Artalk - server/server.go](https://github.com/ArtalkJS/Artalk/blob/master/server/server.go)
- `UI` 及 `Event` 部分参考源码
* [@ArtalkJS/Artalk - src/artalk.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/artalk.ts)
* [@ArtalkJS/Artalk - src/types/event.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/event.ts)
**后端程序**
通过 Artalk 提供的 `API` 和 `Event`,你可以实现很多高级功能,比如编写评论管理机器人、评论提醒推送插件等。Artalk 并不为此提供技术指导,但鼓励你参考此处的文档自行定制。
- <a href="/http-api.html" target="_blank">HTTP API 文档</a>
- [环境变量](../guide/env.md)
- [配置文件](../guide/backend/config.md)
**其他内容**
- [兼容性](../develop/compatibility.md)
- [更新日志](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md)
- [i18n 多语言贡献指南](../guide/frontend/i18n.md#贡献翻译)
- [贡献者契约行为准则](https://github.com/ArtalkJS/Artalk/blob/master/CODE_OF_CONDUCT.md)
::: tip
Artalk 正处于积极维护阶段,请注意 API 版本兼容性。升级可能有突破性变更参考 [更新日志](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md)。
:::
+130
View File
@@ -0,0 +1,130 @@
# 插件开发
## 使用 Vite 开发
我们提供了 Vite 的集成插件,使用 Vite 开发能够开箱即用地构建 Artalk 插件,简化 Vite 配置。
参考文档:[@artalk/plugin-kit](https://github.com/ArtalkJS/Artalk/blob/master/ui/plugin-kit/README.md)。
同时,我们提供了一个模版代码仓库,你可以直接 fork 来开发插件:[artalk-plugin-sample](https://github.com/ArtalkJS/artalk-plugin-sample)。
通过 Vite 结合前端生态,你可以任选你喜欢的技术栈,如 Vue、React、Svelte、SolidJS 等框架开发 Artalk 插件。
## `Artalk.use`
使用 `Artalk.use` 来扩展 Artalk。
```js
import Artalk from 'artalk'
Artalk.use((ctx) => {
ctx.on('list-loaded', () => {
console.log('评论列表加载完毕')
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 实例被挂载')
})
ctx.on('unmounted', () => {
el.remove()
console.log('Artalk 实例被销毁')
})
})
const artalk = Artalk.init({ ... })
```
请注意:
- `Artalk.use` 必须在 `Artalk.init` 之前调用才生效。
- 请勿依赖插件的加载顺序,请监听事件来执行插件逻辑。
- 当所有的插件加载完毕后,会触发 `created` 事件。
- 当插件和配置加载完毕后,会触发 `mounted` 事件。
- 当 Artalk 实例被销毁时,会触发 `unmounted` 事件。
- 当配置发生变化时,会触发 `updated` 事件。
在 use 函数中,你可以通过 `ctx` 来访问 Artalk 的 Context 对象。
### 插件可配置选项
在 TypeScript 中,你可以通过 `ArtalkPlugin<T>` 来定义一个带选项的插件类型。
```ts
export interface DemoPluginOptions {
foo?: string
}
export const ArtalkDemoPlugin: ArtalkPlugin<DemoPluginOptions> = (ctx, options = {}) => {
console.log(options.foo)
}
```
在执行 `Artalk.use` 时,传入选项:
```ts
import { ArtalkDemoPlugin } from 'artalk-plugin-demo'
Artalk.use(ArtalkDemoPlugin, { foo: 'bar' })
```
## ContextAPI
Context 对象包含了 Artalk 的上下文信息。
| 成员 | 说明 |
| --------------------- | -------------------- |
| `ctx.getEl` | 获取容器元素 |
| `ctx.getConf` | 获取配置 |
| `ctx.updateConf` | 更新配置 |
| `ctx.watchConf` | 监听配置 |
| `ctx.setDarkMode` | 设置夜间模式 |
| `ctx.getApi` | 获取 API 客户端对象 |
| -- | -- |
| `ctx.fetch` | 获取评论数据 |
| `ctx.reload` | 重载评论列表 |
| `ctx.getComments` | 获取所有评论数据对象 |
| `ctx.getCommentNodes` | 获取所有评论节点对象 |
| -- | -- |
| `ctx.on` | 添加事件监听 |
| `ctx.off` | 解除事件监听 |
| `ctx.trigger` | 触发事件 |
| -- | -- |
| `ctx.get` | 获取依赖 |
| `ctx.inject` | 注入依赖 |
::: warning
Context API 目前仍不稳定,开发可能会有变动,升级请关注 CHANGELOG。
:::
参考:[@artalk/src/types/context.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/context.ts)
Artalk 包含完整的 TypeScript 类型定义,你可以通过编辑器的自动补全来查看 API。
## 示例插件
以下为 Artalk 官方维护的外置插件列表:
| 插件 | 说明 |
| -------------------------------------------------------------------------------------------- | -------------- |
| [artalk-plugin-sample](https://github.com/ArtalkJS/artalk-plugin-sample) | 示例插件 |
| [@artalk/plugin-katex](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-katex) | LaTeX 公式插件 |
| [@artalk/plugin-auth](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-auth) | Auth 插件 (SolidJS) |
| [@artalk/plugin-lightbox](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-lightbox) | 图片灯箱基础插件 |
同时 Artalk 内部也有很多插件的实现,你可以参考源码来开发插件:
[@ArtalkJS/Artalk - src/plugins](https://github.com/ArtalkJS/Artalk/tree/master/ui/artalk/src/plugins)
## 后端插件开发
【TODO】
+4 -87
View File
@@ -1,90 +1,7 @@
# 插件开发
使用 `Artalk.use` 来扩展 Artalk。
本页面内容已移动至 <https://artalk.js.org/develop/plugin.html>。
```js
import Artalk from 'artalk'
Artalk.use((ctx) => {
ctx.on('list-loaded', () => {
console.log('评论列表加载完毕')
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 实例被挂载')
})
ctx.on('unmounted', () => {
el.remove()
console.log('Artalk 实例被销毁')
})
})
const artalk = Artalk.init({ ... })
```
请注意:
- `Artalk.use` 必须在 `Artalk.init` 之前调用才生效。
- 请勿依赖插件的加载顺序,请监听事件来执行插件逻辑。
- 当所有的插件加载完毕后,会触发 `created` 事件。
- 当插件和配置加载完毕后,会触发 `mounted` 事件。
- 当 Artalk 实例被销毁时,会触发 `unmounted` 事件。
- 当配置发生变化时,会触发 `updated` 事件。
在 use 函数中,你可以通过 `ctx` 来访问 Artalk 的 Context 对象。
## Context
Context 对象包含了 Artalk 的上下文信息。
| 成员 | 说明 |
| --- | --- |
| `ctx.getEl` | 获取容器元素 |
| `ctx.getConf` | 获取配置 |
| `ctx.updateConf` | 更新配置 |
| `ctx.watchConf` | 监听配置 |
| `ctx.setDarkMode` | 设置夜间模式 |
| `ctx.getApi` | 获取 API 客户端对象 |
|--|--|
| `ctx.fetch` | 获取评论数据 |
| `ctx.reload` | 重载评论列表 |
| `ctx.getComments` | 获取所有评论数据对象 |
| `ctx.getCommentNodes` | 获取所有评论节点对象 |
|--|--|
| `ctx.on` | 添加事件监听 |
| `ctx.off` | 解除事件监听 |
| `ctx.trigger` | 触发事件 |
|--|--|
| `ctx.get` | 获取依赖 |
| `ctx.inject` | 注入依赖 |
::: warning
Context API 目前仍不稳定,开发可能会有变动,升级请关注 CHANGELOG。
:::
参考:[@artalk/src/types/context.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/context.ts)
Artalk 包含完整的 TypeScript 类型定义,你可以通过编辑器的自动补全来查看 API。
## 示例插件
Artalk 有很多内置的插件,你可以参考它们的源码来开发自己的插件。
[@ArtalkJS/Artalk - src/plugins](https://github.com/ArtalkJS/Artalk/tree/master/ui/artalk/src/plugins)
我们还提供了一些外置的插件,同样可以参考:
| 插件 | 说明 |
| --- | --- |
| [@artalk/plugin-katex](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-katex) | LaTeX 公式插件 |
| [@artalk/plugin-lightbox](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-lightbox) | 图片灯箱插件 |
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/develop/plugin.html';
</script>
+1 -11
View File
@@ -1,17 +1,7 @@
# 🥬 关于我们
## ~~开发团队~~有人想自我介绍一下
## ~~开发团队有人想自我介绍一下~~
[@qwqcode](https://github.com/qwqcode):🥬 + 🦜
P.S. 因为侧边栏太空了,也许。所以,不知道放点什么好。被迫写了个关于页面。
## 团队成员
<sub style="text-align: center">ohhhh<span data-msg="Artalk 期待你的加入!" data-please-email="qwqcode@gmail.com" style="color:#55555;background:linear-gradient(45deg,#ff0000 0%,#ffb600 11%,#fff600 22%,#a5ff00 33%,#00a9ff 44%,#0400ff 55%,#8a00fc 66%,#ff00e9 77%,#ff0059 88%,#ff0000 100%);font-weight: bold;border-radius: 555px;">hhh.</span></sub>
The Artalk. Made with <span style="color: red;">♥️</span>.
## 关于本站
该站点通过 [Netlify](https://www.netlify.com/) 对 [Docs](https://github.com/ArtalkJS/Artalk/tree/master/docs) 目录进行自动部署。
+71 -74
View File
@@ -4,7 +4,7 @@ Artalk 支持通过多元推送功能以多种方式发送管理员通知。
支持 **Telegram**、**飞书**、**钉钉**、**Bark**、**Slack**、**LINE**,并且多种方式可以同时启用。
你可以在[控制中心](/guide/frontend/sidebar.md#控制中心)找到「设置」界面修改此配置。
你可以在 [控制中心](/guide/frontend/sidebar.md#设置) 的设置界面修改此配置,也可以通过 [配置文件](/guide/backend/config.md#多元推送-admin-notify) 或 [环境变量](/guide/env.md#多元推送) 进行配置。
## 配置文件
@@ -16,50 +16,50 @@ Artalk 支持通过多元推送功能以多种方式发送管理员通知。
# 多元推送
admin_notify:
# 通知模版
notify_tpl: "default"
notify_tpl: default
noise_mode: false
# 邮件通知管理员
email:
enabled: true # 当使用其他推送方式时,可以关闭管理员邮件通知
mail_subject: "[{{site_name}}] 您的文章「{{page_title}}」有新回复"
mail_tpl: ""
mail_subject: '[{{site_name}}] 您的文章「{{page_title}}」有新回复'
mail_tpl: ''
# Telegram
telegram:
enabled: false
api_token: ""
api_token: ''
receivers:
- 7777777
# 飞书
lark:
enabled: false
webhook_url: ""
webhook_url: ''
# 钉钉
ding_talk:
enabled: false
token: ""
secret: ""
token: ''
secret: ''
# Bark
bark:
enabled: false
server: "http://day.app/xxxxxxx/"
server: http://day.app/xxxxxxx/
# Slack
slack:
enabled: false
oauth_token: ""
oauth_token: ''
receivers:
- "CHANNEL_ID"
- CHANNEL_ID
# LINE
line:
enabled: false
channel_secret: ""
channel_access_token: ""
channel_secret: ''
channel_access_token: ''
receivers:
- "USER_ID_1"
- "GROUP_ID_1"
- USER_ID_1
- GROUP_ID_1
# WebHook
webhook:
enabled: false
url: ""
url: ''
```
:::
@@ -71,8 +71,8 @@ admin_notify:
```yaml
admin_notify:
enabled: true # 当使用其他推送方式时,可以关闭管理员邮件通知
mail_subject: "[{{site_name}}] 您的文章「{{page_title}}」有新回复"
mail_tpl: ""
mail_subject: '[{{site_name}}] 您的文章「{{page_title}}」有新回复'
mail_tpl: ''
```
当使用其他推送方式时,可以关闭管理员邮件通知。
@@ -83,7 +83,7 @@ admin_notify:
- 配置项 `mail_subject` 为发送给管理员的邮件标题。
- 配置项 `mail_tpl` 为发送给管理员的邮件选用特定的[邮件模板](./email.md#邮件模板)(填写邮件模板文件路径)。
(当该项留空时,将继承 `email.mail_tpl` 配置项)
## Telegram
@@ -93,7 +93,7 @@ admin_notify:
# Telegram
telegram:
enabled: true
api_token: ""
api_token: ''
receivers:
- 7777777
```
@@ -132,7 +132,7 @@ admin_notify:
# 飞书
lark:
enabled: true
webhook_url: ""
webhook_url: ''
```
- `webhook_url`:填入创建群组机器人时得到的 WebHook 地址。
@@ -160,8 +160,8 @@ admin_notify:
# 钉钉
ding_talk:
enabled: true
token: ""
secret: ""
token: ''
secret: ''
```
可参考:[钉钉开放文档](https://open.dingtalk.com/document/robots/custom-robot-access)
@@ -173,17 +173,15 @@ admin_notify:
# Bark
bark:
enabled: true
server: "http://day.app/xxxxxxx/"
server: http://day.app/xxxxxxx/
```
[Bark](https://github.com/Finb/Bark) 是一款开源的 iOS App,并且[支持自托管](https://github.com/Finb/bark-server),你能使用 Bark 轻松地推送消息给你的 iOS 设备。
你可以在 App Store 搜索下载,并获得需要填入 Artalk 的 `server` 配置项:
<img src="/images/notify/bark.png" width="700px">
## Slack
```yaml
@@ -191,9 +189,9 @@ admin_notify:
# Slack
slack:
enabled: true
oauth_token: ""
oauth_token: ''
receivers:
- "CHANNEL_ID"
- CHANNEL_ID
```
## LINE
@@ -203,18 +201,18 @@ admin_notify:
# LINE
line:
enabled: true
channel_secret: ""
channel_access_token: ""
channel_secret: ''
channel_access_token: ''
receivers:
- "USER_ID_1"
- "GROUP_ID_1"
- USER_ID_1
- GROUP_ID_1
```
## 通知模版
```yaml
admin_notify:
notify_tpl: "default"
notify_tpl: default
```
配置项 `admin_notify.notify_tpl` 可设置为自定义通知模版「文件路径」,默认的通知模版为:
@@ -259,21 +257,21 @@ admin_notify:
```yaml
admin_notify:
webhook:
enabled: true
url: "http://localhost:8080/"
webhook:
enabled: true
url: http://localhost:8080/
```
**Body 数据内容**
`application/json` 类型
|Key|描述|类型|备注|
| - | - | - | - |
|`notify_subject`|通知标题 |String| 对应 admin_notify.notify_subject 配置项 |
|`notify_body` |通知内容 |String| 根据 admin_notify.notify_tpl 模版渲染 |
|`comment` |评论内容 |Object| 新创建的评论数据对象 |
|`parent_comment`|评论回复的目标|Object| 如果是根节点评论值为 null |
| Key | 描述 | 类型 | 备注 |
| ---------------- | -------------- | ------ | --------------------------------------- |
| `notify_subject` | 通知标题 | String | 对应 admin_notify.notify_subject 配置项 |
| `notify_body` | 通知内容 | String | 根据 admin_notify.notify_tpl 模版渲染 |
| `comment` | 评论内容 | Object | 新创建的评论数据对象 |
| `parent_comment` | 评论回复的目标 | Object | 如果是根节点评论值为 null |
**Body 数据样本**
@@ -311,53 +309,53 @@ admin_notify:
**Node.js express 处理示例**
```js
const express = require('express');
const express = require('express')
const app = express();
const app = express()
app.use(express.json()); // Use JSON middleware
app.use(express.json()) // Use JSON middleware
app.post('/', function(request, response){
console.log(request.body);
app.post('/', (request, response) => {
console.log(request.body)
const notifySubject = request.body.notify_subject
const notifyBody = request.body.notify_body
console.log(notifySubject, notifyBody);
const notifyBody = request.body.notify_body
console.log(notifySubject, notifyBody)
response.send(request.body);
});
response.send(request.body)
})
app.listen(8080);
app.listen(8080)
```
**Node.js http 处理示例**
```js
const http = require("http");
const http = require('http')
const requestListener = function (req, res) {
const requestListener = (req, res) => {
// receive json request
let body = "";
req.on("data", function (data) {
body += data;
});
req.on("end", function () {
let json = "";
let body = ''
req.on('data', (data) => {
body += data
})
req.on('end', () => {
let json = ''
try {
json = JSON.parse(body);
json = JSON.parse(body)
} catch {}
// do something with json
console.log(json);
res.end();
});
console.log(json)
res.end()
})
res.writeHead(200);
res.end("Hello, World!");
};
res.writeHead(200)
res.end('Hello, World!')
}
const server = http.createServer(requestListener);
server.listen(8080);
const server = http.createServer(requestListener)
server.listen(8080)
```
**PHP Laravel 处理示例**
@@ -382,10 +380,10 @@ import (
)
type ArtalkNotify struct {
NotifySubject string `json:"notify_subject"`
NotifyBody string `json:"notify_body"`
Comment interface{} `json:"comment"`
ParentComment interface{} `json:"parent_comment"`
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) {
@@ -403,4 +401,3 @@ func main() {
log.Fatal(http.ListenAndServe(":8080", nil))
}
```
+4 -64
View File
@@ -1,67 +1,7 @@
# 后端构建
## 编译运行
本页面内容已移动至 <https://artalk.js.org/develop/contributing.html>。
```bash
# 拉取代码
git clone https://github.com/ArtalkJS/Artalk.git Artalk
# 编译程序
cd Artalk && make all
# 配置文件
cp conf/artalk.example.yml artalk.yml
vim artalk.yml
# 运行程序
./bin/artalk help
./bin/artalk -c artalk.yml server
```
## 构建二进制文件
```bash
# 拉取代码
git clone https://github.com/ArtalkJS/Artalk.git
# 执行编译
make all
```
编译二进制文件将会输出到 `bin` 目录中
## Docker Compose 编译运行
```bash
# 拉取代码
git clone https://github.com/ArtalkJS/Artalk
cd Artalk
# 构建镜像
docker-compose build
# 运行
docker-compose up -d
```
## Docker 镜像构建
```bash
# 拉取代码
git clone https://github.com/ArtalkJS/Artalk
cd Artalk
# 构建镜像
make docker-docker
# 发布镜像
make docker-push
```
## DevOps
程序由 [GitHub Actions](https://github.com/ArtalkJS/Artalk/actions) 自动化构建
|版本发布|Docker 镜像构建发布|二进制构建发布|前端构建发布|
|-|-|-|-|
|[![Release](https://github.com/ArtalkJS/Artalk/actions/workflows/release.yml/badge.svg?branch=master)](https://github.com/ArtalkJS/Artalk/actions/workflows/release.yml)|[![Build Docker](https://github.com/ArtalkJS/Artalk/actions/workflows/build-docker.yml/badge.svg)](https://github.com/ArtalkJS/Artalk/actions/workflows/build-docker.yml)|[![Release](https://github.com/ArtalkJS/Artalk/actions/workflows/build-app.yml/badge.svg?branch=master)](https://github.com/ArtalkJS/Artalk/actions/workflows/build-app.yml)|[![Release](https://github.com/ArtalkJS/Artalk/actions/workflows/build-frontend.yml/badge.svg?branch=master)](https://github.com/ArtalkJS/Artalk/actions/workflows/build-frontend.yml)|
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/develop/contributing.html';
</script>
+28 -29
View File
@@ -6,7 +6,7 @@ Artalk 内置图片验证码功能,你可以配置操作频率限制,当超
目前 Artalk 支持:Turnstile、reCAPTCHA、hCaptcha、极验。
你可以在[控制中心](/guide/frontend/sidebar.md#控制中心)找到「设置」界面修改此配置。
你可以在 [控制中心](/guide/frontend/sidebar.md#设置) 的设置界面修改此配置,也可以通过 [配置文件](/guide/backend/config.md#验证码-captcha) 或 [环境变量](/guide/env.md#验证码) 进行配置。
## 配置文件
@@ -15,29 +15,29 @@ Artalk 内置图片验证码功能,你可以配置操作频率限制,当超
```yaml
# 验证码
captcha:
enabled: true # 总开关
always: false # 总是需要验证码
captcha_type: "image" # 验证码类型
action_limit: 3 # 激活验证码所需操作次数
enabled: true # 总开关
always: false # 总是需要验证码
captcha_type: image # 验证码类型
action_limit: 3 # 激活验证码所需操作次数
action_reset: 60 # 重置操作计数器超时 (单位:s, 设为 -1 不重置)
# Turnstile
# (https://www.cloudflare.com/products/turnstile/)
turnstile:
site_key: ""
secret_key: ""
site_key: ''
secret_key: ''
# reCaptcha
# (https://www.google.com/recaptcha/about/)
recaptcha:
site_key: ""
secret_key: ""
site_key: ''
secret_key: ''
# hCaptcha (https://www.hcaptcha.com/)
hcaptcha:
site_key: ""
secret_key: ""
site_key: ''
secret_key: ''
# Geetest 极验 (https://www.geetest.com)
geetest:
captcha_id: ""
captcha_key: ""
captcha_id: ''
captcha_key: ''
```
- **always**:当该项为 `true` 时,总是需要输入验证码。
@@ -49,7 +49,7 @@ captcha:
## 配置举例
#### 例 1
### 例 1
在 60s 时间范围内,当操作次数超过 3 次,将一直被要求输入验证码:
@@ -61,7 +61,7 @@ captcha:
在 60s 后将自动重置计数器,即重新获得 3 次不用输入验证码的机会。
#### 例 2
### 例 2
无论多少时间范围内,这个 IP 地址操作次数只要超过 5 次时,将一直被要求输入验证码:
@@ -71,7 +71,7 @@ captcha:
action_reset: -1
```
#### 例 3
### 例 3
总是要求输入验证码,无论这个 IP 操作多少次:
@@ -99,10 +99,10 @@ captcha:
```yaml
captcha:
# 省略其他配置...
captcha_type: "turnstile"
captcha_type: turnstile
turnstile:
site_key: ""
secret_key: ""
site_key: ''
secret_key: ''
```
## reCAPTCHA
@@ -114,10 +114,10 @@ captcha:
```yaml
captcha:
# 省略其他配置...
captcha_type: "recaptcha"
captcha_type: recaptcha
recaptcha:
site_key: ""
secret_key: ""
site_key: ''
secret_key: ''
```
注:国内访问 Google API 也许需要配置系统代理。
@@ -133,10 +133,10 @@ reCAPTCHA 官方提供了用于测试的 Keys:[可见此处](https://developer
```yaml
captcha:
# 省略其他配置...
captcha_type: "hcaptcha"
captcha_type: hcaptcha
hcaptcha:
site_key: ""
secret_key: ""
site_key: ''
secret_key: ''
```
hCaptcha 官方提供了用于测试的 Keys:[可见此处](https://docs.hcaptcha.com/#integration-testing-test-keys)。
@@ -152,9 +152,8 @@ Artalk 支持接入 [Geetest 极验](https://www.geetest.com/adaptive-captcha)
```yaml
captcha:
# 省略其他配置...
captcha_type: "geetest"
captcha_type: geetest
geetest:
captcha_id: ""
captcha_key: ""
captcha_id: ''
captcha_key: ''
```
+83 -76
View File
@@ -1,9 +1,13 @@
# 后端配置
# 配置文件
## 轻松配置
推荐在侧边栏 “[控制中心](/guide/frontend/sidebar.md)” 通过图形界面修改配置,无需手动编辑配置文件。
## 环境变量
可通过环境变量配置,参考文档:[环境变量](../env.md)。
## 指定配置文件路径
Artalk 默认以工作目录下的 `artalk.yml` 作为配置文件,可使用参数 `-c` 来指定具体文件:
@@ -12,30 +16,11 @@ Artalk 默认以工作目录下的 `artalk.yml` 作为配置文件,可使用
artalk -c ./conf.yml
```
## 通过环境变量配置
Artalk 读取以 `ATK_` 为前缀的环境变量,并且全部大写,子节点用单个下划线表示,配置名含下划线请用双下划线表示:
- `_` (单下划线) 转为 `.` 表示子节点
- `__` (双下划线) 转为 `_` 表示配置名的下划线
e.g.
```bash
ATK_TIMEZONE -> timezone
ATK_LOGIN__TIMEOUT -> login_timeout
ATK_SITE__DEFAULT -> site_default
ATK_DB_TYPE -> db.type
ATK_DB_TABLE__PREFIX -> db.table_prefix
ATK_CACHE_REDIS_USERNAME -> cache.redis.username
ATK_ADMIN_USERS_0_NAME -> admin_users[0].name
```
## 获取模版配置文件
可参考一份「完整的配置文件」:[artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/blob/master/conf/artalk.example.zh-CN.yml)
#### 使用 gen 命令生成配置文件
### 使用 gen 命令生成配置文件
Artalk 提供 `gen` 命令,你可以快速生成一份新的配置文件:
@@ -43,7 +28,7 @@ Artalk 提供 `gen` 命令,你可以快速生成一份新的配置文件:
artalk gen conf -lang zh-CN ./artalk.yml
```
#### 命令行下载配置文件
### 命令行下载配置文件
```bash
wget -O artalk.yml https://raw.githubusercontent.com/ArtalkJS/Artalk/master/conf/artalk.example.zh-CN.yml
@@ -54,7 +39,7 @@ wget -O artalk.yml https://raw.githubusercontent.com/ArtalkJS/Artalk/master/conf
在 Artalk 启动之前,你需要配置一个 `app_key` 用于对网站内容进行安全加密:
```yaml
app_key: "<任意的字符>"
app_key: <任意的字符>
```
## 语言 `locale`
@@ -62,7 +47,7 @@ app_key: "<任意的字符>"
设置 Artalk 的语言。遵循 Unicode BCP 47 规范,该项默认为 "zh-CN" (简体中文)。
```yml
locale: "zh-CN"
locale: zh-CN
```
详情参考:[多语言](../frontend/i18n.md)
@@ -77,8 +62,8 @@ SQLite 是轻型数据库,使用单个文件存储数据,无需额外运行
```yaml
db:
type: "sqlite"
file: "./data/artalk.db"
type: sqlite
file: ./data/artalk.db
```
#### MySQL / PostgreSQL / SQL Server
@@ -87,15 +72,15 @@ db:
```yaml
db:
type: "mysql" # sqlite, mysql, pgsql, mssql
name: "artalk" # 数据库名
host: "localhost" # 地址
port: "3306" # 端口
user: "root" # 账号
password: "" # 密码
charset: "utf8mb4" # 编码格式
table_prefix: "" # 表前缀 (例如:"atk_")
ssl: false # 启用 SSL
type: mysql # sqlite, mysql, pgsql, mssql
name: artalk # 数据库名
host: localhost # 地址
port: 3306 # 端口
user: root # 账号
password: '' # 密码
charset: utf8mb4 # 编码格式
table_prefix: '' # 表前缀 (例如:"atk_")
ssl: false # 启用 SSL
prepare_stmt: true # 预编译语句
```
@@ -107,12 +92,22 @@ db:
```yaml
db:
type: "mysql"
dsn: "mysql://myuser:mypassword@localhost:3306/mydatabase?tls=skip-verify"
type: mysql
dsn: mysql://myuser:mypassword@localhost:3306/mydatabase?tls=skip-verify
```
更多内容参考:[@go-sql-driver/mysql:README.md](https://github.com/go-sql-driver/mysql)
## 服务器 `http`
```yaml
http:
# 请求体大小限制 (单位:MB)
body_limit: 100
# 代理标头名 (当使用 CDN 时填写 `X-Forwarded-For` 获取用户真实 IP)
proxy_header: ""
```
## 管理员 `admin_users`
你需要配置管理员账户,这样才能通过「[控制中心](../frontend/sidebar.md)」对站点内容进行管理。
@@ -125,61 +120,65 @@ Artalk 支持多站点,你可以创建多个管理员账户,为其分配站
```yaml
trusted_domains:
- "https://前端使用域名A.com"
- "https://前端使用域名B.com"
- https://前端使用域名A.com
- https://前端使用域名B.com
```
配置该项能限制来自列表外的 Referer 和跨域请求。
仅允许列表中的域名访问后端 API,限制来自列表外的域名跨域请求。
:::tip
你需要将「使用该后端的前端」URL 地址加入可信域名列表中,
你需要将「前端页面」的 URL 地址加入可信域名列表中,
若非默认 80/443 端口需额外附带端口号,例如:`https://example.com:8080`
:::
在侧边栏[控制中心](../frontend/sidebar.md#控制中心)「站点」选项卡 - 选择站点「修改 URL」,填入站点 URL 也具有相同的效果;添加多个 URL 可使用 `","` 英文逗号分隔,修改后请重启 Artalk。
在侧边栏 [控制中心](../frontend/sidebar.md#控制中心) 的「站点」选项卡 - 选择站点「修改 URL」,填入站点 URL 也具有相同的设置效果;添加多个 URL 可使用 `,` 英文逗号分隔,修改后请手动重启 Artalk。
可以将其关闭:
默认站点地址 `ATK_SITE_URL` 配置项也会被自动加入可信域名列表。
```yaml
trusted_domains:
- "*"
另外,你也可以在启动时通过环境变量 `ATK_TRUSTED_DOMAINS` 来配置可信域名,例如:
```bash
ATK_TRUSTED_DOMAINS="https://a.com https://b.org" artalk server
```
::: danger
请注意,环境变量将覆盖配置文件中的设置。
但并不建议这样做,关闭后将存在潜在安全风险,例如可能遭受 CSRF 跨域攻击。
:::
细节:`trusted_domains` 配置项实际上是对响应标头:
- `Access-Control-Allow-Origin` 的控制 (参考:[W3C Cross-Origin Resource Sharing](https://fetch.spec.whatwg.org/#http-cors-protocol))
- `Referer` 的限制 (参考:[Referer - HTTP | MDN](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referer))
CSRF 跨域攻击防范措施参考:[OWASP 安全备忘单](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)
技术细节:`trusted_domains` 配置通过控制 HTTP 响应标头 `Access-Control-Allow-Origin` 来对跨域请求进行限制 (参考:[W3C Cross-Origin Resource Sharing](https://fetch.spec.whatwg.org/#http-cors-protocol) / [OWASP 安全备忘单](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)).
## 默认站点 `site_default`
如果你觉得大概是不会用到 Artalk 的多站点功能,可以直接将该项配置为你的站点名,例如:
```yaml
site_default: "Artalk 官网"
site_default: Artalk 官网
```
然后在前端直接使用这个站点名:
```js
Artalk.init({ site: "Artalk 官网" })
Artalk.init({ site: 'Artalk 官网' })
```
这样,你就无需在侧边栏的[控制中心](../frontend/sidebar.md#控制中心)手动创建站点。
## 前端配置 `frontend`
## 界面配置 `frontend`
增加 `frontend` 字段内容可以在后端控制前端的配置,详情可参考:[在后端控制前端](/guide/backend/fe-control)。
在 Artalk 的配置文件 `artalk.yml` 可以配置 `frontend` 字段来控制前端界面,例如:
```yaml
frontend:
placeholder: 键入内容...
noComment: 「此时无声胜有声」
sendBtn: 发送评论
emoticons: 'https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json'
# ----- 此处省略 -------
# 与前端配置项名称保持一致
```
一份完整的后端 `frontend` 字段配置文件可供参考:[artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/blob/master/conf/artalk.example.zh-CN.yml)
## 邮件通知 `email`
@@ -211,11 +210,11 @@ Artalk.init({ site: "Artalk 官网" })
```yaml
cache:
enabled: true # 启用缓存 (默认关闭)
type: "builtin" # 支持 redis, memcache, builtin (自带缓存)
expires: 30 # 缓存过期时间 (单位:分钟)
warm_up: false # 程序启动时预热缓存
server: "" # 连接缓存服务器 (例如:"localhost:6379")
enabled: true # 启用缓存 (默认关闭)
type: builtin # 支持 redis, memcache, builtin (自带缓存)
expires: 30 # 缓存过期时间 (单位:分钟)
warm_up: false # 程序启动时预热缓存
server: '' # 连接缓存服务器 (例如:"localhost:6379")
```
- **warm_up**:缓存预热功能。设置为 `true`,在 Artalk 启动时会立刻对数据库内容进行全面缓存,如果你的评论数据较多,多达上万条,启动时间可能会延长。
@@ -232,10 +231,10 @@ Redis 身份认证、数据库配置:
cache:
# 省略其他配置项...
redis:
network: "tcp" # 连接方式 (tcp 或 unix)
username: "" # 用户名
password: "" # 密码
db: 0 # 使用零号数据库
network: tcp # 连接方式 (tcp 或 unix)
username: '' # 用户名
password: '' # 密码
db: 0 # 使用零号数据库
```
<!-- 技术细节:[Artalk 缓存机制 时序图.png](/images/artalk/artalk-cache.png) -->
@@ -246,7 +245,7 @@ cache:
Artalk 的默认 HTTP 端口为 23366,你可以在配置文件中指定:
```yaml
host: "0.0.0.0"
host: '0.0.0.0'
port: 23366
```
@@ -265,8 +264,8 @@ artalk server --host 127.0.0.1 --port 8080
```yaml
ssl:
enabled: true
cert_path: ""
key_path: ""
cert_path: ''
key_path: ''
```
你可以配置该项,让 HTTP 升级为 HTTPS,通过 SSL 协议加密传输数据。
@@ -279,7 +278,7 @@ ssl:
## 时区配置 `timezone`
```yaml
timezone: "Asia/Shanghai"
timezone: Asia/Shanghai
```
该值填写你所在地时区,对应 IANA 数据库时区名,参考:[Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) / [RFC-6557](https://www.rfc-editor.org/rfc/rfc6557.html)。
@@ -308,9 +307,17 @@ login_timeout: 259200
```yaml
log:
enabled: true # 总开关
filename: "./data/artalk.log" # 日志文件路径
filename: ./data/artalk.log # 日志文件路径
```
日志为 JSON 格式,可以通过使用 Linux 的 `tail` 命令结合 `jq` 工具查看:
```bash
tail -f ./data/artalk.log | jq
```
如果你是 Grafana 用户,可以结合 Loki 和 Promtail 来实现日志的收集和查询。
## 调试模式 `debug`
将 `debug` 配置为 `true` 启用调试模式。
@@ -340,7 +347,7 @@ artalk -w /root/artalk -c ./conf.yml
例如 `conf.yml` 中有这样的配置:
```yaml
test_file: "./data/artalk.log"
test_file: ./data/artalk.log
```
将读取 `/root/artalk/data/artalk.log`。
+2 -2
View File
@@ -54,7 +54,7 @@ After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
Type=simple
User=artalk
Group=artalk
ExecStart=/usr/bin/artalk server -w /var/lib/artalk -c /etc/artalk/artalk.yml
@@ -79,7 +79,7 @@ WantedBy=multi-user.target
保存服务文件后,你可以设置自动启动服务:
```bash
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now artalk
```
+4 -2
View File
@@ -1,5 +1,7 @@
# 数据
## 备份
本页面内容已移动至 <https://artalk.js.org/guide/transfer.html>。
前往:[数据迁移 · 备份](/guide/transfer.md)
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/guide/transfer.html';
</script>
+14 -28
View File
@@ -6,7 +6,9 @@ Artalk 提供后端程序的 Docker 镜像,以便加速部署流程,提供
## 镜像拉取
`docker pull artalk/artalk-go`
```bash
docker pull artalk/artalk-go
```
## 容器创建
@@ -16,34 +18,10 @@ Artalk 提供后端程序的 Docker 镜像,以便加速部署流程,提供
:::
Docker 容器创建:
## 生成配置文件
```bash
# 为 Artalk 创建一个目录
mkdir Artalk
cd Artalk
# 拉取 docker 镜像
docker pull artalk/artalk-go
# 生成配置文件
docker run -it -v $(pwd)/data:/data --rm artalk/artalk-go gen config data/artalk.yml
# 编辑配置文件
vim data/artalk.yml
# 运行 docker 容器
docker run -d \
--name artalk \
-p 0.0.0.0:8080:23366 \
-v $(pwd)/data:/data \
artalk/artalk-go
```
然后,在前端配置填入后端地址:
```js
Artalk.init({ server: "http://your_domain:8080" })
```
## 重启
@@ -92,12 +70,20 @@ docker pull artalk/artalk-go
突破性变动请注意查看版本更新日志中的提示:[CHANGELOG.md](https://github.com/ArtalkJS/Artalk/blob/master/CHANGELOG.md)
:::
## 拉取历史镜像
## 测试版本
Nightly 镜像为测试版本,每日更新,通过代码仓库最新代码自动构建。
```bash
docker pull artalk/artalk-go:nightly
```
## 历史版本
镜像会随代码仓库 tags 自动构建发布,您可拉取不同版本号的镜像。
```bash
docker pull artalk/artalk-go@版本号
docker pull artalk/artalk-go:版本号
```
## 进入容器
+37 -39
View File
@@ -1,8 +1,8 @@
# 邮件通知
Artalk 支持 SMTP 协议、阿里云邮件推送、调用系统 sendmail 命令等方式向用户发送邮件通知。
Artalk 支持通过 SMTP 协议、阿里云邮件推送、调用系统 Sendmail 命令等方式向用户发送邮件通知。
你可以在[控制中心](/guide/frontend/sidebar.md#控制中心)找到「设置」界面修改此配置。
你可以在 [控制中心](/guide/frontend/sidebar.md#设置) 的设置界面修改此配置,也可以通过 [配置文件](/guide/backend/config.md#邮件通知-email) 或 [环境变量](/guide/env.md#邮件通知) 进行配置。
## 配置文件
@@ -11,21 +11,21 @@ Artalk 支持 SMTP 协议、阿里云邮件推送、调用系统 sendmail 命令
```yaml
# 邮件通知
email:
enabled: false # 总开关
send_type: "smtp" # 发送方式 [smtp, ali_dm, sendmail]
enabled: false # 总开关
send_type: smtp # 发送方式 [smtp, ali_dm, sendmail]
send_name: '{{reply_nick}}' # 发信人昵称
send_addr: "example@qq.com" # 发信人地址
mail_subject: "[{{site_name}}] 您收到了来自 @{{reply_nick}} 的回复"
mail_tpl: "default" # 邮件模板文件
send_addr: example@qq.com # 发信人地址
mail_subject: '[{{site_name}}] 您收到了来自 @{{reply_nick}} 的回复'
mail_tpl: default # 邮件模板文件
smtp:
host: "smtp.qq.com"
host: smtp.qq.com
port: 587
username: "example@qq.com"
password: ""
username: example@qq.com
password: ''
ali_dm: # https://help.aliyun.com/document_detail/29444.html
access_key_id: "" # 阿里云颁发给用户的访问服务所用的密钥 ID
access_key_secret: "" # 用于加密的密钥
account_name: "example@example.com" # 管理控制台中配置的发信地址
access_key_id: '' # 阿里云颁发给用户的访问服务所用的密钥 ID
access_key_secret: '' # 用于加密的密钥
account_name: example@example.com # 管理控制台中配置的发信地址
```
### 选择发件方式
@@ -35,7 +35,7 @@ email:
```yaml
email:
enabled: true
send_type: "smtp" # 发送方式
send_type: smtp # 发送方式
# 省略其他配置...
smtp:
# SMTP 配置...
@@ -49,12 +49,12 @@ email:
# 邮件通知
email:
enabled: true
send_type: "smtp" # 选择 smtp
send_type: smtp # 选择 smtp
smtp:
host: "smtp.qq.com"
host: smtp.qq.com
port: 587
username: "example@qq.com"
password: ""
username: example@qq.com
password: ''
```
### 阿里云推送配置
@@ -62,11 +62,11 @@ email:
```yaml
email:
enabled: true
send_type: "ali_dm" # 选择 ali_dm
send_type: ali_dm # 选择 ali_dm
ali_dm:
access_key_id: "" # 阿里云颁发给用户的访问服务所用的密钥 ID
access_key_secret: "" # 用于加密的密钥
account_name: "example@example.com" # 管理控制台中配置的发信地址
access_key_id: '' # 阿里云颁发给用户的访问服务所用的密钥 ID
access_key_secret: '' # 用于加密的密钥
account_name: example@example.com # 管理控制台中配置的发信地址
```
可参考:[阿里云官方文档](https://help.aliyun.com/document_detail/29444.html)
@@ -86,16 +86,16 @@ email:
```yaml
email:
# 省略其他配置...
mail_subject: "[{{site_name}}] 您收到了来自 @{{reply_nick}} 的回复"
mail_subject: '[{{site_name}}] 您收到了来自 @{{reply_nick}} 的回复'
mail_subject_to_admin: '[{{site_name}}] 您的文章 "{{page_title}}" 有新回复'
mail_tpl: "default" # 邮件模板文件
mail_tpl: default # 邮件模板文件
```
变量是 “Mustache” 的语法,`双大括号` + `变量名` 的形式即可输出一个变量:
变量是 “Mustache” 的语法,`双大括号` + `变量名` 的形式即可输出一个变量:
**基本内容变量**
```
```yaml
{{content}} # 评论内容
{{link_to_reply}} # 回复链接
{{nick}} # 评论者昵称
@@ -109,7 +109,7 @@ email:
::: details 查看其他变量
```
```yaml
# 评论创建者
{{comment.badge_color}}
{{comment.badge_name}}
@@ -276,7 +276,7 @@ email:
"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,
"parent_comment.vote_up": 0
}
```
@@ -290,7 +290,7 @@ email:
```yaml
email:
mail_tpl: "/root/Artalk/data/mail_tpl/your_email_template.html"
mail_tpl: /root/Artalk/data/mail_tpl/your_email_template.html
# 其他配置省略...
```
@@ -298,15 +298,13 @@ email:
```html
<div>
<p>Hi, {{nick}}:</p>
<p>
您在 “{{page_title}}” 收到了回复:
</p>
<div>
<div>@{{reply_nick}}:</div>
<div>{{reply_content}}</div>
</div>
<p><a href="{{link_to_reply}}" target="_blank">回复消息 »</a></p>
<p>Hi, {{nick}}:</p>
<p>您在 “{{page_title}}” 收到了回复:</p>
<div>
<div>@{{reply_nick}}:</div>
<div>{{reply_content}}</div>
</div>
<p><a href="{{link_to_reply}}" target="_blank">回复消息 »</a></p>
</div>
```
@@ -319,7 +317,7 @@ Artalk 内置许多预设的邮件模板,例如 `mail_tpl: "default"` 使用
```yaml
admin_notify:
enabled: true
mail_subject: "[{{site_name}}] 您的文章「{{page_title}}」有新回复"
mail_subject: '[{{site_name}}] 您的文章「{{page_title}}」有新回复'
```
注:旧版 `email.mail_subject_to_admin` 配置项已弃用,请使用以上替代。
+5 -68
View File
@@ -1,70 +1,7 @@
# 在后端控制前端
# 如何配置界面
你可以在后端完全控制前端界面的行为(包括设定几乎所有[前端配置项](/guide/frontend/config)),我们推荐使用这种方式配置 Artalk 界面,并且这个特性「默认开启」。
本页面内容已移动至 <https://artalk.js.org/guide/frontend/config.html>。
## 如何修改前端界面配置
在侧边栏的[控制中心](/guide/frontend/sidebar.md#控制中心)提供了图形设置界面,你能快速轻松地对前端界面配置进行修改。
<img src="../../images/sidebar/fe-setting.png" width="400px">
## 在前端引入内置资源
后端 Artalk 服务器中内置了可供前端引入的 JS 和 CSS 资源文件:
```html
<!-- CSS -->
<link href="https://<artalk_go_server>/dist/Artalk.css" rel="stylesheet">
<!-- JS -->
<script src="https://<artalk_go_server>/dist/Artalk.js"></script>
```
> 提示:将 `<artalk_go_server>` 替换为你的 Artalk 服务器地址。
这样能让前后端始终保持兼容性,而无需在程序升级后手动更换 Artalk 前端资源的引入地址。
## 进阶内容
### 手动编辑配置文件
Artalk 提供图形界面简化配置,一般情况无需手动修改。
在 Artalk 的配置文件 `artalk.yml` 中配置 `frontend` 字段来控制前端界面,例如:
```yaml
frontend:
placeholder: "键入内容..."
noComment: "「此时无声胜有声」"
sendBtn: "发送评论"
emoticons: "https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json"
# ----- 此处省略 -------
# 与前端配置项名称保持一致
```
一份完整的后端 `frontend` 字段配置文件可供参考:[artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/blob/master/conf/artalk.example.zh-CN.yml)
### 关闭 “后端控制前端” 功能
后端控制前端功能默认开启,我们不建议关闭该功能。
在前端 `Artalk.init({ ... })` 时定义的配置会被配置文件中的 `frontend` 字段配置所覆盖,但如果有需要也可以在前端禁用这个特性:
```diff
Artalk.init({
+ useBackendConf: false,
})
```
### 表情包配置
建议 `frontend.emoticons` 填入表情包的 URL,而非 Object。
参考文档:[表情包](/guide/frontend/emoticons)
如需传递 Object,可以将其转为 JSON 字符串格式,例如:
```yaml
frontend:
emoticons: '{"表情": { "test": "tttt..." }}'
```
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/guide/frontend/config.html';
</script>
+41 -21
View File
@@ -1,40 +1,60 @@
# 图片上传
Artalk 提供图片上传功能,支持限制图片大小、上传频率等,你还能结合 upgit 将图片上传到图床。
Artalk 提供图片上传功能,支持限制图片大小、上传频率等,你还能结合 UpGit 将图片上传到图床。
你可以在[控制中心](/guide/frontend/sidebar.md#控制中心)找到「设置」界面修改此配置。
你可以在 [控制中心](/guide/frontend/sidebar.md#设置) 的设置界面修改此配置,也可以通过 [配置文件](/guide/backend/config.md#图片上传-img_upload) 或 [环境变量](/guide/env.md#图片上传) 进行配置。
## 配置文件
完整的 `img-upload` 配置如下:
完整的 `img_upload` 配置如下:
```yaml
# 图片上传
img_upload:
enabled: true # 总开关
path: "./data/artalk-img/" # 图片存放路径
max_size: 5 # 图片大小限制 (单位:MB)
public_path: null # 指定图片链接基础路径 (默认为 "/static/images/")
enabled: true # 总开关
path: ./data/artalk-img/ # 图片存放路径
max_size: 5 # 图片大小限制 (单位:MB)
public_path: null # 指定图片链接基础路径 (默认为 "/static/images/")
# 使用 upgit 将图片上传到 GitHub 或图床
upgit:
enabled: false # 启用 upgit
exec: "./upgit -c <upgit配置文件路径> -t /artalk-img"
enabled: false # 启用 upgit
exec: upgit -c <upgit配置文件路径> -t /artalk-img
del_local: true # 上传后删除本地的图片
```
## 使用 Upgit 上传到图床
[Upgit](https://github.com/pluveto/upgit) 支持将图片上传到 Github、Gitee、腾讯云 COS、七牛云、又拍云、SM.MS 等图床或代码仓库。
[UpGit](https://github.com/pluveto/upgit) 支持将图片上传到 Github、Gitee、腾讯云 COS、七牛云、又拍云、SM.MS 等图床或代码仓库。
首先,根据 [README.md](https://github.com/pluveto/upgit) 的说明,下载 Upgit 并完成你需要上传的目标图床的配置。
首先,根据 [README.md](https://github.com/pluveto/upgit) 的说明,下载 UpGit 并完成你需要上传的目标图床的配置。
然后在 Artalk 的 `img_upload.upgit` 字段填入 Upgit 启动参数 (建议使用程序绝对路径),例如:
然后,将 UpGit 加入系统的环境变量中,在 `~/.bashrc` 加入:
```bash
export PATH=$PATH:/path/to/upgit
```
(或者直接移入 `/usr/bin`)
最后,在 Artalk 的 `img_upload.upgit` 字段填入 UpGit 启动参数:
```yaml
upgit:
enabled: true # 启用 upgit
exec: "/root/upgit -c <upgit配置文件路径> -t /artalk-img"
del_local: true # 上传后删除本地的图片
upgit:
enabled: true # 启用 upgit
exec: upgit -c <upgit配置文件路径> -t /artalk-img
del_local: true # 上传后删除本地的图片
```
::: warning 更新注意
从 `v2.8.4` 版本开始,为了增强安全性,Artalk 不再允许指定 UpGit 的可执行文件路径,请将其加入系统的环境变量中。:)
:::
### Docker 挂载 UpGit
如果你使用 Docker 部署 Artalk,可以将 UpGit 可执行文件挂载到容器中:
```bash
docker run -d --name artalk -v /path/to/upgit:/usr/bin/upgit -v /path/to/artalk:/app/data -p 8080:23366 artalk
```
## 上传频率限制
@@ -58,7 +78,7 @@ http://<后端地址>/static/images/
当该项为「相对路径」时,例如:`/static/images/` 前端上传图片得到的 HTML 标签将为:
```html
<img src="http://<后端地址>/static/images/1.png">
<img src="http://<后端地址>/static/images/1.png" />
```
注:这里的 `<后端地址>` 是前端 `conf.server` 配置。
@@ -66,7 +86,7 @@ http://<后端地址>/static/images/
当该项为「完整 URL 路径」时,例如:`https://cdn.github.com/img/` 时,图片标签将为:
```html
<img src="https://cdn.github.com/img/1.png">
<img src="https://cdn.github.com/img/1.png" />
```
提示:这个配置可以结合负载均衡等场景使用。
@@ -81,13 +101,13 @@ Artalk.init({
const form = new FormData()
form.set('file', file)
const imgUrl = await fetch("https://api.example.org/upload", {
const imgUrl = await fetch('https://api.example.org/upload', {
method: 'POST',
body: form
body: form,
})
return imgUrl
}
},
})
```
-17
View File
@@ -1,17 +0,0 @@
# Artalk
Artalk 拥有一个 Golang 语言编写的后端程序。
[GitHub 代码仓库](https://github.com/ArtalkJS/Artalk)
- 高效快速
- 异步执行
- 跨平台兼容
- 轻量级部署
## Supports
- 运行环境:支持 Linux, Windows, Darwin (x64 + ARM)
- 数据存储:支持 SQLite, MySQL, PostgreSQL, SQL Server
- 邮件发送:支持 SMTP, 阿里云邮件, 调用 sendmail 发送邮件
- 高效缓存:支持 Redis, Memcache, In-Memory (BigCache)
+5 -1
View File
@@ -1,3 +1,7 @@
# 后端部署
参考:[程序部署](../deploy.md)
本页面内容已移动至 <https://artalk.js.org/guide/deploy.html>。
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/guide/deploy.html';
</script>
+24 -24
View File
@@ -2,7 +2,7 @@
Artalk 支持多种评论过滤方式以拦截垃圾评论,支持通过 Akismet、腾讯云内容安全、阿里云内容安全 等在线 API 实现垃圾评论识别和拦截,也可通过本地离线关键词词库过滤评论,结合[验证码](./captcha.md)功能进一步提高评论审核强度,让垃圾评论没有容身之地。
你可以在[控制中心](/guide/frontend/sidebar.md#控制中心)找到「设置」界面修改此配置。
你可以在 [控制中心](/guide/frontend/sidebar.md#设置) 的设置界面修改此配置,也可以通过 [配置文件](/guide/backend/config.md#评论审核-moderator) 或 [环境变量](/guide/env.md#评论审核) 进行配置。
## 配置文件
@@ -12,29 +12,29 @@ Artalk 支持多种评论过滤方式以拦截垃圾评论,支持通过 Akisme
# 评论审核
moderator:
pending_default: false # 发表新评论默认为 “待审状态”
api_fail_block: false # 垃圾检测 API 请求错误仍然拦截
api_fail_block: false # 垃圾检测 API 请求错误仍然拦截
# akismet.com 反垃圾
akismet_key: ""
akismet_key: ''
# 腾讯云文本内容安全 (tms)
tencent: # https://cloud.tencent.com/document/product/1124/64508
enabled: false
secret_id: ""
secret_key: ""
region: "ap-guangzhou"
secret_id: ''
secret_key: ''
region: ap-guangzhou
# 阿里云内容安全
aliyun: # https://help.aliyun.com/document_detail/28417.html
enabled: false
access_key_id: ""
access_key_secret: ""
region: "cn-shanghai"
access_key_id: ''
access_key_secret: ''
region: cn-shanghai
# 关键词词库过滤
keywords:
enabled: false
pending: false # 匹配成功设为待审状态
files: # 支持多个词库文件
- "./data/词库_1.txt"
files: # 支持多个词库文件
- './data/词库_1.txt'
file_sep: "\n" # 词库文件内容分割符
replac_to: "x" # 替换字符
replace_to: 'x' # 替换字符
```
## 默认待审模式
@@ -58,7 +58,7 @@ moderator:
```yaml
moderator:
akismet_key: "your_key"
akismet_key: your_key
```
## 腾讯云文本内容安全
@@ -71,9 +71,9 @@ moderator:
moderator:
tencent:
enabled: true
secret_id: ""
secret_key: ""
region: "ap-guangzhou"
secret_id: ''
secret_key: ''
region: ap-guangzhou
```
## 阿里云内容安全
@@ -86,9 +86,9 @@ moderator:
moderator:
aliyun:
enabled: true
access_key_id: ""
access_key_secret: ""
region: "cn-shanghai"
access_key_id: ''
access_key_secret: ''
region: cn-shanghai
```
## 关键词词库过滤
@@ -100,18 +100,18 @@ moderator:
keywords:
enabled: true
pending: false # 匹配成功设为待审状态
files: # 支持多个词库文件
- "./data/词库_1.txt"
files: # 支持多个词库文件
- ./data/词库_1.txt
file_sep: "\n" # 词库文件内容分割符
replac_to: "x" # 替换字符
replace_to: 'x' # 替换字符
```
- **pending**:当成功匹配时,是否将评论设为待审核状态。
- **files**:词库文件。允许多个文件,Artalk 启动时会合并词库。
- **file_sep**:词库文件内容分割符。例如:文件中每行一个词语,该项配置 `\n`。
- **replac_to**:替换字符。例如:该项设置为 `x`,你可以将 `pending` 设置为 `false`,评论自动过审,但匹配到的词语会被替换为 `x`,例如 `fxxk`、`xxxx`。
- **replace_to**:替换字符。例如:该项设置为 `x`,你可以将 `pending` 设置为 `false`,评论自动过审,但匹配到的词语会被替换为 `x`,例如 `fxxk`、`xxxx`。
注:`replac_to` 不建议使用 `*` 星号,应为它和 Markdown 的加粗语法冲突。
注:`replace_to` 不建议使用 `*` 星号,应为它和 Markdown 的加粗语法冲突。
## 使用验证码
+18 -12
View File
@@ -20,7 +20,7 @@ docker exec -it artalk artalk admin
## 站点的创建和管理
你可以在侧边栏「[控制中心](../frontend/sidebar.md#控制中心)」创建多个站点,管理站点和快速切换站点,详情可参考:[侧边栏](/guide/frontend/sidebar.html)。
你可以在侧边栏「[控制中心](../frontend/sidebar.md#控制中心)」创建多个站点,管理站点和快速切换站点。
## 管理员配置
@@ -32,16 +32,16 @@ docker exec -it artalk artalk admin
```yaml
admin_users:
- name: "admin"
email: "admin@example.com"
password: "(bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm"
badge_name: "管理员"
badge_color: "#0083FF"
- name: "admin2"
email: "admin2@example.com"
password: "(bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm"
badge_name: "小管理员"
badge_color: "#0083FF"
- name: admin
email: admin@example.com
password: (bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm
badge_name: 管理员
badge_color: '#0083FF'
- name: admin2
email: admin2@example.com
password: (bcrypt)$2y$10$ti4vZYIrxVN8rLcYXVgXCO.GJND0dyI49r7IoF3xqIx8bBRmIBZRm
badge_name: 小管理员
badge_color: '#0083FF'
```
每项配置的解释:
@@ -65,6 +65,12 @@ admin_users:
- **badge_name**:用户显示的头衔徽标文字。
- **badge_color**:用户显示的头衔徽标背景颜色。
::: tip
可以通过环境变量配置管理员账户,参考:[环境变量配置](/guide/env.md)
:::
### 控制管理员接收邮件通知
当页面有新的评论时,默认配置是邮件会发送给全部管理员,但你可以配置 `receive_email` 强制禁用它。
@@ -77,6 +83,6 @@ admin_users:
```yaml
admin_users:
- name: "admin"
- name: admin
receive_email: false # ← 强制不接收邮件
```
+2 -3
View File
@@ -9,13 +9,12 @@ Artalk v2.1.8+ 配置项:
# 管理员多元推送
admin_notify:
# 通知模版
notify_tpl: "default"
notify_tpl: default
noise_mode: false
# 邮件通知管理员
email:
enabled: true # 当使用其他推送方式时,可以关闭管理员邮件通知
mail_subject: "[{{site_name}}] 您的文章「{{page_title}}」有新回复"
mail_subject: '[{{site_name}}] 您的文章「{{page_title}}」有新回复'
```
请参考新文档:[多元推送](./admin_notify.md)
+6 -6
View File
@@ -4,8 +4,8 @@ Artalk 支持解析相对路径,因此你可以在前端页面进行如下配
```js
Artalk.init({
site: "举个栗子站点", // 你的站点名
pageKey: "/relative-path/xx.html", // 使用相对路径
site: '举个栗子站点', // 你的站点名
pageKey: '/relative-path/xx.html', // 使用相对路径
})
```
@@ -23,7 +23,7 @@ Artalk.init({
"https://设定的举个栗子站点URL.xxx/relative-path/xx.html"
```
### 解析后的 URL 用途
## 解析后的 URL 用途
站点 URL + 页面 相对路径 将用于:
@@ -32,7 +32,7 @@ Artalk.init({
- **控制中心**页面管理打开页面
- **获取页面标题**等信息时使用
### 配置多个站点 URL 的情况
## 配置多个站点 URL 的情况
你可能需要配置站点的多个 URL 来允许 Referer 和跨域。
@@ -40,13 +40,13 @@ Artalk.init({
**当站点存在多个 URL 时**,「相对路径」会基于多个 URL 中的「**第一个**」URL。
### 使用绝对路径的情况
## 使用绝对路径的情况
区别于使用相对路径,你可以使用绝对路径,例如前端这样配置:
```js
Artalk.init({
pageKey: "https://your_domain.com/relative-path/xx.html", // 使用绝对路径
pageKey: 'https://your_domain.com/relative-path/xx.html', // 使用绝对路径
})
```
+4 -1
View File
@@ -76,7 +76,7 @@ sudo systemctl restart nginx
配置前端:
```js
Artalk.init({ server: "http://artalk.your_domain.com" })
Artalk.init({ server: 'http://artalk.your_domain.com' })
```
::: tip
@@ -119,3 +119,6 @@ Artalk.init({ server: "http://artalk.your_domain.com" })
![](/images/baota-proxy/2.png)
## 获取准确的 IP 地址
当使用反向代理服务器后,需要配置代理标头才能获取到用户的准确 IP 地址,参考 [IP 属地](../frontend/ip-region.md#获取准确的-ip-地址) 的说明。
+9 -4
View File
@@ -9,9 +9,16 @@
- [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
### 博客
- [百合花船·教程](https://jc.yuriboat.cn)
- [Misaka の 💭](https://blog.misaka.ink/)
- [备胎书屋](https://beitai.cc)
- [1nonly's blog](https://blog.nonly.cn)
- [慕雪的寒舍](https://blog.musnow.top/)
- [晓雨杂记](https://www.lihaoyu.cn)
- [一蓑烟雨](https://easyf12.top/)
- [二丫讲梵](https://wiki.eryajf.net)
- [Alliot’s blog](https://www.iots.vip/)
@@ -23,16 +30,14 @@
- [频率](https://pinlyu.com/)
- [子舒](https://zburu.com/)
- [叶开](https://xn--qpru0x.cn/)
- [Thun888](https://blog.thun888.xyz/)
- [Thun888](https://blog.hzchu.top/)
- [青空之蓝](https://blog.ixk.me/)
- [Monstx](https://blog.monsterx.cn/)
- [QWQAQ](https://qwqaq.com/)
::: tip
此页面案例由团队成员整理...
如果希望 / 不希望你使用到 Artalk 的项目在此展示,欢迎在下方留言!
如果你希望你的项目在此展示,欢迎在下方留言,或者点击左下角的「完善文档」按钮,在 GitHub 编辑此页提交 PR。
非常感谢你为 Artalk 社区做出的贡献 😘
+90 -66
View File
@@ -2,99 +2,105 @@
## Docker 部署
推荐使用 Docker 部署,需预先安装 [Docker 引擎](https://docs.docker.com/engine/install/),服务器执行命令创建容器:
推荐使用 Docker 部署,需预先安装 [Docker 引擎](https://docs.docker.com/engine/install/),执行命令创建容器:
```bash
docker run -d \
--name artalk \
-p 8080:23366 \
-v $(pwd)/data:/data \
--restart=always \
-e "TZ=Asia/Shanghai" \
-e "ATK_LOCALE=zh-CN" \
-e "ATK_SITE_DEFAULT=Artalk 的博客" \
-e "ATK_SITE_URL=https://example.com" \
artalk/artalk-go
```
> 假设域名 `http://your_domain` 已正确添加 DNS 记录并指向你的服务器 IP
浏览器打开 `http://your_domain:8080` 将出现 Artalk 后台登录界面。
执行命令创建管理员账户:
```bash
docker exec -it artalk artalk admin
```
在你的网站引入 Artalk 程序内嵌的的前端 CSS、JS 资源并初始化:
浏览器输入 `http://artalk.example.com:8080` 进入 Artalk 后台登录界面。
> 注:将 `http://your_domain:8080` 改为你的服务器域名,或使用 [公共 CDN 资源](#cdn-资源)。
在网页中引入 Artalk 程序内嵌的的前端 JS 和 CSS 资源并初始化 Artalk:
<!-- prettier-ignore-start -->
```html
<!-- CSS -->
<link href="http://your_domain:8080/dist/Artalk.css" rel="stylesheet">
<link href="http://artalk.example.com:8080/dist/Artalk.css" rel="stylesheet" />
<!-- JS -->
<script src="http://your_domain:8080/dist/Artalk.js"></script>
<script src="http://artalk.example.com:8080/dist/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments', // 绑定元素的 Selector
pageKey: '/post/1', // 固定链接 (留空自动获取)
pageKey: '/post/1', // 固定链接
pageTitle: '关于引入 Artalk 的这档子事', // 页面标题 (留空自动获取)
server: 'http://your_domain:8080', // 后端地址
server: 'http://artalk.example.com:8080', // 后端地址
site: 'Artalk 的博客', // 你的站点名
})
</script>
```
<!-- prettier-ignore-end -->
在评论框输入管理员的用户名和邮箱,控制台入口按钮将出现在评论框右下角位置。
评论框输入管理员用户名和邮箱,「控制台」按钮将出现在评论框右下角。
在控制台,你可以根据喜好配置评论系统、[将评论迁移到 Artalk](./transfer.md)。
在控制台,你可以根据喜好[配置评论系统](./backend/config.md)、[将评论迁移到 Artalk](./transfer.md)。
🥳 你已成功完成 Artalk 部署!
## 普通方式部署
1. 前往 [GitHub Release](https://github.com/ArtalkJS/Artalk/releases) 下载程序压缩包
2. 提取压缩包:`tar -zxvf artalk_版本号_系统_架构.tar.gz`
3. 运行程序 `./artalk server`
4. 前端配置
1. [GitHub Release](https://github.com/ArtalkJS/Artalk/releases) 下载程序压缩包
2. 解压 `tar -zxvf artalk_版本号_系统_架构.tar.gz`
3. 运行 `./artalk server`
4. 配置
```js
Artalk.init({ server: "http://your_domain:23366" })
```
```js
Artalk.init({ server: 'http://artalk.example.com:23366' })
```
**进一步操作:**
进阶操作:
- [守护进程 (Systemd, Supervisor)](./backend/daemon.md)
- [反向代理 (Caddy, Nginx, Apache)](./backend/reverse-proxy.md)
如果有需要,你还可以自行编译程序,参考:[后端构建](./backend/build.md)。
- [自编译 (通过最新代码构建)](../develop/contributing.md)
## Compose 部署
**compose.yaml**
```yaml
version: "3.5"
version: '3.8'
services:
artalk:
container_name: artalk
image: artalk/artalk-go
restart: always
restart: unless-stopped
ports:
- 8080:23366
volumes:
- ./data:/data
environment:
- TZ=Asia/Shanghai
- ATK_LOCALE=zh-CN
- ATK_SITE_DEFAULT=Artalk 的博客
- ATK_SITE_URL=https://your_domain
```
执行命令创建容器:
创建容器:
```bash
docker-compose up -d
```
::: details 一些 Docker Compose 常用命令
::: details Compose 常用命令
```bash
docker-compose restart # 重启容器
@@ -106,7 +112,37 @@ docker-compose exec artalk bash # 进入容器
:::
可参考:[Docker 部署文档](./backend/docker.md)
参考文档:[Docker](./backend/docker.md) / [环境变量](./env.md)
::: warning
自 2024-06-06 开始,境内的 Docker Hub 镜像相继停止服务,可选择配置代理或自建镜像。
详见:[Docker 镜像加速](https://gist.github.com/y0ngb1n/7e8f16af3242c7815e7ca2f0833d3ea6)。
:::
## Linux 发行版
**Arch Linux (AUR)**:
```bash
paru -S artalk
```
**NixOS**:
```bash
nix-env -iA nixpkgs.artalk
```
**Termux**:
```bash
pkg install artalk
```
[![Packaging status](https://repology.org/badge/vertical-allrepos/artalk.svg)](https://repology.org/project/artalk/versions)
## CDN 资源
@@ -114,66 +150,53 @@ docker-compose exec artalk bash # 进入容器
当前 Artalk 前端最新版本号为: **:ArtalkVersion:**
若需升级前端,请将 URL 中的版本号数字部分替换即可。
若需升级前端将 URL 中的版本号数字部分替换即可。
:::
Artalk 后端程序内嵌了前端 JS、CSS 文件,使用公共 CDN 资源请注意前后端版本的兼容性。
Artalk 静态资源通过上游 CDNJS 分发,以下镜像资源可供选择:
Artalk 后端程序内嵌了前端 JS、CSS 文件,使用公共 CDN 资源请注意版本兼容性。
**CDNJS**
> https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.js
> <https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.js>
>
> https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.css
**SUSTech Mirrors (境内)**
> https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/artalk/:ArtalkVersion:/Artalk.js
>
> https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/artalk/:ArtalkVersion:/Artalk.css
> <https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.css>
::: details 查看更多
**SUSTech Mirrors (境内)**
> <https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/artalk/:ArtalkVersion:/Artalk.js>
>
> <https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/artalk/:ArtalkVersion:/Artalk.css>
**Staticfile CDN (境内)**
> https://cdn.staticfile.org/artalk/:ArtalkVersion:/Artalk.js
> <https://cdn.staticfile.org/artalk/:ArtalkVersion:/Artalk.js>
>
> https://cdn.staticfile.org/artalk/:ArtalkVersion:/Artalk.css
**BootCDN (境内)**
> https://cdn.bootcdn.net/ajax/libs/artalk/:ArtalkVersion:/Artalk.js
>
> https://cdn.bootcdn.net/ajax/libs/artalk/:ArtalkVersion:/Artalk.css
**75CDN (境内)**
> https://lib.baomitu.com/artalk/:ArtalkVersion:/Artalk.js
>
> https://lib.baomitu.com/artalk/:ArtalkVersion:/Artalk.css
> <https://cdn.staticfile.org/artalk/:ArtalkVersion:/Artalk.css>
**UNPKG**
> https://unpkg.com/artalk@:ArtalkVersion:/dist/Artalk.js
>
> https://unpkg.com/artalk@:ArtalkVersion:/dist/Artalk.css
> <https://unpkg.com/artalk@:ArtalkVersion:/dist/Artalk.js>
>
> <https://unpkg.com/artalk@:ArtalkVersion:/dist/Artalk.css>
**JS DELIVR**
> https://cdn.jsdelivr.net/npm/artalk@:ArtalkVersion:/dist/Artalk.js
>
> https://cdn.jsdelivr.net/npm/artalk@:ArtalkVersion:/dist/Artalk.css
> <https://cdn.jsdelivr.net/npm/artalk@:ArtalkVersion:/dist/Artalk.js>
>
> <https://cdn.jsdelivr.net/npm/artalk@:ArtalkVersion:/dist/Artalk.css>
:::
## Node 项目
安装 Artalk:
```bash
pnpm add artalk
npm install artalk
```
引入到你的项目:
引入 Artalk:
```js
import 'artalk/dist/Artalk.css'
@@ -184,10 +207,11 @@ Artalk.init({
})
```
可参考:
更多参考:
- [置入框架文档](./frontend/import-framework.md)
- [置入博客文档](./frontend/import-blog.md)
- [置入博客文档](../develop/import-blog.md)
- [置入框架文档](../develop/import-framework.md)
- [前端配置](./frontend/config.md)
- [前端 API](../develop/fe-api.md)
## 数据导入
-42
View File
@@ -1,42 +0,0 @@
# 😴 深入了解
::: warning
目前文档仍在陆续完善中
:::
## 控制台(管理后台)
面向管理员用户,我们提供了 “控制台” 功能,通过控制台,你能对数据内容进行统一管理。
### 如何呼出控制台
控制台被集成到评论页中,您仅需:
1. 在评论框输入管理员的名字与邮箱
2. 密码验证框自动弹出,输入正确密码
3. 控制台按钮将会在评论框右下角显示
【图示】
## 通知中心
通知中心入口按钮将会在用户填入名字和邮箱后显示,它在评论框的右下角,与管理员控制台按钮位置相同。
通知中心的评论分为 提及、我的、全部、待审 四类。
- 提及:被人 AT 或对你的回复
- 我的:我发布的评论
- 全部:我的所有评论及相关评论
- 待审:我的待审核评论
## 邮件发送
Artalk 支持以多种方式发送邮件,
## 审核制度
你能够通过设置,开启 评论默认待审,当用户提交评论后,需要管理员审核后才能显示,在此期间仅评论者自己可见。
## 反垃圾
Artalk 提供多种反垃圾的方法,其具体实现我们称之为 垃圾评论检查器,一旦检测到垃圾评论,检查器会将它标记为 “待审核” 状态。
+360
View File
@@ -0,0 +1,360 @@
# 环境变量
Artalk 支持通过环境变量修改配置,这使得 Docker 等容器化云部署变得简单。
环境变量名以 `ATK_` 开头,全大写,对应[配置文件](./backend/config.md)中的每个节点。
环境变量的优先级高于配置文件,通过以下命令验证配置是否生效:
```bash
artalk config
```
使用 Docker Compose 部署 Artalk,可在 `compose.yml` 文件添加环境变量,例如:
```yaml
version: '3.8'
services:
artalk:
container_name: artalk
image: artalk/artalk-go
restart: unless-stopped
ports:
- 8080:23366
volumes:
- ./data:/data
environment:
- TZ=Asia/Shanghai
- ATK_LOCALE=zh-CN
- ATK_SITE_DEFAULT=Artalk 的博客
- 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=管理员
- ATK_ADMIN_USERS_0_BADGE_COLOR=#0083FF
```
当变量为数组,通过空格分隔的字符串或数字索引来设置数组值,例如:
```
ATK_TRUSTED_DOMAINS="https://a.com https://b.com"
ATK_TRUSTED_DOMAINS_0="https://a.com"
```
<style>
.env-table table {
table-layout: fixed;
word-break: break-word;
th:first-of-type, td:first-of-type {
width: 30%;
}
th:nth-of-type(2), td:nth-of-type(2) {
width: 20%;
}
th:nth-of-type(3), td:nth-of-type(3) {
width: 20%;
}
th:nth-of-type(4), td:nth-of-type(4) {
width: 30%;
}
}
</style>
<div class="env-table">
<!-- env-variables -->
## 通用配置
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_ADMIN_USERS** | `[]` | 管理员账户 | admin_users (管理员账户) |
| **ATK_APP_KEY** | `""` | 加密密钥 | app_key (加密密钥) |
| **ATK_DEBUG** | `false` | 调试模式 | debug (调试模式) |
| **ATK_HOST** | `"0.0.0.0"` | 服务器地址 | host (服务器地址) |
| **ATK_LOCALE** | `"zh-CN"` | 语言 (可选:`["en", "zh-CN", "zh-TW", "ja", "fr", "ko", "ru"]`) | locale (语言) |
| **ATK_LOGIN_TIMEOUT** | `259200` | 登录有效时长 (单位:秒) | login_timeout (登录有效时长) |
| **ATK_PORT** | `23366` | 服务器端口 | port (服务器端口) |
| **ATK_SITE_DEFAULT** | `"默认站点"` | 默认站点名 | site_default (默认站点名) |
| **ATK_SITE_URL** | `""` | 默认站点地址 | site_url (默认站点地址) |
| **ATK_TIMEZONE** | `"Asia/Shanghai"` | 时间区域 | timezone (时间区域) |
| **ATK_TRUSTED_DOMAINS** | `[]` | 可信域名 | trusted_domains (可信域名) |
## 多元推送
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_ADMIN_NOTIFY_BARK_ENABLED** | `false` | 启用 | admin_notify.bark.enabled (多元推送 > Bark > Enabled) |
| **ATK_ADMIN_NOTIFY_BARK_SERVER** | `"http://day.app/xxxxxxx/"` | Server | admin_notify.bark.server (多元推送 > Bark > Server) |
| **ATK_ADMIN_NOTIFY_DING_TALK_ENABLED** | `false` | 启用 | admin_notify.ding_talk.enabled (多元推送 > 钉钉 > Enabled) |
| **ATK_ADMIN_NOTIFY_DING_TALK_SECRET** | `""` | Secret | admin_notify.ding_talk.secret (多元推送 > 钉钉 > Secret) |
| **ATK_ADMIN_NOTIFY_DING_TALK_TOKEN** | `""` | Token | admin_notify.ding_talk.token (多元推送 > 钉钉 > Token) |
| **ATK_ADMIN_NOTIFY_EMAIL_ENABLED** | `true` | 开启 (当使用其他推送方式时,可以关闭管理员邮件通知) | admin_notify.email.enabled (多元推送 > 邮件通知管理员 > 开启) |
| **ATK_ADMIN_NOTIFY_EMAIL_MAIL_SUBJECT** | `"[{{site_name}}] 您的文章「{{page_title}}」有新回复"` | 邮件标题 (发送给管理员的邮件标题) | admin_notify.email.mail_subject (多元推送 > 邮件通知管理员 > 邮件标题) |
| **ATK_ADMIN_NOTIFY_EMAIL_MAIL_TPL** | `""` | 管理员邮件模板文件 (填入文件路径使用自定义模板) | admin_notify.email.mail_tpl (多元推送 > 邮件通知管理员 > 管理员邮件模板文件) |
| **ATK_ADMIN_NOTIFY_LARK_ENABLED** | `false` | 启用 | admin_notify.lark.enabled (多元推送 > 飞书 > Enabled) |
| **ATK_ADMIN_NOTIFY_LARK_MSG_TYPE** | `"text"` | 消息类型 (可选:`["text", "card"]`) | admin_notify.lark.msg_type (多元推送 > 飞书 > 消息类型) |
| **ATK_ADMIN_NOTIFY_LARK_WEBHOOK_URL** | `""` | WebhookUrl | admin_notify.lark.webhook_url (多元推送 > 飞书 > WebhookUrl) |
| **ATK_ADMIN_NOTIFY_LINE_CHANNEL_ACCESS_TOKEN** | `""` | ChannelAccessToken | admin_notify.line.channel_access_token (多元推送 > LINE > ChannelAccessToken) |
| **ATK_ADMIN_NOTIFY_LINE_CHANNEL_SECRET** | `""` | ChannelSecret | admin_notify.line.channel_secret (多元推送 > LINE > ChannelSecret) |
| **ATK_ADMIN_NOTIFY_LINE_ENABLED** | `false` | 启用 | admin_notify.line.enabled (多元推送 > LINE > Enabled) |
| **ATK_ADMIN_NOTIFY_LINE_RECEIVERS** | `[USER_ID_1 GROUP_ID_1]` | Receivers | admin_notify.line.receivers (多元推送 > LINE > Receivers) |
| **ATK_ADMIN_NOTIFY_NOISE_MODE** | `false` | 嘈杂模式 | admin_notify.noise_mode (多元推送 > 嘈杂模式) |
| **ATK_ADMIN_NOTIFY_NOTIFY_PENDING** | `false` | 待审评论仍然发送通知 (当评论被拦截时仍然发送通知) | admin_notify.notify_pending (多元推送 > 待审评论仍然发送通知) |
| **ATK_ADMIN_NOTIFY_NOTIFY_TPL** | `"default"` | 通知模版 (填入文件路径使用自定义模板) | admin_notify.notify_tpl (多元推送 > 通知模版) |
| **ATK_ADMIN_NOTIFY_SLACK_ENABLED** | `false` | 启用 | admin_notify.slack.enabled (多元推送 > Slack > Enabled) |
| **ATK_ADMIN_NOTIFY_SLACK_OAUTH_TOKEN** | `""` | OauthToken | admin_notify.slack.oauth_token (多元推送 > Slack > OauthToken) |
| **ATK_ADMIN_NOTIFY_SLACK_RECEIVERS** | `[CHANNEL_ID]` | Receivers | admin_notify.slack.receivers (多元推送 > Slack > Receivers) |
| **ATK_ADMIN_NOTIFY_TELEGRAM_API_TOKEN** | `""` | ApiToken | admin_notify.telegram.api_token (多元推送 > Telegram > ApiToken) |
| **ATK_ADMIN_NOTIFY_TELEGRAM_ENABLED** | `false` | 启用 | admin_notify.telegram.enabled (多元推送 > Telegram > Enabled) |
| **ATK_ADMIN_NOTIFY_TELEGRAM_RECEIVERS** | `[7777777]` | Receivers | admin_notify.telegram.receivers (多元推送 > Telegram > Receivers) |
| **ATK_ADMIN_NOTIFY_WEBHOOK_ENABLED** | `false` | 启用 | admin_notify.webhook.enabled (多元推送 > WebHook > Enabled) |
| **ATK_ADMIN_NOTIFY_WEBHOOK_URL** | `""` | Url | admin_notify.webhook.url (多元推送 > WebHook > Url) |
## 社交登录
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_AUTH_ANONYMOUS** | `false` | 允许匿名评论 (允许跳过验证,仅填写匿名的昵称和邮箱) | auth.anonymous (社交登录 > 允许匿名评论) |
| **ATK_AUTH_APPLE_CLIENT_ID** | `""` | ClientId | auth.apple.client_id (社交登录 > Apple > ClientId) |
| **ATK_AUTH_APPLE_CLIENT_SECRET** | `""` | ClientSecret | auth.apple.client_secret (社交登录 > Apple > ClientSecret) |
| **ATK_AUTH_APPLE_ENABLED** | `false` | 启用 | auth.apple.enabled (社交登录 > Apple > Enabled) |
| **ATK_AUTH_AUTH0_CLIENT_ID** | `""` | ClientId | auth.auth0.client_id (社交登录 > Auth0 > ClientId) |
| **ATK_AUTH_AUTH0_CLIENT_SECRET** | `""` | ClientSecret | auth.auth0.client_secret (社交登录 > Auth0 > ClientSecret) |
| **ATK_AUTH_AUTH0_DOMAIN** | `""` | Domain | auth.auth0.domain (社交登录 > Auth0 > Domain) |
| **ATK_AUTH_AUTH0_ENABLED** | `false` | 启用 | auth.auth0.enabled (社交登录 > Auth0 > Enabled) |
| **ATK_AUTH_CALLBACK** | `"http://localhost:23366/api/v2/auth/{provider}/callback"` | 回调地址 (https://example.com/api/v2/auth/{provider}/callback) | auth.callback (社交登录 > 回调地址) |
| **ATK_AUTH_DISCORD_CLIENT_ID** | `""` | ClientId | auth.discord.client_id (社交登录 > Discord > ClientId) |
| **ATK_AUTH_DISCORD_CLIENT_SECRET** | `""` | ClientSecret | auth.discord.client_secret (社交登录 > Discord > ClientSecret) |
| **ATK_AUTH_DISCORD_ENABLED** | `false` | 启用 | auth.discord.enabled (社交登录 > Discord > Enabled) |
| **ATK_AUTH_EMAIL_ENABLED** | `true` | 启用邮箱密码登录 | auth.email.enabled (社交登录 > Email > 启用邮箱密码登录) |
| **ATK_AUTH_EMAIL_VERIFY_SUBJECT** | `"您的验证码是 - {{code}}"` | 邮箱验证邮件标题 | auth.email.verify_subject (社交登录 > Email > 邮箱验证邮件标题) |
| **ATK_AUTH_EMAIL_VERIFY_TPL** | `"default"` | 邮箱验证邮件模板 (填入文件路径使用自定义模板) | auth.email.verify_tpl (社交登录 > Email > 邮箱验证邮件模板) |
| **ATK_AUTH_ENABLED** | `false` | 启用社交登录 | auth.enabled (社交登录 > 启用社交登录) |
| **ATK_AUTH_FACEBOOK_CLIENT_ID** | `""` | ClientId | auth.facebook.client_id (社交登录 > Facebook > ClientId) |
| **ATK_AUTH_FACEBOOK_CLIENT_SECRET** | `""` | ClientSecret | auth.facebook.client_secret (社交登录 > Facebook > ClientSecret) |
| **ATK_AUTH_FACEBOOK_ENABLED** | `false` | 启用 | auth.facebook.enabled (社交登录 > Facebook > Enabled) |
| **ATK_AUTH_GITEA_CLIENT_ID** | `""` | ClientId | auth.gitea.client_id (社交登录 > Gitea > ClientId) |
| **ATK_AUTH_GITEA_CLIENT_SECRET** | `""` | ClientSecret | auth.gitea.client_secret (社交登录 > Gitea > ClientSecret) |
| **ATK_AUTH_GITEA_ENABLED** | `false` | 启用 | auth.gitea.enabled (社交登录 > Gitea > Enabled) |
| **ATK_AUTH_GITHUB_CLIENT_ID** | `""` | ClientId | auth.github.client_id (社交登录 > GitHub > ClientId) |
| **ATK_AUTH_GITHUB_CLIENT_SECRET** | `""` | ClientSecret | auth.github.client_secret (社交登录 > GitHub > ClientSecret) |
| **ATK_AUTH_GITHUB_ENABLED** | `false` | 启用 | auth.github.enabled (社交登录 > GitHub > Enabled) |
| **ATK_AUTH_GITLAB_CLIENT_ID** | `""` | ClientId | auth.gitlab.client_id (社交登录 > GitLab > ClientId) |
| **ATK_AUTH_GITLAB_CLIENT_SECRET** | `""` | ClientSecret | auth.gitlab.client_secret (社交登录 > GitLab > ClientSecret) |
| **ATK_AUTH_GITLAB_ENABLED** | `false` | 启用 | auth.gitlab.enabled (社交登录 > GitLab > Enabled) |
| **ATK_AUTH_GOOGLE_CLIENT_ID** | `""` | ClientId | auth.google.client_id (社交登录 > Google > ClientId) |
| **ATK_AUTH_GOOGLE_CLIENT_SECRET** | `""` | ClientSecret | auth.google.client_secret (社交登录 > Google > ClientSecret) |
| **ATK_AUTH_GOOGLE_ENABLED** | `false` | 启用 | auth.google.enabled (社交登录 > Google > Enabled) |
| **ATK_AUTH_LINE_CLIENT_ID** | `""` | ClientId | auth.line.client_id (社交登录 > Line > ClientId) |
| **ATK_AUTH_LINE_CLIENT_SECRET** | `""` | ClientSecret | auth.line.client_secret (社交登录 > Line > ClientSecret) |
| **ATK_AUTH_LINE_ENABLED** | `false` | 启用 | auth.line.enabled (社交登录 > Line > Enabled) |
| **ATK_AUTH_MASTODON_CLIENT_ID** | `""` | ClientId | auth.mastodon.client_id (社交登录 > Mastodon > ClientId) |
| **ATK_AUTH_MASTODON_CLIENT_SECRET** | `""` | ClientSecret | auth.mastodon.client_secret (社交登录 > Mastodon > ClientSecret) |
| **ATK_AUTH_MASTODON_ENABLED** | `false` | 启用 | auth.mastodon.enabled (社交登录 > Mastodon > Enabled) |
| **ATK_AUTH_MICROSOFT_CLIENT_ID** | `""` | ClientId | auth.microsoft.client_id (社交登录 > Microsoft > ClientId) |
| **ATK_AUTH_MICROSOFT_CLIENT_SECRET** | `""` | ClientSecret | auth.microsoft.client_secret (社交登录 > Microsoft > ClientSecret) |
| **ATK_AUTH_MICROSOFT_ENABLED** | `false` | 启用 | auth.microsoft.enabled (社交登录 > Microsoft > Enabled) |
| **ATK_AUTH_PATREON_CLIENT_ID** | `""` | ClientId | auth.patreon.client_id (社交登录 > Patreon > ClientId) |
| **ATK_AUTH_PATREON_CLIENT_SECRET** | `""` | ClientSecret | auth.patreon.client_secret (社交登录 > Patreon > ClientSecret) |
| **ATK_AUTH_PATREON_ENABLED** | `false` | 启用 | auth.patreon.enabled (社交登录 > Patreon > Enabled) |
| **ATK_AUTH_SLACK_CLIENT_ID** | `""` | ClientId | auth.slack.client_id (社交登录 > Slack > ClientId) |
| **ATK_AUTH_SLACK_CLIENT_SECRET** | `""` | ClientSecret | auth.slack.client_secret (社交登录 > Slack > ClientSecret) |
| **ATK_AUTH_SLACK_ENABLED** | `false` | 启用 | auth.slack.enabled (社交登录 > Slack > Enabled) |
| **ATK_AUTH_STEAM_API_KEY** | `""` | ApiKey | auth.steam.api_key (社交登录 > Steam > ApiKey) |
| **ATK_AUTH_STEAM_ENABLED** | `false` | 启用 | auth.steam.enabled (社交登录 > Steam > Enabled) |
| **ATK_AUTH_TIKTOK_CLIENT_ID** | `""` | ClientId | auth.tiktok.client_id (社交登录 > Tiktok > ClientId) |
| **ATK_AUTH_TIKTOK_CLIENT_SECRET** | `""` | ClientSecret | auth.tiktok.client_secret (社交登录 > Tiktok > ClientSecret) |
| **ATK_AUTH_TIKTOK_ENABLED** | `false` | 启用 | auth.tiktok.enabled (社交登录 > Tiktok > Enabled) |
| **ATK_AUTH_TWITTER_CLIENT_ID** | `""` | ClientId | auth.twitter.client_id (社交登录 > Twitter > ClientId) |
| **ATK_AUTH_TWITTER_CLIENT_SECRET** | `""` | ClientSecret | auth.twitter.client_secret (社交登录 > Twitter > ClientSecret) |
| **ATK_AUTH_TWITTER_ENABLED** | `false` | 启用 | auth.twitter.enabled (社交登录 > Twitter > Enabled) |
| **ATK_AUTH_WECHAT_CLIENT_ID** | `""` | ClientId | auth.wechat.client_id (社交登录 > 微信 > ClientId) |
| **ATK_AUTH_WECHAT_CLIENT_SECRET** | `""` | ClientSecret | auth.wechat.client_secret (社交登录 > 微信 > ClientSecret) |
| **ATK_AUTH_WECHAT_ENABLED** | `false` | 启用 | auth.wechat.enabled (社交登录 > 微信 > Enabled) |
## 缓存
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_CACHE_ENABLED** | `false` | 启用缓存 | cache.enabled (缓存 > 启用缓存) |
| **ATK_CACHE_EXPIRES** | `30` | 缓存过期时间 (单位:分钟) | cache.expires (缓存 > 缓存过期时间) |
| **ATK_CACHE_REDIS_DB** | `0` | 数据库编号 (例如使用零号数据库填写 0) | cache.redis.db (缓存 > Redis 配置 > 数据库编号) |
| **ATK_CACHE_REDIS_NETWORK** | `"tcp"` | 连接方式 (可选:`["tcp", "unix"]`) | cache.redis.network (缓存 > Redis 配置 > 连接方式) |
| **ATK_CACHE_REDIS_PASSWORD** | `""` | 密码 | cache.redis.password (缓存 > Redis 配置 > 密码) |
| **ATK_CACHE_REDIS_USERNAME** | `""` | 用户名 | cache.redis.username (缓存 > Redis 配置 > 用户名) |
| **ATK_CACHE_SERVER** | `""` | 缓存服务器地址 (例如:"localhost:6379") | cache.server (缓存 > 缓存服务器地址) |
| **ATK_CACHE_TYPE** | `"builtin"` | 缓存类型 (可选:`["redis", "memcache", "builtin"]`) | cache.type (缓存 > 缓存类型) |
| **ATK_CACHE_WARM_UP** | `false` | 缓存启动预热 (程序启动时预热缓存) | cache.warm_up (缓存 > 缓存启动预热) |
## 验证码
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_CAPTCHA_ACTION_LIMIT** | `3` | 激活验证码所需操作次数 | captcha.action_limit (验证码 > 激活验证码所需操作次数) |
| **ATK_CAPTCHA_ACTION_RESET** | `60` | 重置操作计数器超时 (单位:s, 设为 -1 不重置) | captcha.action_reset (验证码 > 重置操作计数器超时) |
| **ATK_CAPTCHA_ALWAYS** | `false` | 总是需要验证码 | captcha.always (验证码 > 总是需要验证码) |
| **ATK_CAPTCHA_CAPTCHA_TYPE** | `"image"` | 验证类型 (可选:`["image", "turnstile", "recaptcha", "hcaptcha", "geetest"]`) | captcha.captcha_type (验证码 > 验证类型) |
| **ATK_CAPTCHA_ENABLED** | `true` | 启用验证码 | captcha.enabled (验证码 > 启用验证码) |
| **ATK_CAPTCHA_GEETEST_CAPTCHA_ID** | `""` | CaptchaId | captcha.geetest.captcha_id (验证码 > Geetest 极验 > CaptchaId) |
| **ATK_CAPTCHA_GEETEST_CAPTCHA_KEY** | `""` | CaptchaKey | captcha.geetest.captcha_key (验证码 > Geetest 极验 > CaptchaKey) |
| **ATK_CAPTCHA_HCAPTCHA_SECRET_KEY** | `""` | SecretKey | captcha.hcaptcha.secret_key (验证码 > hCaptcha > SecretKey) |
| **ATK_CAPTCHA_HCAPTCHA_SITE_KEY** | `""` | SiteKey | captcha.hcaptcha.site_key (验证码 > hCaptcha > SiteKey) |
| **ATK_CAPTCHA_RECAPTCHA_SECRET_KEY** | `""` | SecretKey | captcha.recaptcha.secret_key (验证码 > reCaptcha > SecretKey) |
| **ATK_CAPTCHA_RECAPTCHA_SITE_KEY** | `""` | SiteKey | captcha.recaptcha.site_key (验证码 > reCaptcha > SiteKey) |
| **ATK_CAPTCHA_TURNSTILE_SECRET_KEY** | `""` | SecretKey | captcha.turnstile.secret_key (验证码 > Turnstile > SecretKey) |
| **ATK_CAPTCHA_TURNSTILE_SITE_KEY** | `""` | SiteKey | captcha.turnstile.site_key (验证码 > Turnstile > SiteKey) |
## 数据库
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_DB_CHARSET** | `"utf8mb4"` | 编码格式 | db.charset (数据库 > 编码格式) |
| **ATK_DB_FILE** | `"./data/artalk.db"` | 数据库文件 (仅 SQLite 数据库需填写) | db.file (数据库 > 数据库文件) |
| **ATK_DB_HOST** | `"localhost"` | 数据库地址 | db.host (数据库 > 数据库地址) |
| **ATK_DB_NAME** | `"artalk"` | 数据库名称 | db.name (数据库 > 数据库名称) |
| **ATK_DB_PASSWORD** | `""` | 数据库密码 | db.password (数据库 > 数据库密码) |
| **ATK_DB_PORT** | `3306` | 数据库端口 | db.port (数据库 > 数据库端口) |
| **ATK_DB_PREPARE_STMT** | `true` | 预编译语句 | db.prepare_stmt (数据库 > 预编译语句) |
| **ATK_DB_SSL** | `false` | 启用 SSL | db.ssl (数据库 > 启用 SSL) |
| **ATK_DB_TABLE_PREFIX** | `""` | 表前缀 (例如:"atk_") | db.table_prefix (数据库 > 表前缀) |
| **ATK_DB_TYPE** | `"sqlite"` | 数据库类型 (可选:`["sqlite", "mysql", "pgsql", "mssql"]`) | db.type (数据库 > 数据库类型) |
| **ATK_DB_USER** | `"root"` | 数据库账户 | db.user (数据库 > 数据库账户) |
## 邮件通知
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_EMAIL_ALI_DM_ACCESS_KEY_ID** | `""` | AccessKeyId | email.ali_dm.access_key_id (邮件通知 > 阿里云邮件推送 > AccessKeyId) |
| **ATK_EMAIL_ALI_DM_ACCESS_KEY_SECRET** | `""` | AccessKeySecret | email.ali_dm.access_key_secret (邮件通知 > 阿里云邮件推送 > AccessKeySecret) |
| **ATK_EMAIL_ALI_DM_ACCOUNT_NAME** | `"noreply@example.com"` | AccountName | email.ali_dm.account_name (邮件通知 > 阿里云邮件推送 > AccountName) |
| **ATK_EMAIL_ENABLED** | `false` | 启用邮件通知 | email.enabled (邮件通知 > 启用邮件通知) |
| **ATK_EMAIL_MAIL_SUBJECT** | `"[{{site_name}}] 您收到了来自 @{{reply_nick}} 的回复"` | 邮件标题 | email.mail_subject (邮件通知 > 邮件标题) |
| **ATK_EMAIL_MAIL_TPL** | `"default"` | 邮件模板文件 (填入文件路径使用自定义模板) | email.mail_tpl (邮件通知 > 邮件模板文件) |
| **ATK_EMAIL_SEND_ADDR** | `"noreply@example.com"` | 发信人地址 | email.send_addr (邮件通知 > 发信人地址) |
| **ATK_EMAIL_SEND_NAME** | `"{{reply_nick}}"` | 发信人昵称 | email.send_name (邮件通知 > 发信人昵称) |
| **ATK_EMAIL_SEND_TYPE** | `"smtp"` | 发送方式 (可选:`["smtp", "ali_dm", "sendmail"]`) | email.send_type (邮件通知 > 发送方式) |
| **ATK_EMAIL_SMTP_HOST** | `"smtp.qq.com"` | 发件地址 | email.smtp.host (邮件通知 > SMTP 发送 > 发件地址) |
| **ATK_EMAIL_SMTP_PASSWORD** | `""` | 密码 | email.smtp.password (邮件通知 > SMTP 发送 > 密码) |
| **ATK_EMAIL_SMTP_PORT** | `587` | 发件端口 | email.smtp.port (邮件通知 > SMTP 发送 > 发件端口) |
| **ATK_EMAIL_SMTP_USERNAME** | `"example@qq.com"` | 用户名 | email.smtp.username (邮件通知 > SMTP 发送 > 用户名) |
## 界面配置
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_FRONTEND_DARKMODE** | `"inherit"` | 夜间模式 (可选:`["inherit", "auto"]`) | frontend.darkMode (界面配置 > 夜间模式) |
| **ATK_FRONTEND_EDITORTRAVEL** | `true` | 评论框穿梭 | frontend.editorTravel (界面配置 > 评论框穿梭) |
| **ATK_FRONTEND_EMOTICONS** | `"https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json"` | 表情包 | frontend.emoticons (界面配置 > 表情包) |
| **ATK_FRONTEND_FLATMODE** | `"auto"` | 平铺模式 (可选:`["auto", "true", "false"]`) | frontend.flatMode (界面配置 > 平铺模式) |
| **ATK_FRONTEND_GRAVATAR_MIRROR** | `"https://weavatar.com/avatar/"` | API 地址 | frontend.gravatar.mirror (界面配置 > 头像 Gravatar > API 地址) |
| **ATK_FRONTEND_GRAVATAR_PARAMS** | `"sha256=1&d=mp&s=240"` | API 参数 | frontend.gravatar.params (界面配置 > 头像 Gravatar > API 参数) |
| **ATK_FRONTEND_HEIGHTLIMIT_CHILDREN** | `400` | 子评论区域限高 (单位:px) | frontend.heightLimit.children (界面配置 > 内容限高 > 子评论区域限高) |
| **ATK_FRONTEND_HEIGHTLIMIT_CONTENT** | `300` | 评论内容限高 (单位:px) | frontend.heightLimit.content (界面配置 > 内容限高 > 评论内容限高) |
| **ATK_FRONTEND_HEIGHTLIMIT_SCROLLABLE** | `false` | 滚动限高 (允许限高区域滚动) | frontend.heightLimit.scrollable (界面配置 > 内容限高 > 滚动限高) |
| **ATK_FRONTEND_IMGLAZYLOAD** | `false` | 图片懒加载 (可选:`["false", "native", "data-src"]`) | frontend.imgLazyLoad (界面配置 > 图片懒加载) |
| **ATK_FRONTEND_LISTSORT** | `true` | 评论排序功能 | frontend.listSort (界面配置 > 评论排序功能) |
| **ATK_FRONTEND_NESTMAX** | `2` | 最大嵌套层数 | frontend.nestMax (界面配置 > 最大嵌套层数) |
| **ATK_FRONTEND_NESTSORT** | `"DATE_ASC"` | 嵌套评论排序规则 (可选:`["DATE_ASC", "DATE_DESC", "VOTE_UP_DESC"]`) | frontend.nestSort (界面配置 > 嵌套评论排序规则) |
| **ATK_FRONTEND_NOCOMMENT** | `""` | 无评论显示文字 | frontend.noComment (界面配置 > 无评论显示文字) |
| **ATK_FRONTEND_PAGINATION_AUTOLOAD** | `true` | 滚动加载 | frontend.pagination.autoLoad (界面配置 > 评论分页 > 滚动加载) |
| **ATK_FRONTEND_PAGINATION_PAGESIZE** | `20` | 每页评论数 | frontend.pagination.pageSize (界面配置 > 评论分页 > 每页评论数) |
| **ATK_FRONTEND_PAGINATION_READMORE** | `true` | 加载更多模式 (关闭则使用分页条) | frontend.pagination.readMore (界面配置 > 评论分页 > 加载更多模式) |
| **ATK_FRONTEND_PLACEHOLDER** | `""` | 评论框占位文字 | frontend.placeholder (界面配置 > 评论框占位文字) |
| **ATK_FRONTEND_PLUGINURLS** | `[]` | 插件 | frontend.pluginURLs (界面配置 > 插件) |
| **ATK_FRONTEND_PREVIEW** | `true` | 编辑器实时预览功能 | frontend.preview (界面配置 > 编辑器实时预览功能) |
| **ATK_FRONTEND_REQTIMEOUT** | `15000` | 请求超时 (单位:毫秒) | frontend.reqTimeout (界面配置 > 请求超时) |
| **ATK_FRONTEND_SENDBTN** | `""` | 发送按钮文字 | frontend.sendBtn (界面配置 > 发送按钮文字) |
| **ATK_FRONTEND_UABADGE** | `false` | 用户 UA 徽标 | frontend.uaBadge (界面配置 > 用户 UA 徽标) |
| **ATK_FRONTEND_VERSIONCHECK** | `true` | 版本检测 | frontend.versionCheck (界面配置 > 版本检测) |
| **ATK_FRONTEND_VOTE** | `true` | 投票按钮 | frontend.vote (界面配置 > 投票按钮) |
| **ATK_FRONTEND_VOTEDOWN** | `false` | 反对按钮 | frontend.voteDown (界面配置 > 反对按钮) |
## 服务器
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_HTTP_BODY_LIMIT** | `100` | 请求体大小限制 (单位:MB) | http.body_limit (服务器 > 请求体大小限制) |
| **ATK_HTTP_PROXY_HEADER** | `""` | 代理标头名 (当使用 CDN 时填写 `X-Forwarded-For` 获取用户真实 IP) | http.proxy_header (服务器 > 代理标头名) |
## 图片上传
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_IMG_UPLOAD_ENABLED** | `true` | 启用图片上传 | img_upload.enabled (图片上传 > 启用图片上传) |
| **ATK_IMG_UPLOAD_MAX_SIZE** | `5` | 图片大小限制 (单位:MB) | img_upload.max_size (图片上传 > 图片大小限制) |
| **ATK_IMG_UPLOAD_PATH** | `"./data/artalk-img/"` | 图片存放路径 | img_upload.path (图片上传 > 图片存放路径) |
| **ATK_IMG_UPLOAD_PUBLIC_PATH** | `<nil>` | 图片链接基础路径 (默认为 "/static/images/") | img_upload.public_path (图片上传 > 图片链接基础路径) |
| **ATK_IMG_UPLOAD_UPGIT_DEL_LOCAL** | `true` | 上传后删除本地的图片 | img_upload.upgit.del_local (图片上传 > Upgit 配置 > 上传后删除本地的图片) |
| **ATK_IMG_UPLOAD_UPGIT_ENABLED** | `false` | 启用 Upgit | img_upload.upgit.enabled (图片上传 > Upgit 配置 > 启用 Upgit) |
| **ATK_IMG_UPLOAD_UPGIT_EXEC** | `"upgit -c <upgit配置文件路径> -t /artalk-img"` | 命令行参数 | img_upload.upgit.exec (图片上传 > Upgit 配置 > 命令行参数) |
## IP 属地
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_IP_REGION_DB_PATH** | `"./data/ip2region.xdb"` | 数据文件路径 (.xdb 格式) | ip_region.db_path (IP 属地 > 数据文件路径) |
| **ATK_IP_REGION_ENABLED** | `false` | 启用 IP 属地展示 | ip_region.enabled (IP 属地 > 启用 IP 属地展示) |
| **ATK_IP_REGION_PRECISION** | `"province"` | 显示精度 (可选:`["province", "city", "country"]`) | ip_region.precision (IP 属地 > 显示精度) |
## 日志
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_LOG_ENABLED** | `true` | 启用日志 | log.enabled (日志 > 启用日志) |
| **ATK_LOG_FILENAME** | `"./data/artalk.log"` | 日志文件路径 | log.filename (日志 > 日志文件路径) |
## 评论审核
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_MODERATOR_AKISMET_KEY** | `""` | Akismet Key (Akismet 反垃圾服务,https://akismet.com) | moderator.akismet_key (评论审核 > Akismet Key) |
| **ATK_MODERATOR_ALIYUN_ACCESS_KEY_ID** | `""` | AccessKeyId | moderator.aliyun.access_key_id (评论审核 > 阿里云内容安全 > AccessKeyId) |
| **ATK_MODERATOR_ALIYUN_ACCESS_KEY_SECRET** | `""` | AccessKeySecret | moderator.aliyun.access_key_secret (评论审核 > 阿里云内容安全 > AccessKeySecret) |
| **ATK_MODERATOR_ALIYUN_ENABLED** | `false` | 启用 | moderator.aliyun.enabled (评论审核 > 阿里云内容安全 > Enabled) |
| **ATK_MODERATOR_ALIYUN_REGION** | `"cn-shanghai"` | Region | moderator.aliyun.region (评论审核 > 阿里云内容安全 > Region) |
| **ATK_MODERATOR_API_FAIL_BLOCK** | `false` | API 请求错误时拦截 (关闭此项当请求错误时让评论放行) | moderator.api_fail_block (评论审核 > API 请求错误时拦截) |
| **ATK_MODERATOR_KEYWORDS_ENABLED** | `false` | 启用 | moderator.keywords.enabled (评论审核 > 关键词过滤 > Enabled) |
| **ATK_MODERATOR_KEYWORDS_FILE_SEP** | `"\n"` | 词库文件内容分割符 (例如填写 "\n" 文件中一行一个关键词) | moderator.keywords.file_sep (评论审核 > 关键词过滤 > 词库文件内容分割符) |
| **ATK_MODERATOR_KEYWORDS_FILES** | `[./data/词库_1.txt]` | 词库文件 (支持多个词库文件) | moderator.keywords.files (评论审核 > 关键词过滤 > 词库文件) |
| **ATK_MODERATOR_KEYWORDS_PENDING** | `false` | 匹配成功设为待审状态 | moderator.keywords.pending (评论审核 > 关键词过滤 > 匹配成功设为待审状态) |
| **ATK_MODERATOR_KEYWORDS_REPLACE_TO** | `"x"` | 替换字符 | moderator.keywords.replace_to (评论审核 > 关键词过滤 > 替换字符) |
| **ATK_MODERATOR_PENDING_DEFAULT** | `false` | 默认待审 (发表新评论需要后台人工审核后才能显示) | moderator.pending_default (评论审核 > 默认待审) |
| **ATK_MODERATOR_TENCENT_ENABLED** | `false` | 启用 | moderator.tencent.enabled (评论审核 > 腾讯云文本内容安全 > Enabled) |
| **ATK_MODERATOR_TENCENT_REGION** | `"ap-guangzhou"` | Region | moderator.tencent.region (评论审核 > 腾讯云文本内容安全 > Region) |
| **ATK_MODERATOR_TENCENT_SECRET_ID** | `""` | SecretId | moderator.tencent.secret_id (评论审核 > 腾讯云文本内容安全 > SecretId) |
| **ATK_MODERATOR_TENCENT_SECRET_KEY** | `""` | SecretKey | moderator.tencent.secret_key (评论审核 > 腾讯云文本内容安全 > SecretKey) |
## SSL
| 环境变量 | 默认值 | 描述 | 路径 |
| --- | --- | --- | --- |
| **ATK_SSL_CERT_PATH** | `""` | 证书文件路径 | ssl.cert_path (SSL > 证书文件路径) |
| **ATK_SSL_ENABLED** | `false` | 启用 SSL | ssl.enabled (SSL > 启用 SSL) |
| **ATK_SSL_KEY_PATH** | `""` | 密钥文件路径 | ssl.key_path (SSL > 密钥文件路径) |
<!-- /env-variables -->
</div>
## 开发者
通过 `ATK_DEBUG=1` 启用开发者模式。
本文档由 Artalk 开发者工具自动生成,执行 `make update-conf-docs` 根据模版配置文件 ([conf/artalk.example.zh-CN.yml](https://github.com/ArtalkJS/Artalk/tree/master/conf/artalk.example.zh-CN.yml)) 中的注释更新本页内容。
相关代码位于 [@ArtalkJS/Artalk:/internal/config/](https://github.com/ArtalkJS/Artalk/tree/master/internal/config/) 目录。
+2 -3
View File
@@ -15,6 +15,7 @@ Artalk 离不开社区的支持与帮助,**是你们让 Artalk 走得更远!
- [Fly.io 部署 Artalk 评论系统](https://wayjam.me/posts/artalk-deploy-on-flyio/)
- [Railway.app 部署 Artalk 评论系统](https://blog.moraxyc.com/post/eidb8276/)
- [Render.com 部署Artalk自托管评论系统](https://www.leenhawk.com/posts/3932123804/)
- [在 Valaxy 中使用 Artalk 作为评论系统](https://www.lihaoyu.cn/posts/use-artalk-in-valaxy)
更多新版读物正在撰写当中...
@@ -26,16 +27,14 @@ Artalk v1 版本基于 [PHP 后端](https://github.com/ArtalkJS/ArtalkPHP),部
:::
- [[!!!] 一个 Artalk 的非官方文档 (By @thun888)](https://blog.thun888.xyz/wiki/Artalk/)
- [[!!!] 一个 Artalk 的非官方文档 (By @thun888)](https://blog.hzchu.top/wiki/Artalk-doc/)
- [为 Gridsome 添加 Artalk 自托管评论系统 - Monstx's Blog](https://blog.monsterx.cn/code/use-self-hosted-comment-system-in-gridsome/)
- [Artalk 自托管评论系统的后端部署 - Jalen's Blog](https://blog.jalenchuh.cn/posts/artalk-api-php/)
- [无服务器搭建 Artalk 评论系统后端 - 陈YFの博客](https://blog.cyfan.top/p/480ab6ed.html)
- [哔哩哔哩 [站内首发] Artalk 评论系统搭建教程 - @thun888](https://www.bilibili.com/s/video/BV1954y1E7uP)
- [Hexo Next 主题添加 Artalk 评论系统 - 心底的河流](https://lhy.life/20201126-artalk-next/)
- [Hexo 添加 Artalk 评论教程 - 我相信我可以](https://butterfly.imlete.cn/article/Hexo-Artalk.html)
- [基于 Butterfly 主题添加 Artalk 评论系统 - 卓越科技的 Blog](https://blog.imzykj.cn/posts/93afb348/)
## 衍生品
- [Artalk:一款 ~~简洁~~ 有趣的自托管评论系统 (By monsterxcn)](https://github.com/monsterxcn/Artalk)
+76
View File
@@ -0,0 +1,76 @@
# 社交登录
Artalk 默认只需填写昵称和邮箱即可发表评论,无需验证邮箱。
但有时候,我们希望用户能够使用社交账号登录,以减少用户填写信息的时间,或者提高用户信息的真实性,可以通过启用社交登录来实现这一目的。
社交登录目前支持以下多种方式:
| 登录方式 | 接入文档 | 登录方式 | 接入文档 | 登录方式 | 接入文档 |
| --- | --- | --- | --- | --- | --- |
| Google | [查看](https://developers.google.com/identity/protocols/oauth2) | Microsoft | [查看](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow) | Apple | [查看](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/configuring_your_webpage_for_sign_in_with_apple) |
| Facebook | [查看](https://developers.facebook.com/docs/facebook-login/) | Twitter | [查看](https://developer.twitter.com/en/docs/basics/authentication/overview) | Discord | [查看](https://discord.com/developers/docs/topics/oauth2) |
| Slack | [查看](https://api.slack.com/authentication/oauth-v2) | Github | [查看](https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/) | Tiktok | [查看](https://developers.tiktok.com/doc/login) |
| Steam | [查看](https://partner.steamgames.com/doc/webapi_overview/auth) | WeChat | [查看](https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html) | Line | [查看](https://developers.line.biz/en/docs/line-login/integrate-line-login/) |
| GitLab | [查看](https://docs.gitlab.com/ee/api/oauth2.html) | Gitea | [查看](https://docs.gitea.io/en-us/oauth2-provider/) | Mastodon | [查看](https://docs.joinmastodon.org/api/authentication/) |
| Patreon | [查看](https://docs.patreon.com/#oauth) | Auth0 | [查看](https://auth0.com/docs/connections/social/) | 邮箱密码 | [查看](#邮箱密码登录) |
开启社交登录功能仅需在 [控制中心](/guide/frontend/sidebar.md#设置) 找到「社交登录」启用该功能,然后填写对应的配置信息即可。也可以通过 [配置文件](/guide/backend/config.md) 或 [环境变量](/guide/env.md#社交登录) 进行配置。
## 邮箱密码登录
![邮箱登录](../../images/auth/email_login.png)
启用邮箱密码登录后,评论框顶部的昵称邮箱输入框将被隐藏,发送按钮将显示为登录按钮。用户点击登录按钮后,将会弹出一个登录框,用户可以输入邮箱和密码登录,登录成功后即可发表评论。并且,用户发表的评论将展示「邮箱已验证」的标识。
<img src="../../images/auth/email_verified.png" width="550" alt="邮箱已验证标识">
用户可以通过邮箱注册账号,Artalk 将向用户邮箱发送一封带有验证码的邮件。验证码有效期为 10 分钟,验证码发送频率限制为 1 分钟一次。
![邮箱注册](../../images/auth/email_register.png)
支持自定义验证码邮件模板和邮件标题,可在 Artalk 控制中心的设置页面的社交登录找到「邮箱验证邮件标题」、「邮箱验证邮件模板」选项进行设置。在配置文件中,可以通过 `auth.email.verify_subject` 和 `auth.email.verify_tpl` 进行设置:
```yaml
auth:
enabled: true
email:
enabled: true
verify_subject: "您的验证码是 - {{code}}"
verify_tpl: default
```
默认模版如下:
```html
您的验证码是:{{code}}。请使用它来验证您的电子邮件并登录到 Artalk。如果您没有请求此操作,请忽略此消息。
```
![跳过登录](../../images/auth/login_skip.png)
启用邮箱密码登录功能后,仍然可跳过邮箱验证:登录弹窗底部显示 “跳过,不验证” 按钮,点击后评论框顶部恢复为显示原有的昵称、邮箱、网址三个输入框。在设置中勾选「允许匿名评论」可以更改。
## 账号合并工具
登录后如果检测到相同的邮箱下有多个不同用户名的账号,将会弹出账号合并工具,用户可以选择保留其中一个用户名,该邮箱下的所有评论等数据合并到保留的账号下。原有的账号将被删除,评论显示的用户名将会变更为保留的用户名。
![账号合并工具](../../images/auth/merge_accounts.png)
## 多种登录方式
Artalk 支持同时启用多种登录方式,用户可以选择任意一种方式登录。
![多种登录方式](../../images/auth/multi_login.png)
如果只启用了唯一一种登录,例如 GitHub 登录,将直接弹出 GitHub 的授权登录页面。
![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」选项中即可。
## 插件开发
Artalk 的社交登录功能是通过独立的插件实现并采用 Solid.js 开发,代码可在 [@ArtalkJS/Artalk:ui/plugin-auth](https://github.com/ArtalkJS/Artalk/tree/master/ui/plugin-auth) 找到。
在控制中心启用社交登录功能后,将自动在前端加载该插件。
+86 -39
View File
@@ -1,20 +1,33 @@
# 前端配置
# 界面配置
可在「[控制中心](/guide/frontend/sidebar.md)」修改界面配置,而无需改动前端代码。另外也支持 [配置文件](/guide/backend/config.md#界面配置-frontend) 和 [环境变量](/guide/env.md#界面配置)。
界面配置的优先级如下:
```
环境变量 > 配置文件 = 控制中心 > 前端代码
```
## 通过 `Artalk.init` 配置界面
在前端页面调用 `Artalk.init` 初始化时传入参数来配置界面,本文列出了所有可用的配置项。
```js
const artalk = Artalk.init({ ... })
const artalk = Artalk.init({
el: '#Comments',
pageKey: '/post/1',
pageTitle: '页面标题',
server: 'http://your_domain:8080',
site: 'Artalk 的博客',
})
// 更新配置
artalk.update({ ... })
```
- 默认配置:[defaults.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/defaults.ts)
- 声明文件:[config.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk/src/types/config.ts)
## 轻松配置
推荐在侧边栏 “[控制中心](/guide/frontend/sidebar.md)” 通过图形界面修改前端的配置,而无需在代码中对界面进行设定。
注:前端的设定可能会被后端覆盖,更多内容参考:[在后端控制前端](/guide/backend/fe-control.md)
## 基本配置(必填项)
### el
@@ -59,12 +72,6 @@ artalk.update({ ... })
> 例如:http://yourdomain.xxx
::: warning 更新注意
v2.2.6+ 的后续版本,请填入不带 `/api/` 路径的后端 URL。
:::
### site
**站点名称**
@@ -72,20 +79,16 @@ v2.2.6+ 的后续版本,请填入不带 `/api/` 路径的后端 URL。
- 类型:`String`
- 默认值:`undefined`
可留空使用后端配置的 “默认站点”,
Artalk 支持多站点统一管理,此项用于站点隔离。
### useBackendConf
**跟随后端的配置**
**引用后端的配置**
- 类型:`Boolean`
- 默认值:`true`(默认启用)
可以在后端的配置文件中定义前端的配置,让前端配置始终跟随后端。
详情可参考:[在后端控制前端](/guide/backend/fe-control)
可以在后端的配置文件中定义前端的配置,让前端配置始终引用后端。
## 国际化 (i18n)
@@ -102,6 +105,28 @@ Artalk 支持多站点统一管理,此项用于站点隔离。
详情参考:[多语言](./i18n.md)
### dateFormatter
**时间格式化函数**
- 类型:`(date: Date) => string`
- 默认值:`undefined`
默认显示几秒前、几分钟前、几小时前、几天前,如果超过 7 天则显示具体日期,格式为 `YYYY-MM-DD`。
你也可以自定义时间格式化函数,以下的例子演示了使用 [toLocaleString](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) 和 [dayjs](https://day.js.org/) 格式化时间。
```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'
},
})
```
## 请求
### reqTimeout
@@ -128,10 +153,6 @@ Artalk 支持多站点统一管理,此项用于站点隔离。
设置为 `false` 关闭表情包功能。
:::warning 请替换 CDN 资源
JS DELIVR 在中国大陆的 [ICP 牌照已被吊销](https://github.com/jsdelivr/jsdelivr/issues/18348#issuecomment-997777996)。
:::
## 界面
### placeholder
@@ -218,34 +239,45 @@ artalk.setDarkMode(true)
### pvEl
**页面浏览量 (PV) 绑定元素**
**页面浏览量 (PV) 绑定元素**
- 类型:`String`
- 默认值:`"#ArtalkPV"`
- 默认值:`".artalk-pv-count"`
你可以在页面任意位置,放置 HTML 标签:`<span id="ArtalkPV"></span>`
你可以在页面任意位置,放置 HTML 标签:`<span class="artalk-pv-count"></span>`
当 Artalk 完成加载时展示页面的浏览量。
该项填入绑定元素的 Selector,默认为 `#ArtalkPV`。
该项填入绑定元素的 Selector,默认为 `.artalk-pv-count`。
### countEl
**评论数绑定元素**
**评论数绑定元素**
- 类型:`String`
- 默认值:`"#ArtalkCount"`
- 默认值:`".artalk-comment-count"`
你可以在页面任意位置,放置 HTML 标签:`<span id="ArtalkCount"></span>` 显示当前页面的评论数。
你可以在页面任意位置,放置 HTML 标签:`<span class="artalk-comment-count"></span>` 显示当前页面的评论数。
::: tip
pvEl 和 countEl 元素标签都可以设置 `data-page-key` 属性值,来指定显示某个页面的统计数目,例如:`<span id="ArtalkCount" data-page-key="/t/1.html"></span>`
pvEl 和 countEl 元素标签都可以设置 `data-page-key` 属性值,来指定显示某个页面的统计数目,例如:`<span class="artalk-comment-count" data-page-key="/t/1.html"></span>`
详情参考:[浏览量统计](./pv.md#显示多个页面的浏览量)
详情参考:[浏览量统计](./pv.md#同时加载多个页面的统计数)
:::
### statPageKeyAttr
**统计组件 PageKey 属性名**
- 类型:`String`
- 默认值:`"data-page-key"`
Artalk 统计组件查询评论数和浏览量时,会通过该属性名来查询指定页面,例如:`<span data-page-key="/t/1.html"></span>`。
为了便于主题适配,可根据需要自定义属性名,例如将其替换为 `data-path`,则 HTML 标签为 `<span data-path="/t/1.html"></span>`。
### vote
**投票按钮**
@@ -304,16 +336,27 @@ Artalk.init({
const form = new FormData()
form.set('file', file)
const imgUrl = await fetch("https://api.example.org/upload", {
const imgUrl = await fetch('https://api.example.org/upload', {
method: 'POST',
body: form
body: form,
})
return imgUrl
}
},
})
```
### imgLazyLoad
**图片懒加载**
- 类型:`"native"|"data-src"|Boolean`
- 默认值:`false`
为评论中的图片启用懒加载功能。
详情参考:[图片懒加载](./img-lazy-load.md)
### preview
**编辑器实时预览功能**
@@ -337,12 +380,14 @@ gravatar: {
**Gravatar 镜像地址**
- 类型:`String`
- 默认值:`"https://sdn.geekzu.org/avatar/"`
- 默认值:`"https://www.gravatar.com/avatar/"`
如果你觉得 Gravatar 头像加载速度不理想,可以尝试替换。
例如:
> WeAvatar:https://weavatar.com/avatar/
>
> Cravatar:https://cravatar.cn/avatar/
>
> V2EX:https://cdn.v2ex.com/gravatar/
@@ -356,7 +401,7 @@ gravatar: {
**Gravatar API 参数**
- 类型:`String`
- 默认值:`"d=mp&s=240"`
- 默认值:`"sha256=1&d=mp&s=240"`
例如,你可以通过该配置项设置默认头像 (`d=mp`) 和头像尺寸 (`s=240`)。
@@ -366,6 +411,8 @@ gravatar: {
::: warning 更新注意
v2.8.7 支持通过 SHA256 加密算法生成 Gravatar 头像链接,以提高用户隐私保护,请在 `params` 中填入 `sha256=1` 启用该加密([#874](https://github.com/ArtalkJS/Artalk/issues/874))。
v2.5.5 已废弃 `gravatar.default` 配置项,请使用 `gravatar.params` 替代。
:::
@@ -383,7 +430,7 @@ v2.5.5 已废弃 `gravatar.default` 配置项,请使用 `gravatar.params` 替
Artalk.init({
avatarURLBuilder: (comment) => {
return `/api/avatar?email=${comment.email_encrypted}`
}
},
})
```
+82 -74
View File
@@ -1,10 +1,12 @@
# 表情包
编辑后端 `artalk.yml` 配置文件并修改配置项 `frontend.emoticons` 填入表情包列表 URL:
你可以在 [控制中心](/guide/frontend/sidebar.md#设置) 的设置界面修改此配置,也可以通过 [配置文件](../backend/config.md#界面配置-frontend) 或 [环境变量](../env.md#界面配置) 进行配置。
在配置文件中,可在 `frontend.emoticons` 填入表情包列表 URL:
```yaml
frontend:
emoticons: "https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json"
emoticons: https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json
```
## 表情包预设
@@ -21,66 +23,70 @@ Artalk 的表情包功能借鉴了其优秀的设计,并且 Artalk 原生适
```yaml
frontend:
emoticons: "https://raw.githubusercontent.com/DIYgod/OwO/master/demo/OwO.json"
# 直接食用 OwO 格式的表情包 ↑↑
emoticons: https://raw.githubusercontent.com/DIYgod/OwO/master/demo/OwO.json
# 直接使用 OwO 格式的表情包 ↑↑
```
社区也有许多可以直接食用的 OwO 格式表情包资源,例如:[@2X-ercha/Twikoo-Magic](https://github.com/2X-ercha/Twikoo-Magic)。
社区也有许多可以直接使用的 OwO 格式表情包资源,例如:[@2X-ercha/Twikoo-Magic](https://github.com/2X-ercha/Twikoo-Magic)。
### Artalk 表情包列表文件标准格式
Artalk 除了支持 OwO 格式外,还内置支持一种标准的表情包列表文件格式:
```js
[{
"name": "颜表情",
"type": "emoticon", // 字符类型
"items": [
{ "key": "Hi", "val": "|´・ω・)ノ" },
{ "key": "开心", "val": "ヾ(≧∇≦*)ゝ" },
//...
]
}, {
"name": "滑稽",
"type": "image", // 图片类型
"items": [
{
"key": "原味稽",
"val": "<图片 URL>"
},
//...
]
}]
[
{
name: '颜表情',
type: 'emoticon', // 字符类型
items: [
{ key: 'Hi', val: '|´・ω・)ノ' },
{ key: '开心', val: 'ヾ(≧∇≦*)ゝ' },
//...
],
},
{
name: '滑稽',
type: 'image', // 图片类型
items: [
{
key: '原味稽',
val: '<图片 URL>',
},
//...
],
},
]
```
## 前端配置
::: warning
前端的配置可能会被后端所覆盖,详情参考:[在后端控制前端](/guide/backend/fe-control.html)
:::
在前端配置表情包列表,例如:
```js
Artalk.init({
// 默认表情包列表,动态引入 ↓↓
emoticons: "https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json",
// 默认表情包列表,动态引入 ↓↓
emoticons:
'https://raw.githubusercontent.com/ArtalkJS/Emoticons/master/grps/default.json',
})
```
::: tip
配置文件和控制中心的表情包设置优先级高于前端配置。
:::
## 关闭表情包
你可以将 `emoticons` 设置为 `false` 来禁用表情包功能:
```js
Artalk.init({
emoticons: false
emoticons: false,
})
```
## 加载方式
### 动态加载
@@ -89,7 +95,7 @@ Artalk.init({
```js
Artalk.init({
emoticons: "<表情包数据文件 URL>",
emoticons: '<表情包数据文件 URL>',
})
```
@@ -101,25 +107,28 @@ Artalk.init({
```js
Artalk.init({
emoticons: [{
"name": "颜表情",
"type": "emoticon", // 字符类型
"items": [
{ "key": "Hi", "val": "|´・ω・)ノ" },
{ "key": "开心", "val": "ヾ(≧∇≦*)ゝ" },
//...
]
}, {
"name": "滑稽",
"type": "image", // 图片类型
"items": [
{
"key": "原味稽",
"val": "<图片 URL>"
},
//...
]
}],
emoticons: [
{
name: '颜表情',
type: 'emoticon', // 字符类型
items: [
{ key: 'Hi', val: '|´・ω・)ノ' },
{ key: '开心', val: 'ヾ(≧∇≦*)ゝ' },
//...
],
},
{
name: '滑稽',
type: 'image', // 图片类型
items: [
{
key: '原味稽',
val: '<图片 URL>',
},
//...
],
},
],
})
```
@@ -129,20 +138,20 @@ Artalk 支持 **动态**、**静态** 混合加载,例如:
```js
Artalk.init({
emoticons: [
// 动态加载
"https://raw.githubusercontent.com/DIYgod/OwO/master/demo/OwO.json", // OwO 格式表情包
"https://raw.githubusercontent.com/qwqcode/huaji/master/huaji.json",
// 静态加载
{
"name": "表情包名字",
"type": "emoticon", // 字符类型
"items": [
{ "key": "去吧大师球", "val": "(╯°A°)╯︵○○○" },
//...
]
}
]
emoticons: [
// 动态加载
'https://raw.githubusercontent.com/DIYgod/OwO/master/demo/OwO.json', // OwO 格式表情包
'https://raw.githubusercontent.com/qwqcode/huaji/master/huaji.json',
// 静态加载
{
name: '表情包名字',
type: 'emoticon', // 字符类型
items: [
{ key: '去吧大师球', val: '(╯°A°)╯︵○○○' },
//...
],
},
],
})
```
@@ -152,9 +161,7 @@ Artalk 支持远程表情包资源中**嵌套引入**另外的表情包资源,
```js
Artalk.init({
emoticons: [
"https://example.org/表情包.json"
]
emoticons: ['https://example.org/表情包.json'],
})
```
@@ -162,10 +169,11 @@ Artalk.init({
```json
[
"https://example.org/其他表情包.json",
"https://example.org/其他表情包.json",
//...
{
// Artalk 格式、OwO 格式
//...
{ // Artalk 格式、OwO 格式
//...
}
}
]
```
+21 -15
View File
@@ -1,30 +1,36 @@
# 多语言
在配置文件 `artalk.yml` 中设置:
你可以在 Artalk 控制中心的设置页面选择语言,或通过环境变量 `ATK_LOCALE` 和配置文件 `artalk.yml` 的 `locale` 配置项设置 Artalk 的语言。
```yaml
locale: "zh-CN"
```yml
locale: zh-CN
```
locale 配置项格式遵循 Unicode BCP 47 规范,默认为 "zh-CN" (简体中文)。
`locale` 配置项格式遵循 [Unicode BCP 47](https://www.techonthenet.com/js/language_tags.php) 规范,默认为 "zh-CN" (简体中文)。
---
目前 Artalk 支持语言如下:
- "en" (English)
- "zh-CN" (简体中文)
- "en-US" (English)
- "zh-TW" (繁体中文)
- "ja" (日本語)
- "ko" (한국어)
- "fr" (Français)
- "ru" (Русский)
## 贡献翻译
欢迎提交 PR 帮助翻译 Artalk 的多语言,为社区贡献一份力量!
|翻译内容|语言文件目录|模板文件|
|-|-|-|
|后端程序|[/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)|
|前端界面|[/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)|
|配置文件|[/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)
|说明文档|[/docs/[LANG]/**\/*.md](https://github.com/ArtalkJS/Artalk/tree/master/docs)|[/docs/**\/*.md](https://github.com/ArtalkJS/Artalk/tree/master/docs)
| 翻译内容 | 语言文件目录 | 模板文件 |
| -------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| 后端程序 | [/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) |
| 前端界面 | [/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) |
| 后台界面 | [/ui/artalk-sidebar/src/i18n/[LANG].ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk-sidebar/src/i18n) | [zh-CN.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/artalk-sidebar/src/i18n/zh-CN.ts) |
| 配置文件 | [/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) |
| 说明文档 | [/docs/[LANG]/\*\*/\*.md](https://github.com/ArtalkJS/Artalk/tree/master/docs) | [/docs/\*\*/\*.md](https://github.com/ArtalkJS/Artalk/tree/master/docs) |
更多参考:[开发文档](../../develop/index.md) / [CONTRIBUTING.md](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md#translation)
@@ -36,7 +42,7 @@ locale 配置项格式遵循 Unicode BCP 47 规范,默认为 "zh-CN" (简体
```js
Artalk.init({
locale: 'en-US'
locale: 'en-US',
})
```
@@ -46,7 +52,7 @@ Artalk.init({
```js
Artalk.init({
locale: "auto"
locale: 'auto',
})
```
@@ -57,8 +63,8 @@ Artalk.init({
```js
Artalk.init({
locale: {
placeholder: 'こんにちは',
email: 'Eメール',
//...
}
},
})
```
+53
View File
@@ -0,0 +1,53 @@
# 图片懒加载
Artalk 支持为评论中的图片添加懒加载功能,以减少页面加载时间。该功能默认禁用,可在控制中心「设置 - 界面配置」找到「图片懒加载」配置项 (frontend.imgLazyLoad):
| 配置值 | 说明 |
| --- | --- |
| `native` | 使用浏览器原生的图片懒加载 |
| `data-src` | 使用懒加载库实现图片懒加载 |
| `false` | 禁用图片懒加载 |
## 浏览器原生
当图片懒加载设置为 `native` 时,Artalk 将使用浏览器原生的图片懒加载功能,即为图片标签添加 `loading="lazy"` 属性。例如:
```html
<img src="1.png" loading="lazy" />
```
这不需要额外引入库和编写代码,是最简单的方式,但部分浏览器可能不支持该属性,或者实现的懒加载策略不同,详情参考:[MDN - 懒加载](https://developer.mozilla.org/zh-CN/docs/Web/Performance/Lazy_loading)。
## 懒加载库
使用该方式能确保在不同的浏览器下有一致的表现,并且能定制更多功能,如图片加载动画等。一个博客主题可能自带懒加载库,借助其附带的库,让 Artalk 也同时支持懒加载。
当图片懒加载设置为 `data-src` 时,Artalk 将为图片标签添加 `class="lazyload"` 和 `data-src` 属性。例如:
```html
<img data-src="1.png" class="lazyload" />
```
这时,你需要引入一个额外的图片懒加载库:[vanilla-lazyload](https://github.com/verlok/vanilla-lazyload);在页面的 `<head>` 中添加以下代码:
```html
<script src="https://unpkg.com/vanilla-lazyload/dist/lazyload.iife.min.js"></script>
```
编写代码,在 Artalk 初始化之前,添加事件监听:当评论列表发生更新后,调用图片懒加载库的 `update` 方法:
```js
// 初始化图片懒加载库
const lazyLoadInstance = new LazyLoad({
elements_selector: '.lazyload',
threshold: 0,
})
// 监听 Artalk 事件
Artalk.use((ctx) => {
ctx.on('list-loaded', () => lazyLoadInstance.update())
})
// 初始化 Artalk
const artalk = Artalk.init({ /* ... */ })
```
+3 -182
View File
@@ -1,186 +1,7 @@
# 置入博客
## 通用方法
本页面内容已移动至 <https://artalk.js.org/develop/import-blog.html>。
<<< @/code/quick-start/cdn.html
#### 什么时候执行 `Artalk.init({})`?
- 可以在任意位置引入 JS 和 CSS 资源,但需确保 JS 引入在执行 `Artalk.init({})` 前。
- 执行 `Artalk.init({ el: '#artalk' })` 前需要确保 `<div id="artalk"></div>` 在页面当中。
## Hugo
创建模板文件 `/主题目录/layouts/partials/comment/artalk.html`:
```html
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<script src="/lib/artalk/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments',
pageKey: '{{ .Permalink }}',
pageTitle: '{{ .Title }}',
server: '{{ $.Site.Params.artalk.server }}',
site: '{{ $.Site.Params.artalk.site }}',
// ...你的其他配置
})
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/develop/import-blog.html';
</script>
```
文章页模板 `/主题目录/layouts/_default/single.html` 合适的位置添加:
```html
<div class="article-comments">
{{- partial "comment/artalk" . -}}
</div>
```
修改 Hugo 配置文件:
::: code-group
```toml [config.toml]
[params.artalk]
server = 'https://artalk.example.org'
site = '你的站点名'
```
```yaml [config.yaml]
params:
artalk:
server: 'https://artalk.example.org'
site: '你的站点名'
```
:::
## Hexo
创建 `/主题目录/layout/comment/artalk.ejs`:
```html
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<script src="/lib/artalk/Artalk.js"></script>
<div id="Comments"></div>
<script>
var artalk = Artalk.init({
el: '#Comments',
pageKey: '<%= page.permalink %>',
pageTitle: '<%= page.title %>',
server: '<%= theme.comment.artalk.server %>'
site: '<%= theme.comment.artalk.site %>',
})
</script>
```
修改文章模板文件,例如 `/主题目录/layout/post.ejs`:
```html
<div class="article-comments">
<%- partial('comment/artalk') %>
</div>
```
编辑主题配置 `/主题目录/_config.example.yml`:
```yaml
comment:
artalk:
site: '你的站点名'
server: 'https://artalk.example.org'
```
::: tip
NexT 主题可以安装 [Hexo NexT 主题的 Artalk 插件](https://github.com/leirock/hexo-next-artalk)
:::
## VitePress
可参考:[@ArtalkJS/Artalk:/docs/.vitepress](https://github.com/ArtalkJS/Artalk/tree/master/docs/.vitepress)
- `config.ts` 修改配置引入 CSS 资源
- `theme/Artalk.vue` 创建组件
- `theme/index.ts` 注册组件
- `theme/Layout.vue` 使用组件
注:SSG 应用需通过 `import()` 函数异步引入 Artalk,否则会导致构建失败。
```ts
import('artalk').then(({ default: Artalk }) => {
artalk = Artalk.init({
//...
})
})
```
参考文件:[.vitepress/theme/Artalk.vue](https://github.com/ArtalkJS/Artalk/blob/master/docs/.vitepress/theme/Artalk.vue)
## VuePress
(待补充)
::: tip 提示
可参考:[置入框架](./import-framework.md)
:::
## Typecho
修改主题文章模板文件,例如 `post.php`:
```php
<!-- CSS -->
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<!-- JS -->
<script src="/lib/artalk/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments',
pageKey: '<?php $this->permalink() ?>',
pageTitle: '<?php $this->title() ?>',
server: '<后端地址>',
site: '<?php $this->options->title() ?>',
// ...你的其他配置
})
</script>
```
## WordPress
修改主题文章模板文件,例如 `single.php`:
```php
<!-- CSS -->
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<!-- JS -->
<script src="/lib/artalk/Artalk.js"></script>
<!-- Artalk -->
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments',
pageKey: '<?= addslashes(get_permalink()) ?>',
pageTitle: '<?= addslashes(get_the_title()) ?>',
server: '<后端地址>',
site: '<?= addslashes(get_bloginfo('name')) ?>',
// ...你的其他配置
})
</script>
```
+3 -142
View File
@@ -1,146 +1,7 @@
# 置入框架
## 安装 Artalk
本页面内容已移动至 <https://artalk.js.org/develop/import-framework.html>。
通过包管理工具引入 Artalk,推荐使用 [pnpm](https://pnpm.io/zh/)
```bash
pnpm add artalk
```
## Vue
Vue 3 + TypeScript 例:
```vue
<template>
<view ref="el"></view>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import 'artalk/dist/Artalk.css'
import Artalk from 'artalk'
const el = ref<HTMLElement>()
const route = useRoute()
let artalk: Artalk
onMounted(() => {
artalk = Artalk.init({
el: el.value,
pageKey: route.path,
pageTitle: `${document.title}`,
server: 'http://localhost:8080',
site: 'Artalk 的博客',
// ...
})
})
onUnmounted(() => {
artalk.destroy()
})
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/develop/import-framework.html';
</script>
```
## React
```tsx
import React, { useEffect, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import 'artalk/dist/Artalk.css';
import Artalk from 'artalk';
const ArtalkComment = () => {
const el = useRef(null);
const location = useLocation();
let artalk = null;
useEffect(() => {
artalk = new Artalk({
el: el.current,
pageKey: location.pathname,
pageTitle: document.title,
server: 'http://localhost:8080',
site: 'Artalk 的博客',
// ...
});
return () => {
if (artalk) {
artalk.destroy();
}
};
}, [location.pathname]);
return <div ref={el}></div>;
};
export default ArtalkComment;
```
```jsx
import React, { createRef } from 'react'
import 'artalk/dist/Artalk.css'
import Artalk from 'artalk'
export default class Artalk 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 的博客',
// ...
})
}
componentWillUnmount() {
this.artalk?.destroy()
}
render() {
return (
<div ref={this.el} />
)
}
}
```
## Svelte
```html
<script>
import { onMount, onDestroy } from 'svelte';
import 'artalk/dist/Artalk.css';
import Artalk from 'artalk';
let el;
let artalk;
onMount(() => {
artalk = Artalk.init({
el: el,
pageKey: location.pathname,
pageTitle: document.title,
server: 'http://localhost:8080',
site: 'Artalk 的博客',
// ...
});
onDestroy(() => {
if (artalk) {
artalk.destroy();
}
});
});
</script>
<div bind:this={el}></div>
```
-7
View File
@@ -1,7 +0,0 @@
# ArtalkJS
Artalk 拥有一个前端,[GitHub 代码仓库](https://github.com/ArtalkJS/Artalk)。
## 特性
可见:[README.md · 特性](https://github.com/ArtalkJS/Artalk#%E7%89%B9%E6%80%A7)
+5 -1
View File
@@ -1,3 +1,7 @@
# 前端部署
参考:[程序部署](../deploy.md)
本页面内容已移动至 <https://artalk.js.org/guide/deploy.html>。
<script setup lang="ts">
if (!import.meta.env.SSR) window.location = 'https://artalk.js.org/guide/deploy.html';
</script>
+14 -8
View File
@@ -8,7 +8,7 @@ Artalk 内置用户 IP 属地展示功能,并且你可以设置显示的精度
在开启 IP 属地展示功能之前,你需要下载一个数据库文件:
- [GitHub 下载](https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region.xdb) / [镜像站下载](https://gh-proxy.com/?q=https%3A%2F%2Fgithub.com%2Flionsoul2014%2Fip2region%2Fblob%2Fmaster%2Fdata%2Fip2region.xdb) (境内推荐)
- [GitHub 下载](https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region.xdb) / [镜像站下载](https://gh-proxy.com/?q=https%3A%2F%2Fgithub.com%2Flionsoul2014%2Fip2region%2Fblob%2Fmaster%2Fdata%2Fip2region.xdb) (境内推荐)
下载后请手动放置到 `./data/` 目录下,文件命名为:`ip2region.xdb`
@@ -16,11 +16,11 @@ Artalk 内置用户 IP 属地展示功能,并且你可以设置显示的精度
你可在设置中找到该配置项。
|显示精度|描述|示例|
|-|-|-|
|`province`|精确到省(默认)|`四川`|
|`city`|精确到城市|`浙江杭州`|
|`country`|精确到国家、地区|`美国`|
| 显示精度 | 描述 | 示例 |
| ---------- | ---------------- | ---------- |
| `province` | 精确到省(默认) | `四川` |
| `city` | 精确到城市 | `四川成都` |
| `country` | 精确到国家、地区 | `中国` |
配置文件:
@@ -30,11 +30,17 @@ ip_region:
# 启用 IP 属地展示
enabled: false
# 数据文件路径 (.xdb 格式)
db_path: "./data/ip2region.xdb"
db_path: ./data/ip2region.xdb
# 显示精度 ["province", "city", "country"]
precision: "province"
precision: province
```
## 获取准确的 IP 地址
如果你正在使用 CDN 或者 Nginx 等可信的反向代理服务器,那么你需要在「设置」-「服务器」选项 -「代理标头名 (`http.proxy_header`)」填写包含用户真实 IP 的请求头字段名,如:`X-Real-IP`(为了安全,该字段默认为空)。修改后,请手动重启 Artalk 服务以生效。
否则 Artalk 将无法获取到用户真实 IP 地址(如果使用了 Docker,可能获取到的 IP 始终是 172.17.0.X,这是 Docker 虚拟网卡的 IP)。
## 隐私权
Artalk 评论将记录用户的 `IP` 和 `User-Agent` 数据,此类数据有关用户隐私权,请在你的网站隐私政策中声明,并提示用户评论将会收集隐私数据。
+25 -11
View File
@@ -1,27 +1,41 @@
# Latex
# LaTeX
对于学术性站点,支持 Latex 是一个刚需,可以使用 [Katex](https://katex.org/) 这款被前端广泛使用的 Latex 语法解析器。Artalk 为保证简洁性,并未内置 Latex 语法解析功能,但你可以在页面中引入 Latex 和 Artalk Katex 插件,让评论系统获得 Latex 语法支持。
对于学术网站来说,支持 LaTeX 是一个刚需,可以使用 [Katex](https://katex.org/) 这款被前端广泛使用的 LaTeX 语法解析器来继承该功能。Artalk 为保持简洁,并未内置 LaTeX 语法解析功能,你可以手动在页面中引入 Katex 和 Artalk Katex 插件,让评论系统获得 LaTeX 语法支持。
```html
::: code-group
```html [浏览器引入]
<!-- 1. 引入 Katex -->
<link rel="stylesheet" href="https://unpkg.com/katex@0.15.3/dist/katex.min.css">
<script defer src="https://unpkg.com/katex@0.15.3/dist/katex.min.js"></script>
<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. 引入 Artalk -->
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<link href="/lib/artalk/Artalk.css" rel="stylesheet" />
<script src="/lib/artalk/Artalk.js"></script>
<!-- 3. 引入 Artalk Katex 插件 -->
<script src="https://unpkg.com/@artalk/plugin-katex/dist/artalk-plugin-katex.js"></script>
```
之后,你可以回复:
```ts [Node 引入]
// pnpm add katex @artalk/plugin-katex
import Artalk from 'artalk'
import { ArtalkKatexPlugin } from '@artalk/plugin-katex'
import 'katex/dist/katex.min.css'
```
$$ P(A) = \sum P(\{ (e_1,...,e_N) \}) = {{N}\choose{k}} \cdot p^kq^{N-k} $$
Artalk.use(ArtalkKatexPlugin)
```
查看效果:
:::
你可以发表评论:
```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)}
$$
```
检验效果:
![](/images/latex-support/1.png)
+100 -34
View File
@@ -1,55 +1,121 @@
# 图片灯箱
Artalk LightBox 插件能帮助你将网站**现有的图片灯箱**功能自动集成到 Artalk 中。
Artalk 图片灯箱插件帮助你将网站**现有的图片灯箱**功能自动集成到 Artalk 中。
## 浏览器环境
如果处于浏览器环境,博客主题通常自带图片灯箱,插件将自动检测 `window` 全局对象中的灯箱库,并集成到 Artalk 中,无需额外配置。
```html
<!-- 1. 引入图片灯箱依赖,例如 LightGallery (通常博客主题已提供,无需再引入) -->
<script src="lightgallery.js"></script>
<!-- 2. 引入 Artalk -->
<link href="/lib/artalk/Artalk.css" rel="stylesheet">
<link href="/lib/artalk/Artalk.css" rel="stylesheet" />
<script src="/lib/artalk/Artalk.js"></script>
<!-- 3. 引入 Artalk LightBox 插件 -->
<script src="https://unpkg.com/@artalk/plugin-lightbox/dist/artalk-plugin-lightbox.js"></script>
```
如上所示,额外引入一个 `artalk-plugin-lightbox.js` 文件即可。
目前自动集成支持:[LightGallery](https://github.com/sachinchoolur/lightGallery) [v2.5.0] / [FancyBox](https://github.com/fancyapps/fancybox) [v4.0.27] / [lightbox2](https://github.com/lokesh/lightbox2) [v2.11.3]
对于还未适配的图片灯箱,欢迎提交 PR -> [查看代码](https://github.com/ArtalkJS/Artalk/blob/master/ui/plugin-lightbox/main.ts)
::: details 附:图片灯箱依赖 CDN 资源
注:通常一个博客主题本来就是有图片灯箱插件的,所以无需重复引入。
#### LightGallery
```html
<link rel="stylesheet" href="https://unpkg.com/lightgallery@2.5.0/css/lightgallery.css">
<script src="https://unpkg.com/lightgallery@2.5.0/lightgallery.min.js"></script>
```
#### FancyBox
```html
<link rel="stylesheet" href="https://unpkg.com/@fancyapps/ui@4.0.27/dist/fancybox.css">
<script src="https://unpkg.com/@fancyapps/ui@4.0.27/dist/fancybox.umd.js"></script>
```
:::
### 配置灯箱
在引入 `artalk-plugin-lightbox.js` 之前对全局变量 `ATK_LIGHTBOX_CONF` 进行设置,如下:
如有需要,可以通过全局变量 `ATK_LIGHTBOX_CONF` 对灯箱库进行额外的配置:
```html
<script>
// Config for LightGallery
window.ATK_LIGHTBOX_CONF = {
groupAll: true,
// ...其他配置
plugins: [lgZoom, lgThumbnail],
speed: 500,
licenseKey: 'your_license_key'
}
</script>
<script src="artalk-plugin-lightbox.js"></script>
```
## Node 环境
安装图片灯箱插件:
```bash
pnpm add @artalk/plugin-lightbox
```
配置插件,通过 `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'),
},
})
```
:::
在 Node 环境中,如有需要对灯箱库进行额外的配置,可以通过 `config` 选项配置:
```ts
Artalk.use(ArtalkLightboxPlugin, {
// ...
// Config for LightGallery
config: {
speed: 500,
},
})
```
---
目前自动集成支持:[LightGallery](https://github.com/sachinchoolur/lightGallery) • [FancyBox](https://github.com/fancyapps/fancybox) • [lightbox2](https://github.com/lokesh/lightbox2) • [PhotoSwipe](https://photoswipe.com/)
一些灯箱库暂未适配,期待你的 PR 😉:[@artalk/plugin-lightbox](https://github.com/ArtalkJS/Artalk/blob/master/ui/plugin-lightbox/src/main.ts)。
+59 -27
View File
@@ -1,49 +1,81 @@
# 浏览量统计
Artalk 内置页面浏览量统计功能,你可以在你的页面任意位置,放置 HTML 标签:
Artalk 内置页面浏览量统计和评论数统计功能,你可以在页面中显示页面的浏览量和评论数。
```html
<span id="ArtalkPV"></span>
浏览量:<span class="artalk-pv-count"></span>
评论数:<span class="artalk-comment-count"></span>
```
当 Artalk 评论列表加载完毕时,该标签内容将修改为页面的浏览量计数。
## 加载占位符
Artalk 加载需要时间,所以你可以给它一个占位字符:
Artalk 加载需要时间,你可以在展示统计数的元素中加入占位符:
```html
<span id="ArtalkPV">加载中...</span>
<span class="artalk-pv-count">加载中...</span>
```
配置项 `pvEl` 的默认值是 `"#ArtalkPV"`,可修改将评论量加载到指定元素,例如:
## 同时加载多个页面的统计数
```js
Artalk.init({
pvEl: '.your_element',
})
```
例如在文章列表页,你可以显示每篇文章的浏览量和评论数。
### 加载多个页面的浏览量
你能在除评论页面之外的任何页面,例如「文章列表」页,显示页面浏览量或评论数。
在非评论页,无需调用 `Artalk.init` 加载评论框 (会使页面浏览量 PV 数增加),仅调用 `loadCountWidget` 静态方法即可:
当处于文章列表页时,仅需调用 `Artalk.loadCountWidget` 函数,而无需 `Artalk.init` (加载评论列表会使页面浏览量 PV 数 +1)。
<!-- prettier-ignore-start -->
```js
Artalk.loadCountWidget({
server: '服务器地址',
site: '站点名',
pvEl: '#ArtalkPV',
countEl: '#ArtalkCount',
});
server: '服务器地址',
site: '站点名',
pvEl: '.artalk-pv-count',
countEl: '.artalk-comment-count',
statPageKeyAttr: 'data-page-key',
})
```
然后你可以放置多个 `#ArtalkPV` 元素,通过属性 `data-page-key` 来指定需要查询的页面:
<!-- prettier-ignore-end -->
然后放置多个 class 为 `artalk-pv-count` 的元素,通过属性 `data-page-key` 来指定需要查询的页面:
```html
<span id="ArtalkPV" data-page-key="/test/1.html"></span>
<span id="ArtalkPV" data-page-key="/test/2.html"></span>
<span id="ArtalkPV" data-page-key="/test/3.html"></span>
<span id="ArtalkCount" data-page-key="/test/1.html"></span>
<!-- ... -->
<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>
```
评论数查询同理:
```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>
```
## 自定义元素选择器
可通过配置项 `pvEl` 和 `countEl` 来指定元素选择器,以展示页面浏览量和评论数:
```js
Artalk.init({
pvEl: '.your_pv_count_element', // 页面浏览量元素选择器
countEl: '.your_comment_count_element', // 评论数元素选择器
})
```
## 自定义 `data-page-key` 属性名
配置项 `statPageKeyAttr` 的默认值为 `data-page-key`,Artalk 会通过该属性名来查询指定页面。为了方便博客主题的适配,可通过它自定义属性名,例如将其替换为 `data-path`:
```js
Artalk.loadCountWidget({
statPageKeyAttr: 'data-path',
})
```
此时,对应的 HTML 代码应如下所示:
```html
<span class="artalk-pv-count" data-path="/test/1.html"></span>
```
这样,`data-path` 属性值将被用于查询指定的页面。
+14 -12
View File
@@ -1,36 +1,36 @@
# 侧边栏
侧边栏同时充当 **通知中心** + **控制中心** 的功能,当用户**填写评论框的“昵称”和“邮箱”后**,侧边栏入口按钮能在**评论框右下角**找到。
侧边栏同时充当 **通知中心** + **控制中心** 的功能,当用户填写评论框的“**昵称**”和“**邮箱**”后,侧边栏入口按钮能在评论框右下角找到。
<img src="/images/sidebar/1.png" width="650">
## 通知中心
普通用户打开侧边栏能查看与自己相关的评论,评论被分类为:提及、全部、我的、待审。
Artalk 拥有站内消息功能,在接收邮件通知的同时,也能在侧边栏查看消息。
你能快速地找到评论,跳转到评论对应的页面。
在侧边栏可以查看与自己相关的评论,分类包括:提及、全部、我的、待审。
你能快速找到评论,并跳转到对应页面。
<img src="/images/sidebar/2.png" width="430">
当用户收到消息时,会显示红点标记,站内消息功能属于是。
即便是不打开邮件通知,也能收到来自对方的回复。
当用户收到消息时,会显示红点标记。
<img src="/images/sidebar/3.png" width="350">
同时,你能在侧边栏快速回复对方的消息,无需前往评论页面。
另外,你能在侧边栏快速回复对方的消息,无需切换到评论页面。
<img src="/images/sidebar/4.png" width="400">
## 控制中心
管理员账户侧边栏将从「通知中心」切换为「控制中心」。
管理员账户侧边栏将自动从“通知中心”升级为“控制中心”。
当输入管理员“昵称”和“邮件”后,会自动弹出密码验证提示框:
管理员输入“昵称”和“邮箱”后,将弹出密码验证提示框:
<img src="/images/sidebar/5.png" width="500">
<img src="/images/sidebar/5.png" width="600">
进入侧边栏,你可以对「评论、页面、站点」等进行管理。
进入侧边栏,你可以对评论、页面、站点等内容进行管理操作。
<img src="/images/sidebar/6.png" width="800">
@@ -40,4 +40,6 @@
## 设置
登录管理员账户可进入到 “控制中心” 的图形设置界面,轻松地对 [配置文件](/guide/backend/config.md) 以及 [前端的配置](/guide/frontend/config.md) 进行修改,而无需手动编辑复杂的配置文件。
登录管理员账户进入“控制中心”的设置界面,可修改 [配置](/guide/backend/config.md) 和 [界面](/guide/frontend/config.md),无需编辑复杂的配置文件。
<img src="/images/sidebar/settings.png" width="700">
+54 -32
View File
@@ -1,42 +1,64 @@
# <span class="wave">👋</span> Hello Friend
**Artalk** 是一款简洁的**自托管**评论系统,你可以在服务器上**轻松部署**并置入前端页面中。
来到你的博客,或是任意位置,放置 Artalk 评论框,让页面具备丰富的**社会化**功能。
Artalk 是一款简单易用但功能丰富的评论系统,你可以开箱即用地部署并置入任何博客、网站、Web 应用。
![](https://user-images.githubusercontent.com/22412567/141147152-df30a0ff-bf41-42ee-9958-4722206a7a90.png)
## 功能亮点
- **轻量设计**
**轻量设计**
前端采用 TypeScript (Vanilla JS),轻量级,无冗余依赖,仅 ~30KB (gzipped)。
前端采用 TypeScript (Vanilla JS),轻量级,无冗余依赖,仅 ~40KB (gzipped)。
后端采用 Golang 重制 (Artalk v2),跨平台,体积小巧,五脏俱全,快速部署。
后端采用 Golang 重制 (Artalk v2),跨平台,体积小巧,五脏俱全,快速部署。
- **“麻雀虽小,五脏俱全”**
- Markdown 语法 + 代码高亮
- [通知中心](./frontend/sidebar.md) - 站内:侧边栏 + 红点标记
- [多形式推送](./backend/admin_notify.md) - 站外:邮件、TG、钉钉、飞书 + 异步执行
- [评论审核](./backend/moderator.md):折叠 / 反垃圾 / 频率限制 / 滑动验证
- [多站点](./backend/multi-site.md):共用同一个后端程序,多站点集中化管理
- [表情包](./frontend/emoticons.md):支持 OwO 格式 + 动态加载
- [Artrans](./transfer.md):评论数据快速迁移 (导入 / 导出) 工具
- 评论投票 / 身份徽章 / 密码验证 / 说说模式
- 评论盖楼 / 评论分页 / 滚动加载 / 实时预览
- 评论排序 / 评论置顶 / 评论防丢 / 自动填充
- 图片上传 / 页面管理 / 站点隔离 / 夜间模式
**“麻雀虽小,五脏俱全”**
穷举不是我们的特长,更多有趣的功能期待你来探索!
Artalk 的功能包括但不限于:
- **“Unlimited Blade Works”**
<!-- features -->
* [侧边栏](https://artalk.js.org/guide/frontend/sidebar.html): 快速管理、直观浏览
* [社交登录](https://artalk.js.org/guide/frontend/auth.html): 通过社交账号快速登录
* [邮件通知](https://artalk.js.org/guide/backend/email.html): 多种发送方式、邮件模板
* [多元推送](https://artalk.js.org/guide/backend/admin_notify.html): 多种推送方式、通知模版
* [站内通知](https://artalk.js.org/guide/frontend/sidebar.html): 红点标记、提及列表
* [验证码](https://artalk.js.org/guide/backend/captcha.html): 多种验证类型、频率限制
* [评论审核](https://artalk.js.org/guide/backend/moderator.html): 内容检测、垃圾拦截
* [图片上传](https://artalk.js.org/guide/backend/img-upload.html): 自定义上传、支持图床
* [Markdown](https://artalk.js.org/guide/intro.html): 支持 Markdown 语法
* [表情包](https://artalk.js.org/guide/frontend/emoticons.html): 兼容 OwO,快速集成
* [多站点](https://artalk.js.org/guide/backend/multi-site.html): 站点隔离、集中管理
* [管理员](https://artalk.js.org/guide/backend/multi-site.html): 密码验证、徽章标识
* [页面管理](https://artalk.js.org/guide/frontend/sidebar.html): 快速查看、标题一键跳转
* [浏览量统计](https://artalk.js.org/guide/frontend/pv.html): 轻松统计网页浏览量
* [层级结构](https://artalk.js.org/guide/frontend/config.html#nestmax): 嵌套分页列表、滚动加载
* [评论投票](https://artalk.js.org/guide/frontend/config.html#vote): 赞同或反对评论
* [评论排序](https://artalk.js.org/guide/frontend/config.html#listsort): 多种排序方式,自由选择
* [评论搜索](https://artalk.js.org/guide/frontend/sidebar.html): 快速搜索评论内容
* [评论置顶](https://artalk.js.org/guide/frontend/sidebar.html): 重要消息置顶显示
* [仅看作者](https://artalk.js.org/guide/frontend/config.html): 仅显示作者的评论
* [评论跳转](https://artalk.js.org/guide/intro.html): 快速跳转到引用的评论
* [自动保存](https://artalk.js.org/guide/frontend/config.html): 输入内容防丢功能
* [IP 属地](https://artalk.js.org/guide/frontend/ip-region.html): 用户 IP 属地展示
* [数据迁移](https://artalk.js.org/guide/transfer.html): 自由迁移、快速备份
* [图片灯箱](https://artalk.js.org/guide/frontend/lightbox.html): 图片灯箱快速集成
* [图片懒加载](https://artalk.js.org/guide/frontend/img-lazy-load.html): 延迟加载图片,优化体验
* [Latex](https://artalk.js.org/guide/frontend/latex.html): Latex 公式解析集成
* [夜间模式](https://artalk.js.org/guide/frontend/config.html#darkmode): 夜间模式切换
* [扩展插件](https://artalk.js.org/develop/): 创造更多可能性
* [多语言](https://artalk.js.org/guide/frontend/i18n.html): 多国语言切换
* [命令行](https://artalk.js.org/guide/backend/config.html): 命令行操作管理能力
* [API 文档](https://artalk.js.org/develop/): 提供 OpenAPI 格式文档
* [程序升级](https://artalk.js.org/guide/backend/update.html): 版本检测,一键升级
<!-- /features -->
Artalk 正在持续成长,创意由你发挥,价值由你赋予!
穷举不是我们的特长,更多有趣的功能期待你来探索!
不论是 Vue、React、Svelte 的前端项目,还是 WordPress、Typecho、Hexo 等博客系统,都可以快速引入 Artalk,结合诸位的聪明才智,我们相信 Artalk 能够自如应对各种业务场景。
**“Unlimited Blade Works”**
> 更多支持 / 计划的功能,详见:[README.md](https://github.com/ArtalkJS/Artalk#todos)。
Artalk 正在持续成长,创意由你发挥,价值由你赋予!
不论是 Vue、React、Svelte 的前端项目,还是 WordPress、Typecho、Hexo 等博客系统,都可以快速引入 Artalk,结合诸位的聪明才智,我们相信 Artalk 能够自如应对各种业务场景。
## 用户体验
@@ -67,14 +89,14 @@ Artalk 社区是包容开放的社区,我们欢迎不同水平的人员帮助
我们作为开源精神的推崇者以及实践者,希望我们所创造的自由软件,都应该被自由的使用,自由的研究,自由的更改和自由的分享。本项目主程序使用 [MIT](https://github.com/ArtalkJS/Artalk/blob/master/LICENSE) 协议开源,文档使用 [CC](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh) 许可协议。
::: tip 立即为社区贡献力量?
- 浏览开发者资料([开发文档](../develop/index.md) / [CONTRIBUTING.md](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md))
- 维护 Artalk 后端(代码仓库 [@ArtalkJS/Artalk:/](https://github.com/ArtalkJS/Artalk))
- 维护 Artalk 前端(代码仓库 [@ArtalkJS/Artalk:/ui](https://github.com/ArtalkJS/Artalk/tree/master/ui))
- 完善 Artalk 文档(代码仓库 [@ArtalkJS/Artalk:/docs](https://github.com/ArtalkJS/Artalk/tree/master/docs))
- 翻译 多语言 i18n(前往查看 [多语言说明](./frontend/i18n.html))
- 改进数据迁移工具(代码仓库 [@ArtalkJS/Artransfer](https://github.com/ArtalkJS/Artransfer))
- 分享你的想法创意(下方留言 / [Discussions](https://github.com/ArtalkJS/Artalk/discussions))
- 编写相关社区项目(扩展插件 / 部署教程等)
- 浏览开发者资料([开发文档](../develop/index.md) / [CONTRIBUTING.md](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md))
- 维护 Artalk 后端(代码仓库 [@ArtalkJS/Artalk:/](https://github.com/ArtalkJS/Artalk))
- 维护 Artalk 前端(代码仓库 [@ArtalkJS/Artalk:/ui](https://github.com/ArtalkJS/Artalk/tree/master/ui))
- 完善 Artalk 文档(代码仓库 [@ArtalkJS/Artalk:/docs](https://github.com/ArtalkJS/Artalk/tree/master/docs))
- 翻译 多语言 i18n(前往查看 [多语言说明](./frontend/i18n.html))
- 改进数据迁移工具(代码仓库 [@ArtalkJS/Artransfer](https://github.com/ArtalkJS/Artransfer))
- 分享你的想法创意(下方留言 / [Discussions](https://github.com/ArtalkJS/Artalk/discussions))
- 编写相关社区项目(扩展插件 / 部署教程等)
:::
+39 -37
View File
@@ -10,28 +10,28 @@
```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 +0800",
"updated_at": "2021-10-28 20:50:15 +0800 +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": "管理员",
"badge_color": "#FF716D",
"page_key": "https://artalk.js.org/guide/transfer.html",
"page_title": "数据迁移",
"page_admin_only": "false",
"site_name": "Artalk",
"site_urls": "http://localhost:3000/demo/,https://artalk.js.org"
"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 +0800",
"updated_at": "2021-10-28 20:50:15 +0800 +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": "管理员",
"badge_color": "#FF716D",
"page_key": "https://artalk.js.org/guide/transfer.html",
"page_title": "数据迁移",
"page_admin_only": "false",
"site_name": "Artalk",
"site_urls": "http://localhost:3000/demo/,https://artalk.js.org"
}
```
@@ -58,7 +58,7 @@
转换为 `.artrans` 格式的数据文件可以导入 Artalk:
- **控制中心导入**:你可在「[控制中心](./frontend/sidebar.md#控制中心)」找到「迁移」选项卡,并根据提示导入 Artrans。
- **命令行导入**:执行 `artalk import -h` 查阅帮助文档。
- **命令行导入**:参考 [命令行导入](#命令行导入)。
## 获取源数据
@@ -159,35 +159,37 @@ typecho-20220424-202246.artrans
执行 `artalk import -h` 查看帮助文档。
```bash
./artalk import 数据类型 [参数...]
./artalk import [参数...] [文件名]
```
参数格式遵循 `<key>:<value>`,例如:
通过命令行的 `-p` Flag 设定导入参数:
```bash
./artalk import 类型 target_site_name:"Site" target_site_url:"https://xx.com" json_file:"文件路径"
./artalk import -p '{ "target_site_name": "Site", "target_site_url": "https://xx.com", "json_file": "", "url_resolver": true }' ./artrans.json
```
前端的导入同样可以手动输入启动参数,例如:
如果在网页后台导入可将 JSON 填入文本框:
```json
{
"target_site_name": "Site",
"target_site_url": "https://xx.com",
"json_file": "服务器上的文件路径"
"json_file": "服务器上的文件路径",
"url_resolver": true
}
```
Artalk 导入功能的通用启动参数:
Artalk 导入参数:
| 参数 | 类型 | 说明 |
| :------: | ------ | ------------ |
| `target_site_name` | String | 导入站点名称 |
| `target_site_url` | String | 导入站点 URL |
| `url_resolver` | Boolean | 默认关闭,URL 解析器。将 `page_key` 基于 `target_site_url` 参数重新生成为完整 URL 作为评论的新 `page_key` |
| `json_file` | String | JSON 数据文件路径 |
| `json_data` | String | JSON 数据字符串内容 |
| `assumeyes` | Boolean | 不提确认 `y/n`,直接执行 |
| 参数 | 类型 | 说明 |
| :----------------: | ------- | --------------------------------------------------------------------------------------------------------- |
| `target_site_name` | String | 导入站点名称 |
| `target_site_url` | String | 导入站点 URL |
| `url_resolver` | Boolean | 默认关闭,URL 解析器。将 `page_key` 基于 `target_site_url` 参数重新生成为完整 URL 作为评论的新 `page_key` |
| `url_keep_domain`| Boolean | 默认关闭,是否保留原有 URL 的域名部分。当关闭时将去除 `pageKey` 中的域名。当 `url_resolver` 开启时,`url_keep_domain` 将被同时启用 |
| `json_file` | String | JSON 数据文件路径 |
| `json_data` | String | JSON 数据字符串内容 |
| `assumeyes` | Boolean | 不提确认 `y/n`,直接执行 |
## 数据备份
Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Loaded 100 of 635 files, more files were not shown because too many files have changed in this diff. Show more