Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a89426c93 | ||
|
|
7a026ef0e2 | ||
|
|
855f6c261f | ||
|
|
7099598a92 | ||
|
|
ad8851ea94 | ||
|
|
def9dc2707 | ||
|
|
91228a9446 | ||
|
|
7a0a9dbd92 | ||
|
|
441c4fa6a9 | ||
|
|
a16169f69d | ||
|
|
da42676656 | ||
|
|
f3a42e892f | ||
|
|
6a53597485 | ||
|
|
60336e567d | ||
|
|
8918c62ffd | ||
|
|
362fc19cd8 | ||
|
|
1b938752ff | ||
|
|
835a886dc8 | ||
|
|
f390b57fe7 | ||
|
|
6d21a0f204 | ||
|
|
a1d0c37828 | ||
|
|
763fbc417e | ||
|
|
776d5e66fe | ||
|
|
10c0975ce0 | ||
|
|
7286642fc9 | ||
|
|
8db4fb3524 | ||
|
|
08be04979d | ||
|
|
d7ea9ba43f | ||
|
|
bad248534c | ||
|
|
f56ac4eabc | ||
|
|
bbe2e8416c | ||
|
|
d44e79b1f4 | ||
|
|
e816dd686c | ||
|
|
c9ea8f6162 | ||
|
|
87102cd3b0 | ||
|
|
8b6bab828d | ||
|
|
9fb658599a | ||
|
|
f8c33003a8 | ||
|
|
b97136b83f | ||
|
|
df3e983e7f | ||
|
|
1b878fb3cc | ||
|
|
aa87ab94f5 | ||
|
|
4e9afd9761 | ||
|
|
2b7d0ecb72 | ||
|
|
603c7d9439 | ||
|
|
fb93231b35 | ||
|
|
fed83263e2 | ||
|
|
9dc2d83486 | ||
|
|
d918caaf81 | ||
|
|
d44212bd90 | ||
|
|
37d4ca76fa | ||
|
|
8cc39f322c | ||
|
|
2b4e80651a | ||
|
|
415fa0f2e3 | ||
|
|
91809002d7 | ||
|
|
dcaad1b2d5 | ||
|
|
5e635bba68 | ||
|
|
d136d086eb | ||
|
|
9fe765f874 | ||
|
|
72317ead34 | ||
|
|
75c7914fb1 | ||
|
|
863b4deec0 | ||
|
|
6e6fd8d587 | ||
|
|
1608911328 | ||
|
|
87a62961b6 | ||
|
|
e6a9748e70 | ||
|
|
0f35532f0b | ||
|
|
d21e47f881 | ||
|
|
8d11a239fa | ||
|
|
8867eb296c | ||
|
|
a53ddc9f76 | ||
|
|
5ee9e76dcf | ||
|
|
3d5f77ab35 | ||
|
|
25a4f48e5e | ||
|
|
2dc3bc8934 | ||
|
|
7b1bb25d6a | ||
|
|
9bed5be236 | ||
|
|
ec0ef12b0e | ||
|
|
5d2950f842 | ||
|
|
25c2f30165 | ||
|
|
d8b49773b3 | ||
|
|
2c8107a4b7 | ||
|
|
9f8aba068e | ||
|
|
e40235b1c7 | ||
|
|
e050544d21 | ||
|
|
da692649bc | ||
|
|
a0892fc4c0 | ||
|
|
c1e365fdfd | ||
|
|
e6e6d2aa54 | ||
|
|
ac70cd4c9d | ||
|
|
600030b528 | ||
|
|
4e1537b4f0 | ||
|
|
8a8aac945d | ||
|
|
89be748dee | ||
|
|
6c35fe9ded | ||
|
|
9ea6e8d981 | ||
|
|
2c89c2d633 | ||
|
|
5eddd9ff05 | ||
|
|
9fdfb2a043 | ||
|
|
2bdb806aaf | ||
|
|
a1b3f1a1f7 | ||
|
|
dc333e5a9a | ||
|
|
f0ecff9199 | ||
|
|
e3ccc655c5 | ||
|
|
04a96d4ab8 | ||
|
|
71e0fcec75 | ||
|
|
963d3cf3d9 | ||
|
|
2669b0efe8 | ||
|
|
a8b4eb6047 | ||
|
|
cc7b2f574c | ||
|
|
150de6d7c0 | ||
|
|
1da3f6420e | ||
|
|
919dfa43d0 | ||
|
|
b6805ce948 | ||
|
|
137610aa82 | ||
|
|
0cbb5b2dd1 | ||
|
|
9e59fefc8a | ||
|
|
6ead92db54 | ||
|
|
388b5b8b24 | ||
|
|
e15e22ecda | ||
|
|
8336bb0345 | ||
|
|
fc6c6286db | ||
|
|
3af4482db6 | ||
|
|
c9f8e9b824 | ||
|
|
d9c2813e50 | ||
|
|
84d6f9728e | ||
|
|
d1b730113b | ||
|
|
731be57e74 | ||
|
|
9f7fb9dad2 | ||
|
|
9f81879713 | ||
|
|
ff8527f007 | ||
|
|
2e07d2a2ca | ||
|
|
8f5a84969b | ||
|
|
1e76a4d99f | ||
|
|
840621a6b1 | ||
|
|
24485f9615 | ||
|
|
d4f0ae8ad7 | ||
|
|
a06928378a | ||
|
|
bf93ca78c8 | ||
|
|
75180877b1 | ||
|
|
fb4aaf7ecb | ||
|
|
d58355209a | ||
|
|
8488b7e18b | ||
|
|
e7aced94dd | ||
|
|
3dd93c33b3 | ||
|
|
bd613a3304 | ||
|
|
7028dcd905 | ||
|
|
9ef063cf98 | ||
|
|
bf13e1cdba | ||
|
|
79f5f53886 | ||
|
|
4c951d7e44 | ||
|
|
b034e514a7 | ||
|
|
b88a26dcae | ||
|
|
ee30ba4fc8 | ||
|
|
a02b89ba3e | ||
|
|
2ca3ab8274 | ||
|
|
cbf0210131 | ||
|
|
d8d9420616 | ||
|
|
891f792fe4 | ||
|
|
d538e47917 | ||
|
|
6c7ce98522 | ||
|
|
1e839548a4 | ||
|
|
4ea45ae375 | ||
|
|
91f89c6b7d | ||
|
|
0ac70a5a43 | ||
|
|
9ac354cb23 | ||
|
|
40e6fcd966 | ||
|
|
7e476ded1c | ||
|
|
a885c0a179 | ||
|
|
08c0b297e5 | ||
|
|
01ed04c791 | ||
|
|
0135a83b49 | ||
|
|
b9c177bb54 | ||
|
|
00ce23bc99 | ||
|
|
4853b6cc5d | ||
|
|
79dea425ea | ||
|
|
c20faed4e3 | ||
|
|
e9acd28126 | ||
|
|
b71b22f5a7 | ||
|
|
bc7d0e09b8 | ||
|
|
f682ade2c9 | ||
|
|
2b990ff433 | ||
|
|
6d21c2b074 | ||
|
|
3840720620 | ||
|
|
7dd8668b6e | ||
|
|
ac4b8b0b80 | ||
|
|
febe890ecb | ||
|
|
1be2ad4d6e | ||
|
|
848969edbc | ||
|
|
f0d93ad736 | ||
|
|
9fb17d0483 | ||
|
|
63a637a50e | ||
|
|
54487d999c | ||
|
|
6916c5a4d5 | ||
|
|
00d765b563 | ||
|
|
cb4985dc0b | ||
|
|
2b7d69e364 | ||
|
|
5075698f4a | ||
|
|
4c6fbeffb7 | ||
|
|
262dd4123d | ||
|
|
3ccc25e08b | ||
|
|
65ab1bab79 | ||
|
|
4f5f3b9f7c | ||
|
|
fe4dfb2a1c | ||
|
|
b71fe13787 | ||
|
|
340ab407da |
No files matched your search
@@ -2,6 +2,7 @@ version: 2.1
|
||||
|
||||
orbs:
|
||||
node: circleci/node@5.0.3
|
||||
codecov: codecov/codecov@3.3.0
|
||||
|
||||
executors:
|
||||
base:
|
||||
@@ -9,18 +10,15 @@ executors:
|
||||
- image: cimg/base:stable
|
||||
node:
|
||||
docker:
|
||||
- image: 'cimg/node:16.15.1'
|
||||
- image: 'cimg/node:18.19.0'
|
||||
go:
|
||||
docker:
|
||||
- image: cimg/go:1.20
|
||||
- image: cimg/go:1.21.3
|
||||
|
||||
parameters:
|
||||
trigger-app:
|
||||
type: boolean
|
||||
default: false
|
||||
trigger-ui:
|
||||
type: boolean
|
||||
default: false
|
||||
run-them-all:
|
||||
type: boolean
|
||||
default: false
|
||||
@@ -40,40 +38,24 @@ jobs:
|
||||
go version
|
||||
- restore_cache:
|
||||
keys:
|
||||
- go-mod-1.20-{{ checksum "go.sum" }}
|
||||
- go-mod-1.21.3-{{ checksum "go.sum" }}
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: go mod download
|
||||
- save_cache:
|
||||
key: go-mod-1.20-{{ checksum "go.sum" }}
|
||||
key: go-mod-1.21.3-{{ 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
|
||||
gotestsum --junitfile /tmp/test-reports/unit-tests.xml -- -coverprofile=/tmp/test-reports/coverage.out ./...
|
||||
- store_test_results:
|
||||
path: /tmp/test-reports
|
||||
|
||||
## Frontend
|
||||
test_ui:
|
||||
executor: node
|
||||
steps:
|
||||
- node/install
|
||||
- checkout
|
||||
- run:
|
||||
name: Print the node version
|
||||
command: node -v
|
||||
- run:
|
||||
name: Install pnpm
|
||||
command: npm i -g pnpm@7.25.0
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: pnpm --dir ./ui install --frozen-lockfile
|
||||
- run:
|
||||
name: Build Artalk
|
||||
command: pnpm --dir ./ui build:all
|
||||
- codecov/upload:
|
||||
flags: go
|
||||
file: /tmp/test-reports/coverage.out
|
||||
|
||||
all_projects:
|
||||
executor: base
|
||||
@@ -91,14 +73,6 @@ workflows:
|
||||
jobs:
|
||||
- test_app
|
||||
|
||||
build-ui:
|
||||
when:
|
||||
or:
|
||||
- << pipeline.parameters.trigger-ui >>
|
||||
- << pipeline.parameters.run-them-all >>
|
||||
jobs:
|
||||
- test_ui
|
||||
|
||||
build-shared-other:
|
||||
when: << pipeline.parameters.run-them-all >>
|
||||
jobs:
|
||||
|
||||
@@ -8,7 +8,7 @@ setup: true
|
||||
# the path-filtering orb is required to continue a pipeline based on
|
||||
# https://circleci.com/developer/orbs/orb/circleci/path-filtering
|
||||
orbs:
|
||||
path-filtering: circleci/path-filtering@0.0.1
|
||||
path-filtering: circleci/path-filtering@1.0.0
|
||||
|
||||
workflows:
|
||||
setup:
|
||||
@@ -17,7 +17,6 @@ workflows:
|
||||
mapping: |
|
||||
(cmd|internal|server|pkg|test|conf)/.* trigger-app true
|
||||
main.go|go.mod|go.sum trigger-app true
|
||||
(ui)/.* trigger-ui true
|
||||
base-revision: master # git branch name
|
||||
config-path: .circleci/conditional_config.yml
|
||||
filters:
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
{{ end }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
@@ -15,6 +15,13 @@ options:
|
||||
- refactor
|
||||
- docs
|
||||
commit_groups:
|
||||
sort_by: Custom
|
||||
title_order:
|
||||
- feat
|
||||
- fix
|
||||
- perf
|
||||
- refactor
|
||||
- docs
|
||||
title_maps:
|
||||
feat: Features
|
||||
fix: Bug Fixes
|
||||
@@ -22,7 +29,7 @@ options:
|
||||
refactor: Code Refactoring
|
||||
docs: Documentation
|
||||
header:
|
||||
pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$"
|
||||
pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s\\/]*)\\))?\\:\\s(.*)$"
|
||||
pattern_maps:
|
||||
- Type
|
||||
- Scope
|
||||
@@ -0,0 +1,67 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gomod
|
||||
directory: /
|
||||
schedule:
|
||||
interval: monthly
|
||||
commit-message:
|
||||
prefix: "chore(deps/go): "
|
||||
groups:
|
||||
deps:
|
||||
patterns:
|
||||
- '*'
|
||||
open-pull-requests-limit: 15
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: /ui
|
||||
schedule:
|
||||
interval: monthly
|
||||
commit-message:
|
||||
prefix: "chore(deps/ui): "
|
||||
groups:
|
||||
prod-deps:
|
||||
dependency-type: production
|
||||
dev-deps:
|
||||
dependency-type: development
|
||||
open-pull-requests-limit: 15
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: /docs
|
||||
schedule:
|
||||
interval: monthly
|
||||
commit-message:
|
||||
prefix: "chore(deps/docs): "
|
||||
groups:
|
||||
deps:
|
||||
patterns:
|
||||
- '*'
|
||||
open-pull-requests-limit: 15
|
||||
|
||||
- package-ecosystem: docker
|
||||
directory: /
|
||||
schedule:
|
||||
interval: monthly
|
||||
commit-message:
|
||||
prefix: "chore(deps/docker): "
|
||||
groups:
|
||||
deps:
|
||||
patterns:
|
||||
- '*'
|
||||
open-pull-requests-limit: 15
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: /.github/workflows
|
||||
schedule:
|
||||
interval: monthly
|
||||
commit-message:
|
||||
prefix: "chore(deps/ci): "
|
||||
groups:
|
||||
deps:
|
||||
patterns:
|
||||
- '*'
|
||||
open-pull-requests-limit: 15
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"extends": ["config:base", "schedule:weekly"],
|
||||
"automerge": false,
|
||||
"major": {
|
||||
"automerge": false
|
||||
},
|
||||
"branchPrefix": "chore/",
|
||||
"labels": ["dependencies"],
|
||||
"gomodTidy": true,
|
||||
"rangeStrategy": "bump",
|
||||
"reviewers": []
|
||||
}
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
types: [artalk-release]
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.20.1'
|
||||
GO_VERSION: '1.21.3'
|
||||
PKG_NAME: 'github.com/ArtalkJS/Artalk'
|
||||
DOCKER_IMG: ghcr.io/goreleaser/goreleaser-cross
|
||||
CACHE_DIR: /tmp/cache/docker-image
|
||||
@@ -18,27 +18,37 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: master
|
||||
|
||||
- name: Docker Image Cache
|
||||
id: docker-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.CACHE_DIR }}
|
||||
key: docker-image-go-cross-${{ env.GO_VERSION }}
|
||||
- name: Checkout latest tag
|
||||
run: |
|
||||
# fetch tags
|
||||
git fetch --prune --unshallow --tags -f
|
||||
|
||||
# checkout latest version
|
||||
VERSION=$(git describe --tags --abbrev=0)
|
||||
git checkout ${VERSION}
|
||||
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_ENV
|
||||
|
||||
# disable cache because the err `no space left on device`
|
||||
# - name: Docker Image Cache
|
||||
# id: docker-cache
|
||||
# uses: actions/cache@v3
|
||||
# with:
|
||||
# path: ${{ env.CACHE_DIR }}
|
||||
# key: docker-image-go-cross-${{ env.GO_VERSION }}
|
||||
|
||||
- name: Pull Docker Image
|
||||
if: steps.docker-cache.outputs.cache-hit != 'true'
|
||||
# if: steps.docker-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
docker pull "${DOCKER_IMG}:v${GO_VERSION}"
|
||||
mkdir -p "${CACHE_DIR}"
|
||||
docker save -o "${CACHE_DIR}/go-cross.tar" "${DOCKER_IMG}:v${GO_VERSION}"
|
||||
|
||||
- name: Restore Docker Image from Cache
|
||||
if: steps.docker-cache.outputs.cache-hit == 'true'
|
||||
run: docker load -i ${CACHE_DIR}/go-cross.tar
|
||||
# mkdir -p "${CACHE_DIR}"
|
||||
# docker save -o "${CACHE_DIR}/go-cross.tar" "${DOCKER_IMG}:v${GO_VERSION}"
|
||||
|
||||
# - name: Restore Docker Image from Cache
|
||||
# if: steps.docker-cache.outputs.cache-hit == 'true'
|
||||
# run: docker load -i ${CACHE_DIR}/go-cross.tar
|
||||
|
||||
- name: Setup git-chglog
|
||||
run: |
|
||||
@@ -48,20 +58,17 @@ jobs:
|
||||
|
||||
- name: Pre Build
|
||||
run: |-
|
||||
# get latest version by tag
|
||||
VERSION=$(git describe --tags --abbrev=0)
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_ENV
|
||||
|
||||
# changelog
|
||||
mkdir -p local
|
||||
git-chglog ${VERSION} > local/release-notes.md
|
||||
|
||||
# copy config file
|
||||
cp conf/artalk.example.yml artalk.yml
|
||||
|
||||
# github token
|
||||
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" > local/.release-env
|
||||
|
||||
# changelog
|
||||
git-chglog --config .github/chglog/config.yml ${VERSION} > local/release-notes.md
|
||||
|
||||
# copy config file
|
||||
cp conf/artalk.example.yml artalk.yml
|
||||
|
||||
- name: Build and Release
|
||||
run: |
|
||||
docker run \
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Checkout latest release tag
|
||||
- name: Checkout latest tag
|
||||
run: |
|
||||
# fetch tags
|
||||
git fetch --prune --unshallow --tags -f
|
||||
@@ -62,17 +62,12 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
# TODO: https://github.com/docker/metadata-action/pull/248
|
||||
- name: Get Docker Tags and Labels
|
||||
run: |
|
||||
TAGS="${DOCKER_IMG}:latest,${DOCKER_IMG}:${VERSION#v},${DOCKER_IMG}:${VERSION_SHORT},${DOCKER_IMG}:sha-${COMMIT_HASH}"
|
||||
echo "DOCKER_TAGS=${TAGS}" >> $GITHUB_ENV
|
||||
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Gen docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
context: git
|
||||
images: |
|
||||
${{ env.DOCKER_IMG }}
|
||||
tags: |
|
||||
@@ -85,15 +80,14 @@ jobs:
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and Push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: ./
|
||||
file: ./Dockerfile
|
||||
platforms: 'linux/amd64,linux/arm64'
|
||||
push: true
|
||||
# tags: ${{ steps.meta.outputs.tags }}
|
||||
tags: ${{ env.DOCKER_TAGS }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
|
||||
@@ -11,22 +11,26 @@ jobs:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# set for building frontend
|
||||
working-directory: ./ui
|
||||
working-directory: ./ui # set for building frontend
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Checkout latest tag
|
||||
run: |
|
||||
git fetch --prune --unshallow --tags -f
|
||||
git checkout $(git describe --tags --abbrev=0)
|
||||
|
||||
- name: Use pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
version: 8
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 18.x
|
||||
registry-url: https://registry.npmjs.org/
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: './ui/pnpm-lock.yaml'
|
||||
|
||||
@@ -13,50 +13,32 @@ jobs:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# set for building docs
|
||||
working-directory: ./docs
|
||||
|
||||
steps:
|
||||
# - name: Wait for other docs build to succeed
|
||||
# uses: lewagon/wait-on-check-action@v1.2.0
|
||||
# with:
|
||||
# running-workflow-name: 'Docs CN Mirror Deploy'
|
||||
# check-name: 'Build Docs'
|
||||
# ref: ${{ github.ref }}
|
||||
# repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# allowed-conclusions: success,skipped,cancelled
|
||||
# wait-interval: 10
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Use pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
|
||||
- name: Use pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
registry-url: https://registry.npmjs.org/
|
||||
cache: 'pnpm'
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- name: Build Docs
|
||||
run: pnpm docs:build
|
||||
|
||||
- name: Build Docs
|
||||
run: pnpm docs:build
|
||||
|
||||
- name: Deploy
|
||||
uses: TencentCloud/cos-action@v1
|
||||
with:
|
||||
secret_id: ${{ secrets.TENCENT_CLOUD_SECRET_ID }}
|
||||
secret_key: ${{ secrets.TENCENT_CLOUD_SECRET_KEY }}
|
||||
cos_bucket: ${{ secrets.DOCS_CN_COS_BUCKET }}
|
||||
cos_region: ${{ secrets.DOCS_CN_COS_REGION }}
|
||||
local_path: .vitepress/dist/
|
||||
remote_path: /
|
||||
clean: true
|
||||
- name: Deploy
|
||||
uses: TencentCloud/cos-action@v1
|
||||
with:
|
||||
secret_id: ${{ secrets.TENCENT_CLOUD_SECRET_ID }}
|
||||
secret_key: ${{ secrets.TENCENT_CLOUD_SECRET_KEY }}
|
||||
cos_bucket: ${{ secrets.DOCS_CN_COS_BUCKET }}
|
||||
cos_region: ${{ secrets.DOCS_CN_COS_REGION }}
|
||||
local_path: .vitepress/dist/
|
||||
remote_path: /
|
||||
clean: true
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 18.x
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- name: Handle Version Number
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
run: |
|
||||
if [ ! $(git tag -l "${VERSION}") ]; then
|
||||
# prepend changelog
|
||||
changelog=$(git-chglog --next-tag "${VERSION}" "${VERSION}")
|
||||
changelog=$(git-chglog --config .github/chglog/config.yml --next-tag "${VERSION}" "${VERSION}")
|
||||
echo -e "${changelog}\n" | cat - CHANGELOG.md > temp && mv temp CHANGELOG.md
|
||||
|
||||
# modify the version of `package.json`
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
# git commit and push
|
||||
git config user.name github-actions[bot]
|
||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
||||
git add CHANGELOG.md "${UI_NPM_PKG_FILE}"
|
||||
git add .
|
||||
git commit -m "chore: release ${VERSION}"
|
||||
git tag "${VERSION}"
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Test Docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/**"
|
||||
push:
|
||||
paths:
|
||||
- "docs/**"
|
||||
|
||||
jobs:
|
||||
test_docs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build Docs
|
||||
run: pnpm docs:build
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Test Frontend
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'ui/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'ui/**'
|
||||
|
||||
jobs:
|
||||
test_ui:
|
||||
strategy:
|
||||
matrix:
|
||||
node: [18, 20]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./ui
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Use Node.js ${{ matrix.node }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: pnpm
|
||||
cache-dependency-path: './ui/pnpm-lock.yaml'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm --dir ./ui install --frozen-lockfile
|
||||
|
||||
- name: Package Build Test
|
||||
run: pnpm build:all
|
||||
|
||||
# TODO: Add unit test
|
||||
# - name: Unit test
|
||||
# run: pnpm test
|
||||
@@ -48,6 +48,7 @@ npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
__debug*
|
||||
|
||||
# frontend
|
||||
node_modules
|
||||
@@ -64,3 +65,6 @@ node_modules
|
||||
# always compile latest version
|
||||
/public/sidebar
|
||||
/public/dist
|
||||
|
||||
playwright-report
|
||||
test-results
|
||||
Vendored
+2
-2
@@ -8,7 +8,7 @@
|
||||
"mode": "exec",
|
||||
"program": "${workspaceFolder}/bin/artalk",
|
||||
"preLaunchTask": "Build for debugging",
|
||||
"args": ["server", "-c", "${workspaceFolder}/local/local.yml"]
|
||||
"args": ["server", "-c", "${workspaceFolder}/data/artalk.yml"]
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
Vendored
+2
-1
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"eslint.workingDirectories": ["./ui"],
|
||||
"cSpell.words": [
|
||||
"akismet",
|
||||
"artalk",
|
||||
@@ -16,4 +17,4 @@
|
||||
"sqlite",
|
||||
"pkged"
|
||||
]
|
||||
}
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
<p align="center">
|
||||
<img src="./docs/artalk.png" alt="Artalk" width="100%">
|
||||
</p>
|
||||
|
||||
# Artalk
|
||||
|
||||
[](https://circleci.com/gh/ArtalkJS/Artalk/tree/master)
|
||||
[](https://github.com/ArtalkJS/Artalk/actions/workflows/dockerhub.yml) [](https://app.fossa.com/projects/git%2Bgithub.com%2FArtalkJS%2FArtalk?ref=badge_shield)
|
||||
[](https://hub.docker.com/r/artalk/artalk-go)
|
||||
|
||||
> Artalk: Golang backend of Artalk.
|
||||
|
||||
前往:[“**官方文档 · 后端部分**”](https://artalk.js.org/guide/backend/config.html)
|
||||
|
||||
---
|
||||
|
||||
- 高效快速
|
||||
- 异步执行
|
||||
- 跨平台兼容
|
||||
- 轻量级部署
|
||||
|
||||
## Supports
|
||||
|
||||
- 运行环境:支持 Linux, Windows, Darwin (x64 + ARM)
|
||||
- 数据存储:支持 SQLite, MySQL, PostgreSQL, SQL Server
|
||||
- 邮件发送:支持 SMTP, 阿里云邮件, 调用 sendmail 发送邮件
|
||||
- 高效缓存:支持 Redis, Memcache, In-Memory (BigCache)
|
||||
|
||||
## Build
|
||||
|
||||
> 部署可以使用官方提供的 Docker 镜像,见:[后端部署文档](https://artalk.js.org/guide/backend/install.html)
|
||||
|
||||
### 编译二进制文件
|
||||
|
||||
```sh
|
||||
$ make all
|
||||
```
|
||||
|
||||
编译后二进制文件将输出到 `bin/` 目录下
|
||||
|
||||
### Docker Compose 编译运行
|
||||
|
||||
```sh
|
||||
# 克隆项目
|
||||
$ git clone https://github.com/ArtalkJS/Artalk
|
||||
$ cd Artalk
|
||||
|
||||
# 构建镜像
|
||||
$ docker compose build
|
||||
|
||||
# 运行
|
||||
$ docker compose up -d
|
||||
```
|
||||
|
||||
### Docker 镜像构建
|
||||
|
||||
```sh
|
||||
# 克隆项目
|
||||
$ git clone https://github.com/ArtalkJS/Artalk
|
||||
$ cd Artalk
|
||||
|
||||
# 构建镜像
|
||||
$ make docker-build
|
||||
|
||||
# 发布镜像
|
||||
$ make docker-push
|
||||
```
|
||||
|
||||
## TODOs
|
||||
|
||||
Reference to https://github.com/ArtalkJS/Artalk#todos
|
||||
|
||||
## License
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FArtalkJS%2FArtalk?ref=badge_large)
|
||||
+367
-240
@@ -1,256 +1,383 @@
|
||||
|
||||
## [v2.5.0](https://github.com/ArtalkJS/Artalk/compare/v2.4.4...v2.5.0) (2023-03-10)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* admin_page_get default Sort by create_at DESC.
|
||||
* Fix wrong SQL syntax to support mysql database.
|
||||
* add `X-Forwarded-For` proxy header read
|
||||
* `timeAgo` appears negative number minutes ago
|
||||
* `timeAgo` function does not display the now
|
||||
* github actions image cache
|
||||
* Typecho Importer some bugs.
|
||||
* Prevent unsafe svg image uploads
|
||||
* naming conflict of node circleci
|
||||
* crash when frontend config is not set
|
||||
* Truncate Chinese character issue.
|
||||
* Wrong logic of captcha 'always' config.
|
||||
* sidebar navigation sorting ([#361](https://github.com/ArtalkJS/Artalk/issues/361))
|
||||
* docker image build script
|
||||
* add `.npmignore` to fix NPM publish inclusion issue
|
||||
* missing trusted_domains field
|
||||
* config alias and Dockerfile
|
||||
* frontend repository directory issue
|
||||
* Add lock in ChildCommentCacheSave
|
||||
* destroy method remove root element
|
||||
* Add lock prevent query db repeatedly while cache miss.
|
||||
* Dockerfile install bash
|
||||
* Cache add mutex lock
|
||||
* replace gravatar default mirror
|
||||
* PageEdit not work when Page is not created.
|
||||
* add whitelist for origin checker
|
||||
* Geetest js resource url
|
||||
* Rename field total_parents to total_roots.
|
||||
* admin_site_edit URL Validator bug.
|
||||
* Reduce the use of native raw SQL to process boolean judgments and transfer them to ORM for processing.
|
||||
* **UA:** Cooperate with client-side to correct Win11 UA.
|
||||
* **admin_edit:** Remove cache before admin_edit.
|
||||
* **admin_site_edit:** Split urls and TrimSpace to allow Space around sep char.
|
||||
* **api:** Modify to only api subpath enable SiteOrigin checker
|
||||
* **api_main_get:** Msg center disable comment-pin.
|
||||
* **api_version:** Trim version prefix v char
|
||||
* **artrans:** Frontend import Payload modify to JSON object.
|
||||
* **artrans:** Modify Typecho boot param keys.
|
||||
* **artransfer:** trim json string before checking array type.
|
||||
* **artransfer:** typecho date recovery.
|
||||
* **artransfer:** incorrect IsPinned reference to IsPending ([#49](https://github.com/ArtalkJS/Artalk/issues/49))
|
||||
* **artransfer:** improve logger & twikoo importer bug.
|
||||
* **artransfer:** CreatedAt field recovery & json unmarshal number to float64 issue.
|
||||
* **cache:** ChildCommentCacheSave repeatedly cache while exist
|
||||
* **cache:** Use SingleFlight to avoid Cache breakdown.
|
||||
* **cache:** Type conversion issue in Captcha part when using redis.
|
||||
* **cache:** Duplicate display reply comments when pid cache is deleted
|
||||
* **captcha:** Always-mode fail on the first req & modify font size
|
||||
* **captcha:** Fix lots of bugs.
|
||||
* **comment_add:** ip region search in comment add api
|
||||
* **comment_add:** PendingDefault ignore Admin user
|
||||
* **comment_edit:** Resend email when comment is_pending status is modified
|
||||
* **conf_admins:** Preserve admin user which not in config file.
|
||||
* **config:** replace viper with koanf to make map case sensitivity ([#47](https://github.com/ArtalkJS/Artalk/issues/47))
|
||||
* **cors:** Import cors domains from db site urls.
|
||||
* **db:** Time type field use pointer to solve 0000-00-00 issue.
|
||||
* **db:** Fix query syntax error & importer vote recover.
|
||||
* **db:** Support postgres database.
|
||||
* **docker:** Docker-compose file add build option
|
||||
* **docker:** Entrypoint script gen command
|
||||
* **docker:** Run artalk-go anywhere with a right config
|
||||
* **dockerfile:** Expose host for external device
|
||||
* **email:** email queue initialization issue ([#374](https://github.com/ArtalkJS/Artalk/issues/374))
|
||||
* **email:** duplicate sending with multiple admins using same email addrs ([#375](https://github.com/ArtalkJS/Artalk/issues/375))
|
||||
* **email:** failback to `email.mail_tpl` if `admin_notify.email.mail_tpl` is empty
|
||||
* **frontend-conf:** Use pointer with omitempty to ignore frontend config output
|
||||
* **geetest:** Static page prevent cache
|
||||
* **img-upload:** Set img_upload.path defualt value
|
||||
* **importer:** UrlResolver disabled by default
|
||||
* **importer:** UrlResolver avoid end of slash being removed
|
||||
* **importer:** Fix too many sql variables Err while too much items.
|
||||
* **importer:** json decode by universal type.
|
||||
* **importer:** UrlResolver disabled by default when a TargetSiteUrl is given
|
||||
* **limit-middleware:** Precise match & fix disable captcha config.
|
||||
* **lint:** add tsc check before vite compile ([#440](https://github.com/ArtalkJS/Artalk/issues/440))
|
||||
* **notify:** Remove atk-emoticon img tags
|
||||
* **sidebar:** array type config option cannot be shown
|
||||
* **site_origin:** issue of same-origin request under the proxy ([#454](https://github.com/ArtalkJS/Artalk/issues/454))
|
||||
* **time:** Embed IANA timezone database in Windows build
|
||||
* **transfer:** Importer boot param parse.
|
||||
* **trusted_domains:** Extract from full URL with slash suffix & improve referer interceptor
|
||||
* **trusted_domains:** Disable CORS restrictions
|
||||
* **typo:** CaptchaCheck typo
|
||||
* **ui:** hash goto function check condition issue
|
||||
* **upgrade:** Upgrade cmd load config
|
||||
* **utils:** func SplitAndTrimSpace remove blank items by default
|
||||
* **validator:** ValidateURL modify to IsRequestURL
|
||||
* **vote:** Vote up and down at the same time.
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* renamed from artalk-go to artalk
|
||||
* http origin checker
|
||||
* Improve GetLinkToReply logic
|
||||
* Bind API actions under a struct.
|
||||
* abstract email service
|
||||
* project package structure
|
||||
* remove version two-way check ([#452](https://github.com/ArtalkJS/Artalk/issues/452))
|
||||
* batch removing artalk `-go` postfix
|
||||
* Replace global variable lib.DB with injected db.
|
||||
* build scripts and CI tests
|
||||
* move from tmp dir to root
|
||||
* merge ci workflows
|
||||
* merge backend to monorepo branch
|
||||
* migrate from echo to go-fiber
|
||||
* replace pkger with go:embed
|
||||
* **CI:** improve build and release workflows ([#358](https://github.com/ArtalkJS/Artalk/issues/358))
|
||||
* **api:** Modify admin_comment_edit user merge logic
|
||||
* **api:** Remove unnecessary parameter of ParamsDecode method
|
||||
* **api_get:** Comments get api.
|
||||
* **captcha:** abstract captcha service ([#455](https://github.com/ArtalkJS/Artalk/issues/455))
|
||||
* **comment:** seperate comment ui renders from single file ([#427](https://github.com/ArtalkJS/Artalk/issues/427))
|
||||
* **conf:** Rename notify to admin_notify & admin_notify.email option
|
||||
* **docker:** Use a folder to place config instead of mounting a single file
|
||||
* **notify_launcher:** notify_launcher refactor and fix some bugs.
|
||||
* **scripts:** double quote to prevent globbing and word splitting
|
||||
* **style:** convert to use Sass as a style interpreter ([#439](https://github.com/ArtalkJS/Artalk/issues/439))
|
||||
* **ui:** automatic dependency injection ([#429](https://github.com/ArtalkJS/Artalk/issues/429))
|
||||
|
||||
### Documentation
|
||||
|
||||
* add `CODE_OF_CONDUCT.md`
|
||||
* Update README.md
|
||||
* add simplified README for artalk npm package
|
||||
* add translation section to `CONTRIBUTING.md`
|
||||
* Update README.md
|
||||
* fix content and update index
|
||||
* fix wrong config value ([#371](https://github.com/ArtalkJS/Artalk/issues/371))
|
||||
* fix broken links ([#364](https://github.com/ArtalkJS/Artalk/issues/364))
|
||||
* add open api ([#360](https://github.com/ArtalkJS/Artalk/issues/360))
|
||||
* add `Project Structure` section to `CONTRIBUTING.md`
|
||||
* Update README.md
|
||||
* refine and add frontend api docs
|
||||
* example in zh-CN
|
||||
* update setup-example-site.sh script usage
|
||||
* init artalk with new frontend api
|
||||
* migrate ArtalkJS/Docs to monorepo docs
|
||||
* Update README.md
|
||||
* Update README.md
|
||||
* Update README.md
|
||||
* Update README.md
|
||||
* Update README.md
|
||||
* update CONTRIBUTING.md `make debug-build`
|
||||
* **deploy:** add `restart=always` for docker to auto restart ([#425](https://github.com/ArtalkJS/Artalk/issues/425))
|
||||
* **extras:** add deploy guide for vuepress ([#436](https://github.com/ArtalkJS/Artalk/issues/436))
|
||||
## [v2.7.2](https://github.com/ArtalkJS/Artalk/compare/v2.7.1...v2.7.2) (2023-12-20)
|
||||
|
||||
### Features
|
||||
|
||||
* Typecho Impoter PageKey builder.
|
||||
* add graceful shutdown
|
||||
* password support to be encrypted by md5.
|
||||
* Global site & origin checker & support cookie
|
||||
* Update config example file.
|
||||
* display IP region of comment ([#418](https://github.com/ArtalkJS/Artalk/issues/418)) ([#447](https://github.com/ArtalkJS/Artalk/issues/447))
|
||||
* patch `locale` config from `zh-cn` to `zh-CN` ([#678](https://github.com/ArtalkJS/Artalk/issues/678))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sidebar:** sidebar language switch and config save issue ([#708](https://github.com/ArtalkJS/Artalk/issues/708))
|
||||
* **ui:** add `referrerpolicy` attribute for iframe ([#687](https://github.com/ArtalkJS/Artalk/issues/687)) ([#707](https://github.com/ArtalkJS/Artalk/issues/707))
|
||||
* **ui/dark-mode:** potential memory leak issue in auto mode ([#688](https://github.com/ArtalkJS/Artalk/issues/688))
|
||||
* **ui/pagination:** auto switch page by url hashtag issue ([#693](https://github.com/ArtalkJS/Artalk/issues/693))
|
||||
* **ui/sidebar:** refactor settings and fix save issue ([#677](https://github.com/ArtalkJS/Artalk/issues/677)) ([#706](https://github.com/ArtalkJS/Artalk/issues/706))
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **ui:** move window references into function scope ([#675](https://github.com/ArtalkJS/Artalk/issues/675))
|
||||
* **ui/api:** losing coupling between `Api` and `User`
|
||||
* **ui/user:** user class no longer globally singleton
|
||||
|
||||
### Documentation
|
||||
|
||||
* **i18n:** add translation for `open` button
|
||||
* **refactor:** organize the pkgs and fix some issues ([#702](https://github.com/ArtalkJS/Artalk/issues/702))
|
||||
|
||||
|
||||
## [v2.7.1](https://github.com/ArtalkJS/Artalk/compare/v2.7.0...v2.7.1) (2023-12-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **build:** generate source maps to ease debugging
|
||||
* **cout-widget:** `loadCountWidget` issue
|
||||
* **ui:** static method export issue in JS module ([#669](https://github.com/ArtalkJS/Artalk/issues/669))
|
||||
|
||||
### Documentation
|
||||
|
||||
* **i18n:** add translation of update notice
|
||||
|
||||
|
||||
## [v2.7.0](https://github.com/ArtalkJS/Artalk/compare/v2.6.4...v2.7.0) (2023-12-17)
|
||||
|
||||
### Features
|
||||
|
||||
* **ui:** support `scrollRelativeTo` config option
|
||||
* **ui/test:** add end-to-end (e2e) testing using Playwright
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **api/img-upload:** `public_path` config enables the use of full url ([#659](https://github.com/ArtalkJS/Artalk/issues/659)) ([#664](https://github.com/ArtalkJS/Artalk/issues/664))
|
||||
* **lifecycle:** create multi-instances at the same time ([#660](https://github.com/ArtalkJS/Artalk/issues/660)) ([#663](https://github.com/ArtalkJS/Artalk/issues/663))
|
||||
* **notify_pusher:** panic when admin ids array is empty ([#634](https://github.com/ArtalkJS/Artalk/issues/634))
|
||||
* **style/list:** replace `float` to `text-align` in footer part ([#619](https://github.com/ArtalkJS/Artalk/issues/619))
|
||||
* **ui:** scroll to the center of the viewport issue
|
||||
* **ui/conf:** sanitize `noComment` conf option for security ([#624](https://github.com/ArtalkJS/Artalk/issues/624))
|
||||
* **ui/dark-mode:** `setDarkMode` cannot save to instance config ([#661](https://github.com/ArtalkJS/Artalk/issues/661))
|
||||
* **ui/editor:** fix position of the comment box when replying ([#643](https://github.com/ArtalkJS/Artalk/issues/643)) ([#648](https://github.com/ArtalkJS/Artalk/issues/648))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **cache:** implement GC feature for simple_cache pkg ([#656](https://github.com/ArtalkJS/Artalk/issues/656))
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **editor:** refactor editor plugin manager ([#609](https://github.com/ArtalkJS/Artalk/issues/609))
|
||||
* **editor:** refactor plug kit and events ([#613](https://github.com/ArtalkJS/Artalk/issues/613))
|
||||
* **ui:** reduce coupling with `ContextApi`
|
||||
* **ui:** separate standalone admin-only-elem checker
|
||||
* **ui/api:** loose coupling between `Api` and `Context`
|
||||
* **ui/conf:** loose coupling between config and list fetch
|
||||
* **ui/event:** refactor core event manager ([#611](https://github.com/ArtalkJS/Artalk/issues/611))
|
||||
* **ui/layer:** better layer implements and independence ([#662](https://github.com/ArtalkJS/Artalk/issues/662))
|
||||
* **ui/list:** separate list into standalone components ([#618](https://github.com/ArtalkJS/Artalk/issues/618))
|
||||
* **ui/marked:** separate markdown related codes
|
||||
* **ui/marked:** loose coupling with `marked` func
|
||||
* **ui/plugin:** further divide functionality into plugins ([#615](https://github.com/ArtalkJS/Artalk/issues/615))
|
||||
* **ui/stat:** losing coupling of `CountWidget`
|
||||
* **ui/types:** better `ArtalkType` import and export ([#620](https://github.com/ArtalkJS/Artalk/issues/620))
|
||||
|
||||
### Documentation
|
||||
|
||||
* revise and add more examples
|
||||
* provide clearer and more detailed instructions in CONTRIBUTING.md
|
||||
* **conf:** disable `frontend.uaBadge` config option by default
|
||||
* **deploy:** add deployment guide for render.com ([#649](https://github.com/ArtalkJS/Artalk/issues/649))
|
||||
* **import:** update the examples in import-framework.md ([#665](https://github.com/ArtalkJS/Artalk/issues/665))
|
||||
|
||||
### BREAKING CHANGE
|
||||
|
||||
|
||||
The following top-level functions exported by the 'artalk' npm package have been deprecated: `Artalk.update`, `Artalk.reload`, and `Artalk.destroy`. These methods now require invocation on an instance created by either `Artalk.init` or `new Artalk`. Please utilize instance-level methods instead, such as `artalkInstance.update`. For more information, refer to [the documentation](https://artalk.js.org/guide/frontend/import-framework.html). The update was implemented to enable the concurrent creation of multiple instances, adapting to situations where Vue components are simultaneously referenced across various pages. Initially, only a singular instance was permitted to mitigate memory leak concerns. However, this proved limiting for scenarios involving the caching of multiple component instances through 'keep-alive.' To better suit intricate SPA application needs, the choice was made to permit the creation of multiple independent instances. It's crucial to remember to manually invoke the `artalk.destroy` method when releasing components to avoid memory leaks (Issue [#660](https://github.com/ArtalkJS/Artalk/issues/660)).
|
||||
|
||||
|
||||
## [v2.6.4](https://github.com/ArtalkJS/Artalk/compare/v2.6.3...v2.6.4) (2023-10-12)
|
||||
|
||||
### Features
|
||||
|
||||
* **go:** upgrade golang to v1.21.3 and some deps
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** fix duplicate event binding when update conf ([#605](https://github.com/ArtalkJS/Artalk/issues/605))
|
||||
* **email:** sender not initialized correctly
|
||||
* **style:** fix copyright text overlay on send button ([#607](https://github.com/ArtalkJS/Artalk/issues/607))
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **anti_spam:** refactor anti_spam pkg and add unit test ([#589](https://github.com/ArtalkJS/Artalk/issues/589))
|
||||
|
||||
|
||||
## [v2.6.3](https://github.com/ArtalkJS/Artalk/compare/v2.6.2...v2.6.3) (2023-09-20)
|
||||
|
||||
### Features
|
||||
|
||||
* **config:** add `db.ssl` to enable db ssl mode ([#587](https://github.com/ArtalkJS/Artalk/issues/587))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **notify_tpl:** fix template render result in notify case
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **config:** add error message for timezone setting ([#586](https://github.com/ArtalkJS/Artalk/issues/586))
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **renderer:** abstract func of template renderer for multi-cases ([#585](https://github.com/ArtalkJS/Artalk/issues/585))
|
||||
|
||||
### Documentation
|
||||
|
||||
* new landing page
|
||||
|
||||
|
||||
## [v2.6.2](https://github.com/ArtalkJS/Artalk/compare/v2.6.1...v2.6.2) (2023-09-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cmd:** remove app instance creation when mini boot ([#577](https://github.com/ArtalkJS/Artalk/issues/577))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **style:** modify `z-index` less than 5 ([#578](https://github.com/ArtalkJS/Artalk/issues/578))
|
||||
|
||||
|
||||
## [v2.6.1](https://github.com/ArtalkJS/Artalk/compare/v2.6.0...v2.6.1) (2023-09-11)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **captcha:** image captcha base64 response issue ([#575](https://github.com/ArtalkJS/Artalk/issues/575))
|
||||
|
||||
### Documentation
|
||||
|
||||
* **config:** add info about env variables ([#566](https://github.com/ArtalkJS/Artalk/issues/566))
|
||||
* **extras:** add deploy guide for railway.app ([#567](https://github.com/ArtalkJS/Artalk/issues/567))
|
||||
|
||||
|
||||
## [v2.6.0](https://github.com/ArtalkJS/Artalk/compare/v2.5.5...v2.6.0) (2023-09-01)
|
||||
|
||||
### Features
|
||||
|
||||
* **config:** support load env variables as config ([#564](https://github.com/ArtalkJS/Artalk/issues/564))
|
||||
* **go:** upgrade golang to v1.21.0 and some deps ([#543](https://github.com/ArtalkJS/Artalk/issues/543))
|
||||
* **hook:** add hook pkg
|
||||
* **simple_cache:** a simple thread-safe cache with sync.Map
|
||||
* **utils:** add common random utils
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cache:** child comment ids store after comment updated
|
||||
* **cmd:** fix parse root cmd global flags
|
||||
* **config:** fix ip region patch
|
||||
* **db:** fix dsn strings for mysql connections ([#541](https://github.com/ArtalkJS/Artalk/issues/541))
|
||||
* **limiter:** limiter log ignore options method req
|
||||
* **limiter:** fix limiter always mode
|
||||
* **log:** add missing log for web server listen func ([#556](https://github.com/ArtalkJS/Artalk/issues/556))
|
||||
* **ui:** fix plug cannot disable issue ([#563](https://github.com/ArtalkJS/Artalk/issues/563))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **cmd:** support command mini boot mode
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **CI:** replace using `docker/metadata-action` for the docker push ([#545](https://github.com/ArtalkJS/Artalk/issues/545))
|
||||
* **CI:** replace renovate with github dependabot ([#546](https://github.com/ArtalkJS/Artalk/issues/546))
|
||||
* **anti_spam:** refactor anti_spam pkg
|
||||
* **artransfer:** refactor artransfer pkg
|
||||
* **cache:** remove cached fields in struct to save memory ([#555](https://github.com/ArtalkJS/Artalk/issues/555))
|
||||
* **cache:** cache code tidy-up
|
||||
* **cache:** refactor cache pkg
|
||||
* **cache:** refactor cache pkg
|
||||
* **cache:** refactor cache pkg
|
||||
* **captcha:** refactor captcha pkg
|
||||
* **cloud:** refactor cloud pkg
|
||||
* **cmd:** refactor cmd pkg
|
||||
* **conf:** better config.NewFromFile with error handle
|
||||
* **config:** refactor config pkg
|
||||
* **core:** refactor core pkg
|
||||
* **core:** better AppService func with error handle
|
||||
* **cors:** refactor cors middleware
|
||||
* **dao:** refactor dao pkg
|
||||
* **dao_cache:** add dao_cache pkg
|
||||
* **db:** refactor db pkg
|
||||
* **email:** refactor email pkg
|
||||
* **i18n:** refactor i18n pkg
|
||||
* **ip_region:** refactor ip_region pkg
|
||||
* **limiter:** add limiter pkg
|
||||
* **log:** create common log pkg
|
||||
* **main:** refactor main.go
|
||||
* **notify:** add notify_pusher pkg
|
||||
* **server/common:** refactor server/common pkg
|
||||
* **server/handler:** refactor server/handler pkg
|
||||
* **server/middleware:** refactor server/middleware pkg
|
||||
* **test:** create common test pkg
|
||||
|
||||
### Documentation
|
||||
|
||||
* **extras:** add deploy guide for fly.io ([#520](https://github.com/ArtalkJS/Artalk/issues/520))
|
||||
|
||||
|
||||
## [v2.5.5](https://github.com/ArtalkJS/Artalk/compare/v2.5.4...v2.5.5) (2023-05-10)
|
||||
|
||||
### Features
|
||||
|
||||
* **build:** add embedded fe lite and i18n scripts ([#493](https://github.com/ArtalkJS/Artalk/issues/493)) ([#505](https://github.com/ArtalkJS/Artalk/issues/505))
|
||||
* **go:** upgrade golang to v1.20.4 and some deps ([#506](https://github.com/ArtalkJS/Artalk/issues/506))
|
||||
* **gravatar:** add `gravatar.params` config option ([#508](https://github.com/ArtalkJS/Artalk/issues/508))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **api:** comment IP data loss after editing ([#504](https://github.com/ArtalkJS/Artalk/issues/504))
|
||||
* **editor:** prevent editor reset on comment failure ([#507](https://github.com/ArtalkJS/Artalk/issues/507))
|
||||
|
||||
### BREAKING CHANGE
|
||||
|
||||
|
||||
The `gravatar.default` config option has been removed. Please use `gravatar.params` instead. The default value for `gravatar.params` is now `"d=mp&s=240"`.
|
||||
|
||||
|
||||
## [v2.5.4](https://github.com/ArtalkJS/Artalk/compare/v2.5.3...v2.5.4) (2023-04-09)
|
||||
|
||||
### Features
|
||||
|
||||
* **go:** upgrade golang to v1.20.3 and some deps ([#485](https://github.com/ArtalkJS/Artalk/issues/485))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **CI:** upgrade and pin node.js and pnpm version ([#484](https://github.com/ArtalkJS/Artalk/issues/484))
|
||||
|
||||
### Documentation
|
||||
|
||||
* update swagger docs and some deps
|
||||
|
||||
|
||||
## [v2.5.3](https://github.com/ArtalkJS/Artalk/compare/v2.5.2...v2.5.3) (2023-04-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **api/comment_add:** SIGSEGV crash in comment_add ([#478](https://github.com/ArtalkJS/Artalk/issues/478)) ([#481](https://github.com/ArtalkJS/Artalk/issues/481))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **ip_region:** add db file existence check and error message ([#482](https://github.com/ArtalkJS/Artalk/issues/482))
|
||||
|
||||
|
||||
## [v2.5.2](https://github.com/ArtalkJS/Artalk/compare/v2.5.1...v2.5.2) (2023-03-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ui:** destroy instance when calling init func twice
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **notify:** shorten the length of notify key ([#466](https://github.com/ArtalkJS/Artalk/issues/466))
|
||||
* **style:** add `!important` for white-space css in code block ([#467](https://github.com/ArtalkJS/Artalk/issues/467))
|
||||
|
||||
|
||||
## [v2.5.1](https://github.com/ArtalkJS/Artalk/compare/v2.5.0...v2.5.1) (2023-03-16)
|
||||
|
||||
### Features
|
||||
|
||||
* **go:** upgrade golang to v1.20.2
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ui/count-widget:** context api undefined issue ([#464](https://github.com/ArtalkJS/Artalk/issues/464))
|
||||
* **ui/i18n:** duplicate packaging built-in language in the external script
|
||||
* **ui/paginator:** showErr func call issue
|
||||
* **ui/sort-dropdown:** dropdown menu disappears after call reload func ([#461](https://github.com/ArtalkJS/Artalk/issues/461))
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **anti_spam/aliyun:** accessing aliyun green text api without sdk ([#459](https://github.com/ArtalkJS/Artalk/issues/459))
|
||||
* **ui/user:** modify user to standalone module ([#463](https://github.com/ArtalkJS/Artalk/issues/463))
|
||||
|
||||
|
||||
## [v2.5.0](https://github.com/ArtalkJS/Artalk/compare/v2.4.4...v2.5.0) (2023-03-10)
|
||||
|
||||
### Features
|
||||
|
||||
* migrate from `echo` to `go-fiber`
|
||||
* upgrade go to v1.20.1
|
||||
* more functions to handle artalk lifecycle ([#426](https://github.com/ArtalkJS/Artalk/issues/426))
|
||||
* Add script to build artalk-sidebar
|
||||
* Use bluemonday sanitizer
|
||||
* Global trusted_domain config
|
||||
* launch with vscode debugger
|
||||
* display IP region of comment ([#418](https://github.com/ArtalkJS/Artalk/issues/418)) ([#447](https://github.com/ArtalkJS/Artalk/issues/447))
|
||||
* docker ci add support for building arm64 wheels
|
||||
* one-key site creating with artalk integrated
|
||||
* trusted_domains disable referer check
|
||||
* ApiVersion & FeMinVersion.
|
||||
* Page PV counter
|
||||
* Pagination of admin_page_get.
|
||||
* FeMinVersion update to 2.0.5
|
||||
* root path redict to sidebar login page
|
||||
* FindCommentChildren query db while cache miss
|
||||
* Add goreleaser with golang-cross.
|
||||
* Remove example config allow_origins field
|
||||
* Specific comments get flat mode.
|
||||
* Add robots.txt.
|
||||
* Typecho Impoter.
|
||||
* admin_users password support to be encrypted by using bcrypt.
|
||||
* Page title fetch support meta tag redirect link
|
||||
* Admin update all title of pages.
|
||||
* Typecho Impoter add some hint.
|
||||
* **anti-spam:** Support Aliyun for Spam detection.
|
||||
* **anti-spam:** Support KeyWords for Spam detection.
|
||||
* **api:** Add Accessible URL fields
|
||||
* **api:** Modify some APIs method to post
|
||||
* **api:** Get login status API
|
||||
* **api:** New statistic api
|
||||
* **api:** Site cannot find err mark
|
||||
* **api:** settings get & save
|
||||
* **api-import-upload:** Frontend importer upload before.
|
||||
* **api_add:** Allow patch user-agent parameter
|
||||
* **api_admin_cache:** Add api handle cache
|
||||
* **api_admin_page_fetch:** Add GetStatus parameter.
|
||||
* **api_login_status:** Add is_admin field
|
||||
* **artrans:** Import from Artalk v1 (PHP).
|
||||
* **artrans:** Export and Import Artrans type data.
|
||||
* **artrans:** Run on frontend client.
|
||||
* **cache:** Almost full cache coverage.
|
||||
* **cache:** Support redis & memcache
|
||||
* **cache:** Replace built-in json lib with vmihailenco/msgpack to speed up
|
||||
* more functions to handle artalk lifecycle ([#426](https://github.com/ArtalkJS/Artalk/issues/426))
|
||||
* **ui:** add some static methods
|
||||
* **ui/height_limit:** support scrollable height limit area ([#451](https://github.com/ArtalkJS/Artalk/issues/451))
|
||||
* **ui/sidebar:** add dark mode support ([#450](https://github.com/ArtalkJS/Artalk/issues/450))
|
||||
* **captcha:** add support for reCAPTCHA and hCaptcha ([#456](https://github.com/ArtalkJS/Artalk/issues/456))
|
||||
* **captcha:** support turnstile captcha by cloudflare ([#453](https://github.com/ArtalkJS/Artalk/issues/453))
|
||||
* **cmd:** Add workdir parameter & gen cmd.
|
||||
* **cmd:** add admin command to create new user
|
||||
* **cmd:** Add config cmd
|
||||
* **comment:** Add field content_marked to render the markdown content
|
||||
* **conf:** Support control Frontend Conf by Backend.
|
||||
* **conf:** add conf option for specific email tpl for admins
|
||||
* **conf:** auto-gen config file when initializing the app
|
||||
* **conf:** Support for admin_notify.email.enabled option
|
||||
* **conf:** Support for admin_notify.noise_mode option
|
||||
* **conf:** Config database options not just dsn.
|
||||
* **db:** Remove formal foreign key constraints
|
||||
* **db:** Allow set table_prefix
|
||||
* **email-tpl:** add ip variable to email template
|
||||
* **geetest:** Provide geetest check API for frontend.
|
||||
* **geetest:** Access geetest API
|
||||
* **gen:** Gen cmd support overwrite file
|
||||
* **go:** upgrade to Go 1.19 and update some deps
|
||||
* **go:** Update golang to v1.18.1
|
||||
* **i18n:** add i18n support for backend ([#343](https://github.com/ArtalkJS/Artalk/issues/343))
|
||||
* **i18n:** translations for backend ([#344](https://github.com/ArtalkJS/Artalk/issues/344))
|
||||
* **i18n:** add i18n support for sidebar ([#353](https://github.com/ArtalkJS/Artalk/issues/353))
|
||||
* **i18n:** add zh-TW i18n translation for sidebar and app
|
||||
* **img-upload:** Add img-upload option to config file.
|
||||
* **img-upload:** Image Upload Api
|
||||
* **img-upload:** Upload rate limitation.
|
||||
* **img-upload:** Upload using upgit
|
||||
* **img-upload:** Admin always enable img_upload function.
|
||||
* **importer:** import from Twikoo.
|
||||
* **importer:** import from valine.
|
||||
* **importer:** Speed up importer & fix some bugs.
|
||||
* **model:** Add IsPinned field into commnent model.
|
||||
* **multi-site:** Isolate admin users among sites
|
||||
* **notify:** Support WebHook notify
|
||||
* **notify:** Various ways to send notify message for admin.
|
||||
* **notify:** Support template & fix some bugs
|
||||
* **pin:** Update admin_comment_edit api to edit IsPinned
|
||||
* **pin:** Pin comments keep most top & Child-comments recursive query use Cooked.
|
||||
* **pv:** Make route rule & create pvs table
|
||||
* **self-upgrade:** Add cmd Self-upgrade function
|
||||
* **tencent_tms:** Support tencent tms for Spam detection.
|
||||
* **ui:** add some static methods
|
||||
* **upgit:** Config del_local to remove local file after uploaded.
|
||||
* **upgrade:** Upgrade command allow ignore version check.
|
||||
* **user:** Admin email sending isolation between sites.
|
||||
* **version:** Update Frontend min version to 2.2.1
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ui:** hash goto function check condition issue
|
||||
* **ui/conf:** avoid some conf overrides frontend from the backend ([#449](https://github.com/ArtalkJS/Artalk/issues/449))
|
||||
* **ui/editor:** disable img upload cannot hide its btn
|
||||
* **ui/i18n:** subscribe event priority issue
|
||||
* **ui/sidebar:** array type of preference initial data issue
|
||||
* **ui/sidebar:** array type config option cannot be shown
|
||||
* **ui/sidebar:** boolean type setting option save issue ([#431](https://github.com/ArtalkJS/Artalk/issues/431)) ([#444](https://github.com/ArtalkJS/Artalk/issues/444))
|
||||
* **ui/sidebar:** setting item save follow type of template
|
||||
* **lint:** add tsc check before vite compile ([#440](https://github.com/ArtalkJS/Artalk/issues/440))
|
||||
* **email:** duplicate sending with multiple admins using same email addrs ([#375](https://github.com/ArtalkJS/Artalk/issues/375))
|
||||
* **email:** email queue initialization issue ([#374](https://github.com/ArtalkJS/Artalk/issues/374))
|
||||
* **email:** failback to `email.mail_tpl` if `admin_notify.email.mail_tpl` is empty
|
||||
* `timeAgo` function does not display the now
|
||||
* add `.npmignore` to fix NPM publish inclusion issue
|
||||
* sidebar navigation sorting ([#361](https://github.com/ArtalkJS/Artalk/issues/361))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **conf:** only provide conf for frontend when fetching the first page
|
||||
* **docker-build:** cache by separating the downloading of deps
|
||||
* **trusted_domains:** Improve origin checker
|
||||
* improve some css styles
|
||||
* add graceful shutdown
|
||||
* **conf/i18n:** detect and change locale when config file contains chinese
|
||||
* **ui/list:** remove useless function call
|
||||
* **ui/sidebar:** improve sidebar i18n
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* bump to monorepo
|
||||
* renamed from artalk-go to artalk
|
||||
* http origin checker
|
||||
* abstract email service
|
||||
* project package structure
|
||||
* remove version two-way check ([#452](https://github.com/ArtalkJS/Artalk/issues/452))
|
||||
* build scripts and CI tests
|
||||
* replace pkger with go:embed
|
||||
* launch with vscode debugger
|
||||
* **CI:** one-key site creating with artalk integrated
|
||||
* **CI:** improve build and release workflows ([#358](https://github.com/ArtalkJS/Artalk/issues/358))
|
||||
* **captcha:** abstract captcha service ([#455](https://github.com/ArtalkJS/Artalk/issues/455))
|
||||
* **comment:** separate comment ui renders from single file ([#427](https://github.com/ArtalkJS/Artalk/issues/427))
|
||||
* **style:** convert to use Sass as a style interpreter ([#439](https://github.com/ArtalkJS/Artalk/issues/439))
|
||||
* **ui:** automatic dependency injection ([#429](https://github.com/ArtalkJS/Artalk/issues/429))
|
||||
* **ui/checker:** simplify checker lifecycle function param table ([#428](https://github.com/ArtalkJS/Artalk/issues/428))
|
||||
* **ui/dark-mode:** separate dark mode logic into its own module ([#430](https://github.com/ArtalkJS/Artalk/issues/430))
|
||||
* **ui/editor:** modify editor ui to standalone module ([#441](https://github.com/ArtalkJS/Artalk/issues/441))
|
||||
* **ui/editor:** change functions of editor to standalone modules ([#443](https://github.com/ArtalkJS/Artalk/issues/443))
|
||||
* **ui/height-limit:** modify height limit function to standalone module ([#435](https://github.com/ArtalkJS/Artalk/issues/435))
|
||||
* **ui/i18n:** improve i18n function to standalone module ([#434](https://github.com/ArtalkJS/Artalk/issues/434))
|
||||
* **ui/list:** modify list pagination to standalone module ([#437](https://github.com/ArtalkJS/Artalk/issues/437))
|
||||
* **page/fetch:** remove goquery dependency when extracting page data ([#442](https://github.com/ArtalkJS/Artalk/issues/442))
|
||||
* **anti_spam/qcloud-tms:** implement qcloud tms api without sdk ([#438](https://github.com/ArtalkJS/Artalk/issues/438))
|
||||
|
||||
### Documentation
|
||||
|
||||
* migrate ArtalkJS/Docs to monorepo docs
|
||||
* add `CODE_OF_CONDUCT.md`
|
||||
* add simplified README for artalk npm package
|
||||
* add translation section to `CONTRIBUTING.md`
|
||||
* fix wrong config value ([#371](https://github.com/ArtalkJS/Artalk/issues/371))
|
||||
* fix broken links ([#364](https://github.com/ArtalkJS/Artalk/issues/364))
|
||||
* add open api ([#360](https://github.com/ArtalkJS/Artalk/issues/360))
|
||||
* add `Project Structure` section to `CONTRIBUTING.md`
|
||||
* refine and add frontend api docs
|
||||
* update setup-example-site.sh script usage
|
||||
* init artalk with new frontend api
|
||||
* **deploy:** add `restart=always` for docker to auto restart ([#425](https://github.com/ArtalkJS/Artalk/issues/425))
|
||||
* **extras:** add deploy guide for vuepress ([#436](https://github.com/ArtalkJS/Artalk/issues/436))
|
||||
+11
-11
@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the overall
|
||||
- Focusing on what is best not just for us as individuals, but for the overall
|
||||
community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||
- The use of sexualized language or imagery, and sexual attention or advances of
|
||||
any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email address,
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email address,
|
||||
without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
@@ -59,7 +59,7 @@ representative at an online or offline event.
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at artalkjs@gmail.com.
|
||||
reported to the community leaders responsible for enforcement at <artalkjs@gmail.com>.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
|
||||
+42
-15
@@ -6,8 +6,8 @@ This guide is for developers who want to contribute to the project.
|
||||
|
||||
To develop Artalk, including the frontend and backend, you need to install the following tools:
|
||||
|
||||
- [Node.js](https://nodejs.org/en/) (>= 16.0.0)
|
||||
- [Go](https://golang.org/) (>= 1.20)
|
||||
- [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)
|
||||
|
||||
@@ -29,33 +29,52 @@ Enter the directory:
|
||||
cd Artalk
|
||||
```
|
||||
|
||||
### Build frontend and backend
|
||||
### Build Backend
|
||||
|
||||
First, we need to install the dependencies for backend written in Go. Simply run the following command:
|
||||
First, you need to install the dependencies for the backend written in Go. Simply run the `make install` command to install the dependencies.
|
||||
|
||||
```sh
|
||||
make build-debug
|
||||
```
|
||||
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`.
|
||||
|
||||
This will build both the frontend and backend, with debugging symbols.
|
||||
This will build the backend with debugging symbols. The binary file will be placed under the `./bin` directory.
|
||||
|
||||
- **Frontend** will be built under `./ui/packages/artalk` and copied to `./public` directory.
|
||||
- **Backend** will be built under `./bin` directory.
|
||||
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.
|
||||
|
||||
### Optional: Use one-key script to run a demo site
|
||||
### Build Frontend
|
||||
|
||||
If you want to run a demo site, you can use the following command:
|
||||
First, you need to install the dependencies for the frontend. Simply run the `cd ui && pnpm install` command to install the dependencies.
|
||||
|
||||
Then, run the `cd ui && pnpm dev` to build and run the frontend, and you can pass startup parameters to the program using `ARGS="--port 5173" pnpm dev`.
|
||||
|
||||
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.
|
||||
|
||||
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`.
|
||||
|
||||
### Development Workflow
|
||||
|
||||
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 `cd ui && 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.
|
||||
|
||||
When you make changes to the frontend code, you can build the complete frontend program using `cd ui && pnpm build:all`. The JavaScript and CSS code can be found in `ui/packages/artalk/dist`.
|
||||
|
||||
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.
|
||||
|
||||
Additionally, there is automated CI on GitHub for building. You can find the relevant code in the `.github/workflows` directory.
|
||||
|
||||
### Optional: Use a One-Key Script to Run a Demo Site
|
||||
|
||||
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.
|
||||
|
||||
Run the following command:
|
||||
|
||||
```sh
|
||||
./scripts/setup-example-site.sh
|
||||
```
|
||||
|
||||
This script sets up a local example site for testing at `local` folder, with Artalk integrated into its theme.
|
||||
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 ./local/local.yml
|
||||
./bin/artalk server -c ./data/artalk.yml
|
||||
```
|
||||
|
||||
to start the artalk server.
|
||||
@@ -70,6 +89,14 @@ 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.
|
||||
|
||||
## 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.
|
||||
@@ -80,7 +107,7 @@ Artalk is a monorepo project, which means all the source code is in the same rep
|
||||
- `docs/` - The documentation site source code.
|
||||
- `i18n/` - The translation files.
|
||||
- `internal/` - The internal packages.
|
||||
- `local/` - The local example site. This directory is ignored by git.
|
||||
- `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.
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
### build Artalk
|
||||
FROM golang:1.20.1-alpine3.17 as builder
|
||||
FROM golang:1.21.3-alpine3.18 as builder
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
# install tools
|
||||
RUN set -ex \
|
||||
&& apk add --no-cache make git gcc musl-dev nodejs bash npm\
|
||||
&& npm install -g pnpm@7.25.0
|
||||
&& npm install -g pnpm@8.12.1
|
||||
|
||||
# download go deps
|
||||
# (cache by separating the downloading of deps)
|
||||
@@ -23,7 +23,7 @@ RUN set -ex \
|
||||
&& make build
|
||||
|
||||
### build final image
|
||||
FROM alpine:3.17
|
||||
FROM alpine:3.18
|
||||
|
||||
# we set the timezone `Asia/Shanghai` by default, you can be modified
|
||||
# by `docker build --build-arg="TZ=Other_Timezone ..."`
|
||||
|
||||
@@ -1,165 +1,21 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
Copyright (c) 2018-present, qwqcode and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -44,10 +44,15 @@ test:
|
||||
test-coverage:
|
||||
$(GOTEST) -cover ./...
|
||||
|
||||
test-coverage-html:
|
||||
$(GOTEST) -v -coverprofile=coverage.out ./...
|
||||
go tool cover -html=coverage.out
|
||||
|
||||
update-i18n:
|
||||
go generate ./internal/i18n
|
||||
|
||||
update-swagger:
|
||||
go install github.com/swaggo/swag/cmd/swag@latest
|
||||
swag init -g server/server.go --output ./docs/swagger
|
||||
|
||||
docker-build:
|
||||
@@ -56,6 +61,9 @@ 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 update-i18n \
|
||||
docker-build docker-push;
|
||||
dev test test-coverage test-coverage-html update-i18n \
|
||||
docker-build docker-push test-frontend-e2e;
|
||||
+5
-5
@@ -4,12 +4,12 @@
|
||||
|
||||
# Artalk
|
||||
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://bundlephobia.com/package/artalk)
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://bundlephobia.com/package/artalk)
|
||||
[](https://circleci.com/gh/ArtalkJS/Artalk/tree/master)
|
||||
|
||||
> 🌌 A Self-hosted comment system
|
||||
> 🌌 A self-hosted comment system
|
||||
|
||||
[简体中文](./README.md) / [Documentation](https://artalk.js.org) / [Releases](https://github.com/ArtalkJS/Artalk/releases) / [Artalk](https://github.com/ArtalkJS/Artalk)
|
||||
|
||||
@@ -131,7 +131,7 @@ Thanks for the help and feedback provided by the community, if you have good sug
|
||||
|
||||
## License
|
||||
|
||||
[LGPL-3.0](./LICENSE)
|
||||
[MIT](./LICENSE)
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FArtalkJS%2FArtalk?ref=badge_shield)
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
# Artalk
|
||||
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://bundlephobia.com/package/artalk)
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://www.npmjs.com/package/artalk)
|
||||
[](https://hub.docker.com/r/artalk/artalk-go)
|
||||
[](https://circleci.com/gh/ArtalkJS/Artalk/tree/master)
|
||||
[](https://goreportcard.com/report/github.com/ArtalkJS/Artalk)
|
||||
[](https://circleci.com/gh/ArtalkJS/Artalk/tree/master)
|
||||
[](https://codecov.io/gh/ArtalkJS/Artalk)
|
||||
[](https://bundlephobia.com/package/artalk)
|
||||
|
||||
> 🌌 Golang 自托管评论系统
|
||||
|
||||
@@ -53,13 +55,19 @@
|
||||
- 支持 Latex:提供集成 Katex 插件
|
||||
- 使用 [Vite](https://github.com/vitejs/vite):属于开发者的极致体验
|
||||
|
||||
更多内容请查看:[“**介绍文档**”](https://artalk.js.org/guide/intro.html)
|
||||
更多内容请查看:[**介绍文档**](https://artalk.js.org/guide/intro.html)
|
||||
|
||||
## 食用方针
|
||||
## 安装
|
||||
|
||||
前往:[“**部署文档**”](https://artalk.js.org/guide/deploy.html)
|
||||
参考:[**部署文档**](https://artalk.js.org/guide/deploy.html)
|
||||
|
||||
```bash
|
||||
npm install artalk
|
||||
```
|
||||
|
||||
```ts
|
||||
import Artalk from 'artalk'
|
||||
|
||||
Artalk.init({
|
||||
el: '#Comments',
|
||||
site: 'Artalk 的博客',
|
||||
@@ -74,6 +82,7 @@ docker run -d \
|
||||
--name artalk \
|
||||
-p 8080:23366 \
|
||||
-v $(pwd)/data:/data \
|
||||
--restart=always \
|
||||
artalk/artalk-go
|
||||
```
|
||||
|
||||
@@ -89,6 +98,7 @@ services:
|
||||
artalk:
|
||||
container_name: artalk
|
||||
image: artalk/artalk-go
|
||||
restart: always
|
||||
ports:
|
||||
- 8080:23366
|
||||
volumes:
|
||||
@@ -119,7 +129,7 @@ see [CONTRIBUTING.md](./CONTRIBUTING.md)
|
||||
|
||||
感谢社区提供的帮助与反馈,若有好的建议与意见欢迎前往 [ISSUES](https://github.com/ArtalkJS/Artalk/issues) 随时告知。
|
||||
|
||||
## TODOs
|
||||
## TODOs
|
||||
|
||||
- [x] Golang 后端
|
||||
- [x] 多数据库支持
|
||||
@@ -171,6 +181,8 @@ see [CONTRIBUTING.md](./CONTRIBUTING.md)
|
||||
- [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/)
|
||||
@@ -217,7 +229,7 @@ see [CONTRIBUTING.md](./CONTRIBUTING.md)
|
||||
|
||||
## License
|
||||
|
||||
[LGPL-3.0](./LICENSE)
|
||||
[MIT](./LICENSE)
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2FArtalkJS%2FArtalk?ref=badge_shield)
|
||||
|
||||
|
||||
+44
-49
@@ -2,72 +2,67 @@ package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/ArtalkJS/Artalk/internal/entity"
|
||||
"github.com/ArtalkJS/Artalk/internal/i18n"
|
||||
"github.com/ArtalkJS/Artalk/internal/query"
|
||||
"github.com/ArtalkJS/Artalk/internal/log"
|
||||
"github.com/ArtalkJS/Artalk/internal/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
var adminCmd = &cobra.Command{
|
||||
Use: "admin",
|
||||
Short: "Create or edit an administrator account",
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
core.LoadCore(cfgFile, workDir)
|
||||
func NewAdminCommand(app *ArtalkCmd) *cobra.Command {
|
||||
adminCmd := &cobra.Command{
|
||||
Use: "admin",
|
||||
Short: "Create or edit an administrator account",
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("--------------------------------")
|
||||
fmt.Println(" " + i18n.T("Create admin account"))
|
||||
fmt.Println("--------------------------------")
|
||||
|
||||
fmt.Println("--------------------------------")
|
||||
fmt.Println(" " + i18n.T("Create admin account"))
|
||||
fmt.Println("--------------------------------")
|
||||
|
||||
username, email, password, err := credentials()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
findUser := query.FindUser(username, email)
|
||||
if !findUser.IsEmpty() {
|
||||
findUser.SetPasswordEncrypt(password)
|
||||
if err := query.UpdateUser(&findUser); err != nil {
|
||||
logrus.Fatal(err)
|
||||
username, email, password, err := credentials()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
logrus.Info(i18n.T("{{name}} already exists", map[string]interface{}{"name": i18n.T("Account")}) +
|
||||
", " + i18n.T("Password updated"))
|
||||
return
|
||||
}
|
||||
findUser := app.Dao().FindUser(username, email)
|
||||
if !findUser.IsEmpty() {
|
||||
findUser.SetPasswordEncrypt(password)
|
||||
if err := app.Dao().UpdateUser(&findUser); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
user := entity.User{
|
||||
Name: username,
|
||||
Email: email,
|
||||
IsAdmin: true,
|
||||
BadgeName: i18n.T("Admin"),
|
||||
BadgeColor: "#0083FF",
|
||||
}
|
||||
user.SetPasswordEncrypt(password)
|
||||
log.Info(i18n.T("{{name}} already exists", map[string]interface{}{"name": i18n.T("Account")}) +
|
||||
", " + i18n.T("Password updated"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := query.CreateUser(&user); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
user := entity.User{
|
||||
Name: username,
|
||||
Email: email,
|
||||
IsAdmin: true,
|
||||
BadgeName: i18n.T("Admin"),
|
||||
BadgeColor: "#0083FF",
|
||||
}
|
||||
user.SetPasswordEncrypt(password)
|
||||
|
||||
fmt.Println("--------------------------------")
|
||||
fmt.Println(" Name: " + username)
|
||||
fmt.Println(" Mail: " + email)
|
||||
fmt.Println("--------------------------------")
|
||||
},
|
||||
}
|
||||
if err := app.Dao().CreateUser(&user); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(adminCmd)
|
||||
fmt.Println("--------------------------------")
|
||||
fmt.Println(" Name: " + username)
|
||||
fmt.Println(" Mail: " + email)
|
||||
fmt.Println("--------------------------------")
|
||||
},
|
||||
}
|
||||
|
||||
return adminCmd
|
||||
}
|
||||
|
||||
func credentials() (string, string, string, error) {
|
||||
@@ -85,7 +80,7 @@ func credentials() (string, string, string, error) {
|
||||
return "", "", "", err
|
||||
}
|
||||
if !utils.ValidateEmail(strings.TrimSpace(email)) {
|
||||
return "", "", "", errors.New("invalid email format")
|
||||
return "", "", "", fmt.Errorf("invalid email format")
|
||||
}
|
||||
|
||||
fmt.Print(i18n.T("Enter {{name}}", map[string]interface{}{"name": i18n.T("Password")}) + ": ")
|
||||
@@ -107,7 +102,7 @@ func credentials() (string, string, string, error) {
|
||||
rePassword := strings.TrimSpace(string(byteRePassword))
|
||||
|
||||
if rePassword != password {
|
||||
return "", "", "", errors.New("inconsistent password input")
|
||||
return "", "", "", fmt.Errorf("inconsistent password input")
|
||||
}
|
||||
|
||||
return strings.TrimSpace(username), strings.TrimSpace(email), password, nil
|
||||
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/config"
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/ArtalkJS/Artalk/internal/log"
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var Version = config.Version + `/` + config.CommitHash
|
||||
|
||||
var Banner = `
|
||||
________ ________ _________ ________ ___ ___ __
|
||||
|\ __ \|\ __ \|\___ ___\\ __ \|\ \ |\ \|\ \
|
||||
\ \ \|\ \ \ \|\ \|___ \ \_\ \ \|\ \ \ \ \ \ \/ /|_
|
||||
\ \ __ \ \ _ _\ \ \ \ \ \ __ \ \ \ \ \ ___ \
|
||||
\ \ \ \ \ \ \\ \| \ \ \ \ \ \ \ \ \ \____\ \ \\ \ \
|
||||
\ \__\ \__\ \__\\ _\ \ \__\ \ \__\ \__\ \_______\ \__\\ \__\
|
||||
\|__|\|__|\|__|\|__| \|__| \|__|\|__|\|_______|\|__| \|__|
|
||||
|
||||
Artalk (` + Version + `)
|
||||
|
||||
-> A Self-hosted Comment System.
|
||||
-> https://artalk.js.org
|
||||
`
|
||||
|
||||
type ArtalkCmd struct {
|
||||
*core.App
|
||||
|
||||
cfgFile string
|
||||
workDir string
|
||||
|
||||
RootCmd *cobra.Command
|
||||
}
|
||||
|
||||
const BootModeKey = "BootMode"
|
||||
|
||||
const (
|
||||
MODE_FULL_BOOT = "FULL_BOOT"
|
||||
MODE_MINI_BOOT = "MINI_BOOT"
|
||||
)
|
||||
|
||||
func New() *ArtalkCmd {
|
||||
cmd := &ArtalkCmd{
|
||||
RootCmd: &cobra.Command{
|
||||
Use: "artalk",
|
||||
Short: "Artalk: A self-hosted comment system",
|
||||
Long: Banner,
|
||||
Version: Version,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(Banner)
|
||||
fmt.Print("-------------------------------\n\n")
|
||||
fmt.Println("NOTE: add `-h` flag to show help about any command.")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cmd.RootCmd.SetVersionTemplate("Artalk ({{printf \"%s\" .Version}})\n")
|
||||
|
||||
// Parse base flags
|
||||
cmd.eagerParseFlags()
|
||||
|
||||
// Change work directory
|
||||
if cmd.workDir != "" {
|
||||
if err := os.Chdir(cmd.workDir); err != nil {
|
||||
log.Fatal("Working directory change error: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Parses the global app flags before calling atk.RootCmd.Execute().
|
||||
// so we can have all flags ready for use on initialization.
|
||||
func (atk *ArtalkCmd) eagerParseFlags() error {
|
||||
atk.RootCmd.PersistentFlags().StringVarP(&atk.cfgFile, "config", "c", "", "config file path (defaults are './artalk.yml')")
|
||||
atk.RootCmd.PersistentFlags().StringVarP(&atk.workDir, "workdir", "w", "", "program working directory (defaults are './')")
|
||||
|
||||
return atk.RootCmd.ParseFlags(os.Args[1:])
|
||||
}
|
||||
|
||||
func (atk *ArtalkCmd) addCommand(cmd *cobra.Command) {
|
||||
originalPreRunFunc := cmd.PreRun
|
||||
|
||||
cmd.PreRun = func(cmd *cobra.Command, args []string) {
|
||||
// ================
|
||||
// APP Bootstrap
|
||||
// ================
|
||||
if cmd.Annotations[BootModeKey] != string(MODE_MINI_BOOT) {
|
||||
// Load config
|
||||
config, err := getConfig(atk.cfgFile)
|
||||
if err != nil {
|
||||
log.Fatal("Config fail: ", err)
|
||||
}
|
||||
|
||||
// Create new instance
|
||||
atk.App = core.NewApp(config)
|
||||
|
||||
// Bootstrap APP
|
||||
if err := atk.App.Bootstrap(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if originalPreRunFunc != nil {
|
||||
originalPreRunFunc(cmd, args) // extends original pre-run logic
|
||||
}
|
||||
}
|
||||
|
||||
atk.RootCmd.AddCommand(cmd)
|
||||
}
|
||||
|
||||
func (atk *ArtalkCmd) mountCommands() {
|
||||
atk.addCommand(NewServeCommand(atk))
|
||||
atk.addCommand(NewAdminCommand(atk))
|
||||
atk.addCommand(NewExportCommand(atk))
|
||||
atk.addCommand(NewImportCommand(atk))
|
||||
atk.addCommand(NewConfigCommand())
|
||||
atk.addCommand(NewGenCommand())
|
||||
atk.addCommand(NewUpgradeCommand())
|
||||
atk.addCommand(NewVersionCommand())
|
||||
}
|
||||
|
||||
func (atk *ArtalkCmd) Launch() error {
|
||||
// ===================
|
||||
// 1. Prepare Commands
|
||||
// ===================
|
||||
atk.mountCommands()
|
||||
|
||||
done := make(chan bool, 1) // shutdown signal
|
||||
|
||||
// listen for interrupt signal to gracefully shutdown the application
|
||||
go func() {
|
||||
sigch := make(chan os.Signal, 1)
|
||||
signal.Notify(sigch, os.Interrupt, syscall.SIGTERM)
|
||||
<-sigch
|
||||
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// ===================
|
||||
// 2. Command Execute
|
||||
// ===================
|
||||
go func() {
|
||||
if err := atk.RootCmd.Execute(); err != nil {
|
||||
color.Red(err.Error())
|
||||
}
|
||||
|
||||
done <- true
|
||||
}()
|
||||
|
||||
<-done
|
||||
|
||||
// ===================
|
||||
// 3. App Cleanups
|
||||
// ===================
|
||||
if atk.App != nil {
|
||||
return atk.App.OnTerminate().Trigger(&core.TerminateEvent{
|
||||
App: atk.App,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create new config instance by specific config filename
|
||||
func getConfig(cfgFile string) (*config.Config, error) {
|
||||
// Retrieve config file by default names when specific filename is empty
|
||||
if cfgFile == "" {
|
||||
cfgFile = config.RetrieveConfigFile()
|
||||
}
|
||||
|
||||
// Generate new config file when retrieve failed
|
||||
if cfgFile == "" {
|
||||
cfgFile = config.CONF_DEFAULT_FILENAMES[0]
|
||||
core.Gen("config", cfgFile, false)
|
||||
}
|
||||
|
||||
// Create new config instance and return
|
||||
return config.NewFromFile(cfgFile)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Shortcut Functions
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
func flag(cmd *cobra.Command, name string, defaultVal interface{}, usage string) {
|
||||
f := cmd.PersistentFlags()
|
||||
switch y := defaultVal.(type) {
|
||||
case bool:
|
||||
f.Bool(name, y, usage)
|
||||
case int:
|
||||
f.Int(name, y, usage)
|
||||
case string:
|
||||
f.String(name, y, usage)
|
||||
}
|
||||
}
|
||||
|
||||
func flagP(cmd *cobra.Command, name, shorthand string, defaultVal interface{}, usage string) {
|
||||
f := cmd.PersistentFlags()
|
||||
switch y := defaultVal.(type) {
|
||||
case bool:
|
||||
f.BoolP(name, shorthand, y, usage)
|
||||
case int:
|
||||
f.IntP(name, shorthand, y, usage)
|
||||
case string:
|
||||
f.StringP(name, shorthand, y, usage)
|
||||
}
|
||||
}
|
||||
|
||||
func flagV(cmd *cobra.Command, name string, defaultVal interface{}, usage string) {
|
||||
flag(cmd, name, defaultVal, usage)
|
||||
}
|
||||
|
||||
func flagPV(cmd *cobra.Command, name, shorthand string, defaultVal interface{}, usage string) {
|
||||
flagP(cmd, name, shorthand, defaultVal, usage)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewConfigCommand() *cobra.Command {
|
||||
configCmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Output Config Information",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// Get config filename from cmd flags
|
||||
filename, _ := cmd.Flags().GetString("config")
|
||||
|
||||
// Get new config instance
|
||||
config, err := getConfig(filename)
|
||||
if err != nil {
|
||||
log.Fatal("Config fail: ", err)
|
||||
}
|
||||
|
||||
// Output JSON of config
|
||||
buf, _ := json.MarshalIndent(config, "", " ")
|
||||
fmt.Println(string(buf))
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
BootModeKey: MODE_MINI_BOOT,
|
||||
},
|
||||
}
|
||||
|
||||
return configCmd
|
||||
}
|
||||
+47
-50
@@ -8,68 +8,65 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/artransfer"
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/ArtalkJS/Artalk/internal/i18n"
|
||||
"github.com/ArtalkJS/Artalk/internal/log"
|
||||
"github.com/ArtalkJS/Artalk/internal/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var exportCmd = &cobra.Command{
|
||||
Use: "export",
|
||||
Aliases: []string{},
|
||||
Short: "Artransfer - Export",
|
||||
Long: "\n# Artransfer - Export\n\n See the documentation to learn more: https://artalk.js.org/guide/transfer.html",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
core.LoadCore(cfgFile, workDir)
|
||||
|
||||
jsonStr, err := artransfer.ExportArtransString()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
if len(args) < 1 || args[0] == "" {
|
||||
// write to stdout
|
||||
fmt.Println(jsonStr)
|
||||
} else {
|
||||
filename := args[0]
|
||||
|
||||
// make sure is abs path
|
||||
filename, err := filepath.Abs(filename)
|
||||
func NewExportCommand(app *ArtalkCmd) *cobra.Command {
|
||||
exportCmd := &cobra.Command{
|
||||
Use: "export",
|
||||
Aliases: []string{},
|
||||
Short: "Artransfer export",
|
||||
Long: "\n# Artransfer - Export\n\n See the documentation to learn more: https://artalk.js.org/guide/transfer.html",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonStr, err := artransfer.RunExportArtrans(app.Dao(), &artransfer.ExportParams{})
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// check dir
|
||||
stat, err := os.Stat(filename)
|
||||
if err == nil {
|
||||
if stat.IsDir() {
|
||||
filename = path.Join(filename, "backup-"+time.Now().Format("20060102-150405")+".artrans")
|
||||
if len(args) < 1 || args[0] == "" {
|
||||
// write to stdout
|
||||
fmt.Println(jsonStr)
|
||||
} else {
|
||||
filename := args[0]
|
||||
|
||||
// make sure is abs path
|
||||
filename, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// mkdir -p
|
||||
if err := utils.EnsureDir(filepath.Dir(filename)); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
// check dir
|
||||
stat, err := os.Stat(filename)
|
||||
if err == nil {
|
||||
if stat.IsDir() {
|
||||
filename = path.Join(filename, "backup-"+time.Now().Format("20060102-150405")+".artrans")
|
||||
}
|
||||
}
|
||||
|
||||
// touch
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
// mkdir -p
|
||||
if err := utils.EnsureDir(filepath.Dir(filename)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// >
|
||||
_, err2 := f.WriteString(jsonStr)
|
||||
if err2 != nil {
|
||||
logrus.Fatal(err2)
|
||||
}
|
||||
// touch
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
logrus.Info(i18n.T("Export complete") + ": " + filename)
|
||||
}
|
||||
},
|
||||
}
|
||||
// >
|
||||
_, err2 := f.WriteString(jsonStr)
|
||||
if err2 != nil {
|
||||
log.Fatal(err2)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(exportCmd)
|
||||
log.Info(i18n.T("Export complete") + ": " + filename)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return exportCmd
|
||||
}
|
||||
+22
-29
@@ -1,41 +1,34 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var genCmd = &cobra.Command{
|
||||
Use: "gen <TYPE> <DEST>",
|
||||
Short: "A collection of several useful generators",
|
||||
Long: "Generate some content\ne.g. `artalk gen config ./artalk.yml`",
|
||||
Args: cobra.RangeArgs(1, 2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// change working directory
|
||||
if workDir != "" {
|
||||
if err := os.Chdir(workDir); err != nil {
|
||||
logrus.Fatal("change working directory error ", err)
|
||||
func NewGenCommand() *cobra.Command {
|
||||
genCmd := &cobra.Command{
|
||||
Use: "gen <TYPE> <DEST>",
|
||||
Short: "A collection of several useful generators",
|
||||
Long: "Generate some content\ne.g. `artalk gen config ./artalk.yml`",
|
||||
Args: cobra.RangeArgs(1, 2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var (
|
||||
specificPath string
|
||||
isForce bool
|
||||
)
|
||||
if len(args) > 1 {
|
||||
specificPath = args[1]
|
||||
}
|
||||
}
|
||||
isForce, _ = cmd.Flags().GetBool("force")
|
||||
|
||||
var (
|
||||
specificPath string
|
||||
isForce bool
|
||||
)
|
||||
if len(args) > 1 {
|
||||
specificPath = args[1]
|
||||
}
|
||||
isForce, _ = cmd.Flags().GetBool("force")
|
||||
|
||||
core.Gen(args[0], specificPath, isForce)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(genCmd)
|
||||
core.Gen(args[0], specificPath, isForce)
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
BootModeKey: MODE_MINI_BOOT,
|
||||
},
|
||||
}
|
||||
|
||||
flagPV(genCmd, "force", "f", false, "Force overwrite an existing file")
|
||||
|
||||
return genCmd
|
||||
}
|
||||
+24
-25
@@ -5,38 +5,37 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/artransfer"
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/ArtalkJS/Artalk/internal/i18n"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/ArtalkJS/Artalk/internal/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var importCmd = &cobra.Command{
|
||||
Use: "import <FILENAME>",
|
||||
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) {
|
||||
core.LoadCore(cfgFile, workDir) // load core
|
||||
func NewImportCommand(app *ArtalkCmd) *cobra.Command {
|
||||
importCmd := &cobra.Command{
|
||||
Use: "import <FILENAME>",
|
||||
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")}))
|
||||
}
|
||||
|
||||
parcelFile := args[0]
|
||||
if _, err := os.Stat(parcelFile); errors.Is(err, os.ErrNotExist) {
|
||||
logrus.Fatal(i18n.T("{{name}} not found", map[string]interface{}{"name": i18n.T("File")}))
|
||||
}
|
||||
payload := args[1:]
|
||||
payload = append(payload, "json_file:"+parcelFile)
|
||||
|
||||
payload := args[1:]
|
||||
payload = append(payload, "json_file:"+parcelFile)
|
||||
// import Artrans
|
||||
params := artransfer.ArrToImportParams(payload)
|
||||
params.Assumeyes, _ = cmd.Flags().GetBool("assumeyes")
|
||||
artransfer.RunImportArtrans(app.Dao(), params)
|
||||
|
||||
// import Artrans
|
||||
artransfer.RunImportArtrans(payload)
|
||||
|
||||
logrus.Info(i18n.T("Import complete"))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(importCmd)
|
||||
log.Info(i18n.T("Import complete"))
|
||||
},
|
||||
}
|
||||
|
||||
flagPV(importCmd, "assumeyes", "y", false, "Automatically answer yes for all questions.")
|
||||
|
||||
return importCmd
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/config"
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var Version = config.Version + `/` + config.CommitHash
|
||||
|
||||
var Banner = `
|
||||
________ ________ _________ ________ ___ ___ __
|
||||
|\ __ \|\ __ \|\___ ___\\ __ \|\ \ |\ \|\ \
|
||||
\ \ \|\ \ \ \|\ \|___ \ \_\ \ \|\ \ \ \ \ \ \/ /|_
|
||||
\ \ __ \ \ _ _\ \ \ \ \ \ __ \ \ \ \ \ ___ \
|
||||
\ \ \ \ \ \ \\ \| \ \ \ \ \ \ \ \ \ \____\ \ \\ \ \
|
||||
\ \__\ \__\ \__\\ _\ \ \__\ \ \__\ \__\ \_______\ \__\\ \__\
|
||||
\|__|\|__|\|__|\|__| \|__| \|__|\|__|\|_______|\|__| \|__|
|
||||
|
||||
Artalk (` + Version + `)
|
||||
|
||||
-> A Selfhosted Comment System.
|
||||
-> https://artalk.js.org
|
||||
`
|
||||
|
||||
var (
|
||||
cfgFile string
|
||||
workDir string
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "artalk",
|
||||
Short: "Artalk: A Fast, Slight & Delightful Comment System",
|
||||
Long: Banner,
|
||||
Version: Version,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(Banner)
|
||||
fmt.Print("-------------------------------\n\n")
|
||||
fmt.Println("NOTE: add `-h` flag to show help about any command.")
|
||||
},
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
cobra.CheckErr(rootCmd.Execute())
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.SetVersionTemplate("Artalk ({{printf \"%s\" .Version}})\n")
|
||||
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file path (defaults are './artalk.yml')")
|
||||
rootCmd.PersistentFlags().StringVarP(&workDir, "workdir", "w", "", "program working directory (defaults are './')")
|
||||
|
||||
// Version Command
|
||||
versionCmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Output Version Information",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Artalk (" + Version + ")")
|
||||
},
|
||||
}
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
|
||||
// Config Command
|
||||
configCmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Output Config Information",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
core.LoadConfOnly(cfgFile, workDir)
|
||||
buf, _ := json.MarshalIndent(config.Instance, "", " ")
|
||||
fmt.Println(string(buf))
|
||||
},
|
||||
}
|
||||
rootCmd.AddCommand(configCmd)
|
||||
|
||||
}
|
||||
+21
-72
@@ -2,85 +2,34 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/config"
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/ArtalkJS/Artalk/internal/log"
|
||||
"github.com/ArtalkJS/Artalk/server"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Aliases: []string{"serve"},
|
||||
Short: "Start the server",
|
||||
Long: Banner,
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
core.LoadCore(cfgFile, workDir)
|
||||
func NewServeCommand(app *ArtalkCmd) *cobra.Command {
|
||||
var serverCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Aliases: []string{"serve"},
|
||||
Short: "Start the server",
|
||||
Long: Banner,
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(Banner)
|
||||
fmt.Print("-------------------------------\n\n")
|
||||
|
||||
fmt.Println(Banner)
|
||||
fmt.Print("-------------------------------\n\n")
|
||||
|
||||
// create fiber app
|
||||
// @see https://docs.gofiber.io/api/fiber#config
|
||||
app := fiber.New(fiber.Config{
|
||||
// @see https://github.com/gofiber/fiber/issues/426
|
||||
// @see https://github.com/gofiber/fiber/issues/185
|
||||
Immutable: true,
|
||||
|
||||
// TODO add config to set ProxyHeader
|
||||
ProxyHeader: "X-Forwarded-For",
|
||||
EnableIPValidation: true,
|
||||
})
|
||||
|
||||
// logger
|
||||
app.Use(logger.New(logger.Config{
|
||||
Format: "[${status}] ${method} ${path} ${latency} ${ip} ${reqHeader:X-Request-ID} ${referer} ${ua}\n",
|
||||
Output: io.Discard,
|
||||
Done: func(c *fiber.Ctx, logString []byte) {
|
||||
statusOK := c.Response().StatusCode() >= 200 && c.Response().StatusCode() <= 302
|
||||
if !statusOK {
|
||||
logrus.StandardLogger().WriterLevel(logrus.ErrorLevel).Write(logString)
|
||||
} else {
|
||||
logrus.StandardLogger().WriterLevel(logrus.DebugLevel).Write(logString)
|
||||
}
|
||||
},
|
||||
}))
|
||||
|
||||
// init router
|
||||
server.Init(app)
|
||||
|
||||
// graceful shutdown signal listen
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
<-c
|
||||
fmt.Println("Gracefully shutting down...")
|
||||
_ = app.Shutdown()
|
||||
}()
|
||||
|
||||
// socket listen
|
||||
listenAddr := fmt.Sprintf("%s:%d", config.Instance.Host, config.Instance.Port)
|
||||
if config.Instance.SSL.Enabled {
|
||||
app.ListenTLS(listenAddr, config.Instance.SSL.CertPath, config.Instance.SSL.KeyPath)
|
||||
} else {
|
||||
app.Listen(listenAddr)
|
||||
}
|
||||
|
||||
// graceful shutdown tasks
|
||||
fmt.Println("Running cleanup tasks...")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(serverCmd)
|
||||
// init fiber app
|
||||
_, err := server.Serve(app.App)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
flagPV(serverCmd, "host", "", "0.0.0.0", "Listening IP")
|
||||
flagPV(serverCmd, "port", "", 23366, "Listening port")
|
||||
|
||||
return serverCmd
|
||||
}
|
||||
+44
-44
@@ -6,63 +6,63 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/ArtalkJS/Artalk/internal/config"
|
||||
"github.com/ArtalkJS/Artalk/internal/core"
|
||||
"github.com/ArtalkJS/Artalk/internal/i18n"
|
||||
"github.com/ArtalkJS/Artalk/internal/log"
|
||||
"github.com/blang/semver"
|
||||
"github.com/rhysd/go-github-selfupdate/selfupdate"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var upgradeCmd = &cobra.Command{
|
||||
Use: "upgrade",
|
||||
Aliases: []string{"update"},
|
||||
Short: "Upgrade to the latest version",
|
||||
Long: "Upgrade Artalk to the latest version, \n update source is GitHub Releases, \n update need to restart Artalk to take effect.",
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// loadCore()
|
||||
core.LoadConfOnly(cfgFile, workDir)
|
||||
func NewUpgradeCommand() *cobra.Command {
|
||||
upgradeCmd := &cobra.Command{
|
||||
Use: "upgrade",
|
||||
Aliases: []string{"update"},
|
||||
Short: "Upgrade to the latest version",
|
||||
Long: "Upgrade Artalk to the latest version, \n update source is GitHub Releases, \n update need to restart Artalk to take effect.",
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Info(i18n.T("Checking for updates") + "...")
|
||||
|
||||
logrus.Info(i18n.T("Checking for updates") + "...")
|
||||
|
||||
latest, found, err := selfupdate.DetectLatest("ArtalkJS/Artalk")
|
||||
if err != nil {
|
||||
logrus.Fatal("Error occurred while detecting version: ", err)
|
||||
}
|
||||
|
||||
ignoreVersionCheck, _ := cmd.Flags().GetBool("force")
|
||||
if !ignoreVersionCheck {
|
||||
v := semver.MustParse(strings.TrimPrefix(config.Version, "v"))
|
||||
if !found || latest.Version.LTE(v) {
|
||||
logrus.Println(i18n.T("Current version is the latest") + " (v" + v.String() + ")")
|
||||
return
|
||||
latest, found, err := selfupdate.DetectLatest("ArtalkJS/Artalk")
|
||||
if err != nil {
|
||||
log.Fatal("Error occurred while detecting version: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Info(i18n.T("New version available") + ": v" + latest.Version.String())
|
||||
logrus.Info(i18n.T("Downloading") + "...")
|
||||
ignoreVersionCheck, _ := cmd.Flags().GetBool("force")
|
||||
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() + ")")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
logrus.Fatal("Could not locate executable path ", err)
|
||||
}
|
||||
log.Info(i18n.T("New version available") + ": v" + latest.Version.String())
|
||||
log.Info(i18n.T("Downloading") + "...")
|
||||
|
||||
if err := selfupdate.UpdateTo(latest.AssetURL, exe); err != nil {
|
||||
logrus.Fatal(i18n.T("Update failed")+" ", err)
|
||||
}
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
log.Fatal("Could not locate executable path ", err)
|
||||
}
|
||||
|
||||
logrus.Println(i18n.T("Update complete"))
|
||||
fmt.Println("\n-------------------------------\n v" +
|
||||
latest.Version.String() +
|
||||
" Release Note\n" +
|
||||
"-------------------------------\n\n" +
|
||||
latest.ReleaseNotes)
|
||||
},
|
||||
}
|
||||
if err := selfupdate.UpdateTo(latest.AssetURL, exe); err != nil {
|
||||
log.Fatal(i18n.T("Update failed")+" ", err)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(upgradeCmd)
|
||||
log.Println(i18n.T("Update complete"))
|
||||
fmt.Printf("\n"+
|
||||
"-------------------------------\n"+
|
||||
" v%s Release Note\n"+
|
||||
"-------------------------------\n\n"+
|
||||
"%s\n",
|
||||
latest.Version.String(), latest.ReleaseNotes)
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
BootModeKey: MODE_MINI_BOOT,
|
||||
},
|
||||
}
|
||||
|
||||
flagPV(upgradeCmd, "force", "f", false, "Force upgrade ignore version comparison.")
|
||||
|
||||
return upgradeCmd
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
//// Shortcut Functions ////
|
||||
|
||||
func flag(cmd *cobra.Command, name string, defaultVal interface{}, usage string) {
|
||||
f := cmd.PersistentFlags()
|
||||
switch y := defaultVal.(type) {
|
||||
case bool:
|
||||
f.Bool(name, y, usage)
|
||||
case int:
|
||||
f.Int(name, y, usage)
|
||||
case string:
|
||||
f.String(name, y, usage)
|
||||
}
|
||||
}
|
||||
|
||||
func flagP(cmd *cobra.Command, name, shorthand string, defaultVal interface{}, usage string) {
|
||||
f := cmd.PersistentFlags()
|
||||
switch y := defaultVal.(type) {
|
||||
case bool:
|
||||
f.BoolP(name, shorthand, y, usage)
|
||||
case int:
|
||||
f.IntP(name, shorthand, y, usage)
|
||||
case string:
|
||||
f.StringP(name, shorthand, y, usage)
|
||||
}
|
||||
}
|
||||
|
||||
func flagV(cmd *cobra.Command, name string, defaultVal interface{}, usage string) {
|
||||
flag(cmd, name, defaultVal, usage)
|
||||
}
|
||||
|
||||
func flagPV(cmd *cobra.Command, name, shorthand string, defaultVal interface{}, usage string) {
|
||||
flagP(cmd, name, shorthand, defaultVal, usage)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewVersionCommand() *cobra.Command {
|
||||
versionCmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Output version information",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Artalk (" + Version + ")")
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
BootModeKey: MODE_MINI_BOOT,
|
||||
},
|
||||
}
|
||||
|
||||
return versionCmd
|
||||
}
|
||||
@@ -16,10 +16,12 @@ db:
|
||||
user: "root"
|
||||
password: ""
|
||||
charset: "utf8mb4"
|
||||
ssl: false
|
||||
log:
|
||||
enabled: true
|
||||
filename: "./data/artalk.log"
|
||||
cache:
|
||||
enabled: false
|
||||
type: "builtin"
|
||||
expires: 30
|
||||
warm_up: false
|
||||
@@ -34,7 +36,6 @@ ssl:
|
||||
enabled: false
|
||||
cert_path: ""
|
||||
key_path: ""
|
||||
admin_users:
|
||||
moderator:
|
||||
pending_default: false
|
||||
api_fail_block: false
|
||||
@@ -52,7 +53,8 @@ moderator:
|
||||
keywords:
|
||||
enabled: false
|
||||
pending: false
|
||||
files: []
|
||||
files:
|
||||
- "./data/keywords_1.txt"
|
||||
file_sep: "\n"
|
||||
replac_to: "x"
|
||||
captcha:
|
||||
@@ -73,11 +75,21 @@ captcha:
|
||||
geetest:
|
||||
captcha_id: ""
|
||||
captcha_key: ""
|
||||
img_upload:
|
||||
enabled: true
|
||||
path: "./data/artalk-img/"
|
||||
max_size: 5
|
||||
public_path: null
|
||||
upgit:
|
||||
enabled: false
|
||||
exec: "./upgit -c UPGIT_CONF_FILE_PATH -t /artalk-img"
|
||||
del_local: true
|
||||
email:
|
||||
enabled: false
|
||||
send_type: "smtp"
|
||||
send_name: "{{reply_nick}}"
|
||||
send_addr: "noreply@example.com"
|
||||
mail_subject: "[{{site_name}}] You got a reply from @{{reply_nick}}"
|
||||
mail_tpl: "default"
|
||||
smtp:
|
||||
host: "smtp.qq.com"
|
||||
@@ -88,15 +100,6 @@ email:
|
||||
access_key_id: ""
|
||||
access_key_secret: ""
|
||||
account_name: "noreply@example.com"
|
||||
img_upload:
|
||||
enabled: true
|
||||
path: "./data/artalk-img/"
|
||||
max_size: 5
|
||||
public_path: null
|
||||
upgit:
|
||||
enabled: false
|
||||
exec: "./upgit -c UPGIT_CONF_FILE_PATH -t /artalk-img"
|
||||
del_local: true
|
||||
admin_notify:
|
||||
notify_tpl: "default"
|
||||
noise_mode: false
|
||||
@@ -139,10 +142,10 @@ frontend:
|
||||
noComment: ""
|
||||
sendBtn: ""
|
||||
editorTravel: true
|
||||
emoticons: ""
|
||||
emoticons: "https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json"
|
||||
vote: true
|
||||
voteDown: false
|
||||
uaBadge: true
|
||||
uaBadge: false
|
||||
listSort: true
|
||||
pvEl: "#ArtalkPV"
|
||||
countEl: "#ArtalkCount"
|
||||
@@ -151,8 +154,8 @@ frontend:
|
||||
nestMax: 2
|
||||
nestSort: DATE_ASC
|
||||
gravatar:
|
||||
mirror: "https://www.gravatar.com/"
|
||||
default: "mp"
|
||||
mirror: "https://www.gravatar.com/avatar/"
|
||||
params: "d=mp&s=240"
|
||||
pagination:
|
||||
pageSize: 20
|
||||
readMore: true
|
||||
|
||||
@@ -45,6 +45,8 @@ db:
|
||||
password: ""
|
||||
# Database charset
|
||||
charset: "utf8mb4"
|
||||
# Enable SSL mode
|
||||
ssl: false
|
||||
|
||||
# Logging
|
||||
log:
|
||||
@@ -55,6 +57,8 @@ log:
|
||||
|
||||
# Cache
|
||||
cache:
|
||||
# Enable cache
|
||||
enabled: false
|
||||
# Cache type ["redis", "memcache", "builtin"]
|
||||
type: "builtin"
|
||||
# Cache expiration time (in minutes)
|
||||
@@ -280,7 +284,7 @@ frontend:
|
||||
# Dislike button
|
||||
voteDown: false
|
||||
# User UA badge
|
||||
uaBadge: true
|
||||
uaBadge: false
|
||||
# Comment sorting
|
||||
listSort: true
|
||||
# Page PV binding element
|
||||
@@ -297,8 +301,10 @@ frontend:
|
||||
nestSort: DATE_ASC
|
||||
# Gravatar
|
||||
gravatar:
|
||||
mirror: "https://www.gravatar.com/"
|
||||
default: "mp"
|
||||
# API URL
|
||||
mirror: "https://www.gravatar.com/avatar/"
|
||||
# API parameters
|
||||
params: "d=mp&s=240"
|
||||
# Comment pagination
|
||||
pagination:
|
||||
# Number of comments per page
|
||||
|
||||
@@ -42,6 +42,8 @@ db:
|
||||
charset: "utf8mb4"
|
||||
# 表前缀 (例如:"atk_")
|
||||
table_prefix: ""
|
||||
# 启用 SSL
|
||||
ssl: false
|
||||
|
||||
# 日志
|
||||
log:
|
||||
@@ -52,6 +54,8 @@ log:
|
||||
|
||||
# 缓存
|
||||
cache:
|
||||
# 启用缓存
|
||||
enabled: false
|
||||
# 缓存类型 ["redis", "memcache", "builtin"]
|
||||
type: "builtin"
|
||||
# 缓存过期时间 (单位:分钟)
|
||||
@@ -287,7 +291,7 @@ frontend:
|
||||
# 反对按钮
|
||||
voteDown: false
|
||||
# 用户 UA 徽标
|
||||
uaBadge: true
|
||||
uaBadge: false
|
||||
# 评论排序功能
|
||||
listSort: true
|
||||
# 页面 PV 绑定元素
|
||||
@@ -302,12 +306,12 @@ frontend:
|
||||
nestMax: 2
|
||||
# 嵌套评论排序规则 ["DATE_ASC", "DATE_DESC", "VOTE_UP_DESC"]
|
||||
nestSort: DATE_ASC
|
||||
# 头像
|
||||
# 头像 Gravatar
|
||||
gravatar:
|
||||
# Gravatar 镜像地址
|
||||
# API 地址
|
||||
mirror: "https://cravatar.cn/avatar/"
|
||||
# 默认头像
|
||||
default: "mp"
|
||||
# API 参数
|
||||
params: "d=mp&s=240"
|
||||
# 评论分页
|
||||
pagination:
|
||||
# 每页评论数
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
shamefully-hoist=true
|
||||
@@ -1,206 +0,0 @@
|
||||
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',
|
||||
|
||||
head: [
|
||||
['link', { rel: 'icon', href: '/favicon.png' }],
|
||||
['meta', { 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' }],
|
||||
// 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://npm.elemecdn.com/lightgallery@2.3.0/css/lightgallery.css', rel: 'stylesheet' }],
|
||||
['script', { src: 'https://npm.elemecdn.com/lightgallery@2.3.0/lightgallery.min.js' }],
|
||||
// katex
|
||||
// ['link', { href: "https://npm.elemecdn.com/katex@0.15.3/dist/katex.min.css", rel: 'stylesheet' }],
|
||||
// ['script', { src: 'https://npm.elemecdn.com/katex@0.15.3/dist/katex.min.js' }],
|
||||
// ['script', { src: 'https://npm.elemecdn.com/@artalkjs/plugin-katex/dist/artalk-plugin-katex.js' }],
|
||||
],
|
||||
|
||||
lastUpdated: true,
|
||||
|
||||
markdown: {
|
||||
// @link https://github.com/shikijs/shiki
|
||||
theme: {
|
||||
light: 'github-light',
|
||||
dark: 'github-dark',
|
||||
},
|
||||
config: (md) => {
|
||||
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')
|
||||
tokens[idx].attrSet('href', href.replace(/:ArtalkVersion:/g, Version.latest))
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
locales: {
|
||||
root: {
|
||||
label: '简体中文',
|
||||
lang: 'zh'
|
||||
},
|
||||
en: {
|
||||
label: 'English',
|
||||
lang: 'en',
|
||||
link: '/en/'
|
||||
}
|
||||
},
|
||||
|
||||
themeConfig: {
|
||||
sidebar: {
|
||||
"/guide/": [
|
||||
{
|
||||
text: "快速开始",
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: '项目介绍', link: '/guide/intro.md' },
|
||||
{ text: '程序部署', link: '/guide/deploy.md' },
|
||||
{ text: '数据迁移', link: '/guide/transfer.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
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: "进阶指南",
|
||||
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: '开发文档', link: '/develop/index.md', },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "配置文档",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: '后端配置', link: '/guide/backend/config.md' },
|
||||
{ text: '前端配置', link: '/guide/frontend/config.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: "部署说明",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Docker', link: '/guide/backend/docker.md' },
|
||||
{ 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: '更多内容',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: '安全防范', link: '/guide/security.md' },
|
||||
{ text: '扩展阅读', link: '/guide/extras.md' },
|
||||
{ text: '案例展示', link: '/guide/cases.md' },
|
||||
{ text: '关于我们', link: '/guide/about.md' },
|
||||
]
|
||||
}
|
||||
],
|
||||
"/develop/": [
|
||||
{
|
||||
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: '🔬 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' },
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
nav: [
|
||||
// NavbarItem
|
||||
{
|
||||
text: '介绍',
|
||||
link: '/guide/intro',
|
||||
},
|
||||
{
|
||||
text: '部署',
|
||||
link: '/guide/deploy',
|
||||
},
|
||||
{
|
||||
text: '配置',
|
||||
link: '/guide/backend/config',
|
||||
},
|
||||
{
|
||||
text: '迁移',
|
||||
link: '/guide/transfer',
|
||||
},
|
||||
{
|
||||
text: '案例',
|
||||
link: '/guide/cases',
|
||||
},
|
||||
{
|
||||
text: '开发',
|
||||
link: '/develop/',
|
||||
},
|
||||
// NavbarGroup
|
||||
{
|
||||
text: '传送',
|
||||
items: [
|
||||
{
|
||||
text: '代码仓库',
|
||||
link: 'https://github.com/ArtalkJS/Artalk',
|
||||
},
|
||||
{
|
||||
text: '文档镜像 (国内)',
|
||||
link: 'https://artalk-docs.qwqaq.com'
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/ArtalkJS/Artalk' }
|
||||
],
|
||||
|
||||
algolia: {
|
||||
appId: 'BH4D9OD16A',
|
||||
apiKey: '37ab96e3f5a774cbbf0571b035b42adb',
|
||||
indexName: 'artalk-js',
|
||||
searchParameters: {
|
||||
facetFilters: ['lang:zh-CN']
|
||||
}
|
||||
},
|
||||
|
||||
editLink: {
|
||||
pattern: 'https://github.com/ArtalkJS/Artalk/edit/master/docs/:path',
|
||||
text: '完善文档'
|
||||
},
|
||||
}
|
||||
})
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"latest": "2.4.4"
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
# Event
|
||||
|
||||
## 基本事件
|
||||
|
||||
|事件名|描述|
|
||||
|-|-|
|
||||
| `list-load` | 评论加载事件 |
|
||||
| `list-loaded` | 评论加载完成事件 |
|
||||
| `list-inserted` | 新增评论插入事件 |
|
||||
| `editor-submit` | 编辑器提交事件 |
|
||||
| `editor-submitted` | 编辑器提交完成事件 |
|
||||
| `user-changed` | 本地用户数据变更事件 |
|
||||
| `conf-loaded` | 配置变更事件 |
|
||||
| `sidebar-show` | 侧边栏显示事件 |
|
||||
| `sidebar-hide` | 侧边栏隐藏事件 |
|
||||
|
||||
## 添加事件监听
|
||||
|
||||
```js
|
||||
Artalk.use(ctx => {
|
||||
ctx.on('list-loaded', () => {
|
||||
alert('评论已加载完毕')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## 解除事件监听
|
||||
|
||||
```js
|
||||
let foo = function() { /* do something */ }
|
||||
|
||||
Artalk.use(ctx => {
|
||||
ctx.on('list-loaded', foo)
|
||||
ctx.off('list-loaded', foo)
|
||||
})
|
||||
```
|
||||
@@ -1,106 +0,0 @@
|
||||
# Frontend API
|
||||
|
||||
## 初始化 `Artalk.init`
|
||||
|
||||
创建 Artalk 实例化对象。
|
||||
|
||||
```js
|
||||
Artalk.init({
|
||||
el: '#Comments',
|
||||
pageKey: '/post/1',
|
||||
pageTitle: '关于引入 Artalk 的这档子事',
|
||||
server: 'http://your_domain:8080',
|
||||
site: 'Artalk 的博客',
|
||||
})
|
||||
```
|
||||
|
||||
## 更新配置 `Artalk.update`
|
||||
|
||||
修改 Artalk 当前配置。
|
||||
|
||||
```js
|
||||
Artalk.update({
|
||||
// 新的配置...
|
||||
})
|
||||
```
|
||||
|
||||
该函数调用后,`conf-loaded` 事件将被触发。
|
||||
|
||||
更新配置不会自动刷新评论列表,可按需继续执行 `Artalk.reload()` 函数。
|
||||
|
||||
注:前端的一些配置将会被后端的配置覆盖,详情见:[在后端控制前端](../guide/backend/fe-control.md)
|
||||
|
||||
## 重新加载 `Artalk.reload`
|
||||
|
||||
刷新 Artalk 评论列表。
|
||||
|
||||
```js
|
||||
Artalk.reload()
|
||||
```
|
||||
|
||||
列表加载前将触发 `list-load` 事件,加载完毕后将触发 `list-loaded` 事件。
|
||||
|
||||
## 释放资源 `Artalk.destroy`
|
||||
|
||||
销毁 Artalk 实例,用于资源释放。
|
||||
|
||||
```js
|
||||
Artalk.destroy()
|
||||
```
|
||||
|
||||
## 事件监听 `Artalk.on`
|
||||
|
||||
添加 Artalk 事件监听。
|
||||
|
||||
```js
|
||||
Artalk.on('list-loaded', () => {
|
||||
alert('评论列表加载完毕')
|
||||
})
|
||||
```
|
||||
|
||||
可监听事件类型见:[前端界面事件](./event.md)
|
||||
|
||||
## 解除监听 `Artalk.off`
|
||||
|
||||
解除 Artalk 事件监听。
|
||||
|
||||
```js
|
||||
const handler = () => {
|
||||
alert('评论列表加载完毕')
|
||||
}
|
||||
|
||||
Artalk.on('list-loaded', handler)
|
||||
Artalk.off('list-loaded', handler)
|
||||
```
|
||||
|
||||
## 触发事件 `Artalk.trigger`
|
||||
|
||||
触发 Artalk 事件。
|
||||
|
||||
```js
|
||||
Artalk.trigger('list-loaded')
|
||||
```
|
||||
|
||||
## 扩展插件 `Artalk.use`
|
||||
|
||||
该 API 用于扩展 Artalk。
|
||||
|
||||
```js
|
||||
Artalk.use((ctx) => {
|
||||
ctx.editor.setContent("Hello World")
|
||||
})
|
||||
```
|
||||
|
||||
详情见:[插件开发](./plugs.md)
|
||||
|
||||
## 夜间模式 `Artalk.setDarkMode`
|
||||
|
||||
修改夜间模式,可以配合博客主题调用,例如当用户点击夜间模式切换按钮。
|
||||
|
||||
```js
|
||||
Artalk.setDarkMode(true)
|
||||
```
|
||||
|
||||
## 浏览量组件 `Artalk.loadCountWidget`
|
||||
|
||||
详情见:[浏览量统计](../guide/frontend/pv.md)
|
||||
@@ -1,17 +0,0 @@
|
||||
# 插件开发
|
||||
|
||||
你可以使用 `Artalk.use` 来扩展 Artalk。
|
||||
|
||||
```js
|
||||
Artalk.use((ctx) => {
|
||||
ctx.editor.setContent("Hello World")
|
||||
})
|
||||
```
|
||||
|
||||
## Context
|
||||
|
||||
::: warning
|
||||
Context API 目前仍不稳定,开发可能会有变动,升级请关注 CHANGELOG。
|
||||
:::
|
||||
|
||||
参考:[@artalk/types/context.d.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/types/context.d.ts)
|
||||
@@ -0,0 +1,2 @@
|
||||
.vitepress/dist/**
|
||||
.vitepress/cache/**
|
||||
@@ -0,0 +1,253 @@
|
||||
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",
|
||||
|
||||
head: [
|
||||
["link", { rel: "icon", href: "/favicon.png" }],
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
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",
|
||||
},
|
||||
],
|
||||
// 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://npm.elemecdn.com/lightgallery@2.3.0/css/lightgallery.css",
|
||||
rel: "stylesheet",
|
||||
},
|
||||
],
|
||||
[
|
||||
"script",
|
||||
{
|
||||
src: "https://npm.elemecdn.com/lightgallery@2.3.0/lightgallery.min.js",
|
||||
},
|
||||
],
|
||||
// katex
|
||||
// ['link', { href: "https://npm.elemecdn.com/katex@0.15.3/dist/katex.min.css", rel: 'stylesheet' }],
|
||||
// ['script', { src: 'https://npm.elemecdn.com/katex@0.15.3/dist/katex.min.js' }],
|
||||
// ['script', { src: 'https://npm.elemecdn.com/@artalkjs/plugin-katex/dist/artalk-plugin-katex.js' }],
|
||||
],
|
||||
|
||||
lastUpdated: true,
|
||||
|
||||
markdown: {
|
||||
// @link https://github.com/shikijs/shiki
|
||||
theme: {
|
||||
light: "github-light",
|
||||
dark: "github-dark",
|
||||
},
|
||||
config: (md) => {
|
||||
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");
|
||||
tokens[idx].attrSet(
|
||||
"href",
|
||||
href.replace(/:ArtalkVersion:/g, Version.latest)
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
locales: {
|
||||
root: {
|
||||
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",
|
||||
},
|
||||
},
|
||||
|
||||
themeConfig: {
|
||||
sidebar: {
|
||||
"/guide/": [
|
||||
{
|
||||
text: "快速开始",
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: "项目介绍", link: "/guide/intro.md" },
|
||||
{ text: "程序部署", link: "/guide/deploy.md" },
|
||||
{ text: "数据迁移", link: "/guide/transfer.md" },
|
||||
],
|
||||
},
|
||||
{
|
||||
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: "进阶指南",
|
||||
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: "配置文档",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "后端配置", link: "/guide/backend/config.md" },
|
||||
{ text: "前端配置", link: "/guide/frontend/config.md" },
|
||||
],
|
||||
},
|
||||
{
|
||||
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: "更多内容",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: "安全防范", link: "/guide/security.md" },
|
||||
{ text: "扩展阅读", link: "/guide/extras.md" },
|
||||
{ text: "案例展示", link: "/guide/cases.md" },
|
||||
{ text: "关于我们", link: "/guide/about.md" },
|
||||
],
|
||||
},
|
||||
],
|
||||
"/develop/": [
|
||||
{
|
||||
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: "🔬 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",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
nav: [
|
||||
// NavbarItem
|
||||
{
|
||||
text: "介绍",
|
||||
link: "/guide/intro",
|
||||
},
|
||||
{
|
||||
text: "部署",
|
||||
link: "/guide/deploy",
|
||||
},
|
||||
{
|
||||
text: "配置",
|
||||
link: "/guide/backend/config",
|
||||
},
|
||||
{
|
||||
text: "迁移",
|
||||
link: "/guide/transfer",
|
||||
},
|
||||
{
|
||||
text: "案例",
|
||||
link: "/guide/cases",
|
||||
},
|
||||
{
|
||||
text: "开发",
|
||||
link: "/develop/",
|
||||
},
|
||||
// NavbarGroup
|
||||
{
|
||||
text: "传送",
|
||||
items: [
|
||||
{
|
||||
text: "代码仓库",
|
||||
link: "https://github.com/ArtalkJS/Artalk",
|
||||
},
|
||||
{
|
||||
text: "文档镜像 (国内)",
|
||||
link: "https://artalk-docs.qwqaq.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
socialLinks: [
|
||||
{ icon: "github", link: "https://github.com/ArtalkJS/Artalk" },
|
||||
],
|
||||
|
||||
search: {
|
||||
provider: "algolia",
|
||||
options: {
|
||||
appId: "2WNJ32WVTY",
|
||||
apiKey: "6c6ebc345a87b738264f19095b78c91c",
|
||||
indexName: "artalk-js",
|
||||
searchParameters: {
|
||||
facetFilters: ["lang:zh-CN"],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
editLink: {
|
||||
pattern: "https://github.com/ArtalkJS/Artalk/edit/master/docs/:path",
|
||||
text: "完善文档",
|
||||
},
|
||||
},
|
||||
|
||||
vite: {
|
||||
server: {
|
||||
open: "/guide/intro.html",
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,53 +1,64 @@
|
||||
<template>
|
||||
<div ref="artalkEl" style="margin-top: 20px;"></div>
|
||||
<div ref="el" style="margin-top: 20px;"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { watch, nextTick, ref, onMounted } from 'vue'
|
||||
import { watch, nextTick, ref, onMounted, onUnmounted } from 'vue'
|
||||
import { useData, useRouter } from 'vitepress'
|
||||
import type Artalk from 'artalk'
|
||||
|
||||
const artalkEl = ref<HTMLElement | null>(null)
|
||||
const el = ref<HTMLElement | null>(null)
|
||||
|
||||
const router = useRouter()
|
||||
const page = useData().page
|
||||
|
||||
onMounted(() => {
|
||||
const script = document.createElement('script')
|
||||
script.src = `https://artalk.qwqaq.com/dist/Artalk.js`
|
||||
document.getElementsByTagName('head')[0].appendChild(script)
|
||||
script.onload = () => {
|
||||
initArtalk(page.value)
|
||||
}
|
||||
})
|
||||
let artalk: Artalk
|
||||
|
||||
watch(() => router.route.data.relativePath, (path) => {
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
Artalk.update(getArtalkConfByPage(page.value))
|
||||
Artalk.reload()
|
||||
initArtalk(getConfByPage())
|
||||
})
|
||||
})
|
||||
|
||||
function getArtalkConfByPage(page: any) {
|
||||
watch(() => router.route.path, () => {
|
||||
nextTick(() => {
|
||||
artalk.update(getConfByPage())
|
||||
artalk.reload()
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
artalk.destroy()
|
||||
})
|
||||
|
||||
function initArtalk(conf: any) {
|
||||
// TODO: remove dynamic import after the new version released
|
||||
import('artalk').then(({ default: Artalk }) => {
|
||||
artalk = Artalk.init({
|
||||
el: el.value,
|
||||
emoticons: '/assets/emoticons/default.json',
|
||||
gravatar: {
|
||||
mirror: 'https://cravatar.cn/avatar/'
|
||||
},
|
||||
...conf
|
||||
})
|
||||
}).then(() => {
|
||||
loadExtraFuncs()
|
||||
})
|
||||
}
|
||||
|
||||
function getConfByPage() {
|
||||
return {
|
||||
pageKey: 'https://artalk.js.org'+location.pathname,
|
||||
pageTitle: page.title,
|
||||
pageKey: 'https://artalk.js.org'+router.route.path,
|
||||
pageTitle: page.value.title,
|
||||
server: 'https://artalk.qwqaq.com',
|
||||
site: 'ArtalkDocs',
|
||||
}
|
||||
}
|
||||
|
||||
function initArtalk(page: any) {
|
||||
Artalk.init({
|
||||
el: artalkEl.value,
|
||||
emoticons: '/assets/emoticons/default.json',
|
||||
gravatar: {
|
||||
mirror: 'https://cravatar.cn/avatar/'
|
||||
},
|
||||
...getArtalkConfByPage(page)
|
||||
})
|
||||
|
||||
function loadExtraFuncs() {
|
||||
// 图片灯箱插件
|
||||
Artalk.on('list-loaded', () => {
|
||||
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) => {
|
||||
@@ -66,7 +77,7 @@ function initArtalk(page: any) {
|
||||
|
||||
// 夜间模式
|
||||
const darkMode = document.querySelector('html').classList.contains('dark')
|
||||
Artalk.setDarkMode(darkMode)
|
||||
artalk.setDarkMode(darkMode)
|
||||
|
||||
new MutationObserver((mList) => {
|
||||
mList.forEach((m) => {
|
||||
@@ -74,7 +85,7 @@ function initArtalk(page: any) {
|
||||
|
||||
// @ts-ignore
|
||||
const darkMode = m.target.classList.contains('dark')
|
||||
Artalk.setDarkMode(darkMode)
|
||||
artalk.setDarkMode(darkMode)
|
||||
})
|
||||
}).observe(document.querySelector('html'), { attributes: true })
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,8 @@
|
||||
## Artalk Documentation
|
||||
# Artalk Documentation
|
||||
|
||||
> The Documentation of Artalk
|
||||
[](https://app.netlify.com/sites/artalk/deploys)
|
||||
|
||||
Documentation of Artalk
|
||||
|
||||
## Build
|
||||
|
||||
@@ -11,9 +13,8 @@ pnpm docs:build
|
||||
|
||||
## Deploy
|
||||
|
||||
[](https://app.netlify.com/sites/artalk/deploys)
|
||||
|
||||
文档通过 [Netlify](https://www.netlify.com/) 对 master 分支进行自动部署。
|
||||
|
||||
## Licensed
|
||||
|
||||
CC BY-NC-SA 4.0
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"latest": "2.7.1"
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,50 @@
|
||||
# Event
|
||||
|
||||
## 基本事件
|
||||
|
||||
|事件名|描述|
|
||||
|-|-|
|
||||
| `inited` | 初始化后 |
|
||||
| `destroy` | 实例销毁时 |
|
||||
| `list-fetch` | 评论列表请求时 |
|
||||
| `list-fetched` | 评论列表请求后 |
|
||||
| `list-load` | 评论装载前 |
|
||||
| `list-loaded` | 评论装载后 |
|
||||
| `list-error` | 评论加载错误时 |
|
||||
| `list-goto-first` | 评论列表归位时 |
|
||||
| `list-reach-bottom` | 评论列表滚动到底部时 |
|
||||
| `list-reach-bottom` | 评论列表滚动到底部时 |
|
||||
| `comment-inserted` | 评论插入后 |
|
||||
| `comment-updated` | 评论更新后 |
|
||||
| `comment-deleted` | 评论删除后 |
|
||||
| `comment-rendered` | 评论节点渲染后 |
|
||||
| `unreads-updated` | 未读消息变更时 |
|
||||
| `list-goto` | 评论跳转时 |
|
||||
| `page-loaded` | 页面数据更新后 |
|
||||
| `editor-submit` | 编辑器提交时 |
|
||||
| `editor-submitted` | 编辑器提交后 |
|
||||
| `user-changed` | 本地用户数据变更时 |
|
||||
| `conf-loaded` | 配置变更时 |
|
||||
| `dark-mode-changed` | 深色模式变更时 |
|
||||
| `sidebar-show` | 侧边栏显示 |
|
||||
| `sidebar-hide` | 侧边栏隐藏 |
|
||||
|
||||
|
||||
事件声明代码:[@ArtalkJS/Artalk - types/event.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/types/event.ts)
|
||||
|
||||
## 添加事件监听
|
||||
|
||||
```js
|
||||
artalk.on('list-loaded', () => {
|
||||
alert('评论已加载完毕')
|
||||
})
|
||||
```
|
||||
|
||||
## 解除事件监听
|
||||
|
||||
```js
|
||||
let foo = function() { /* do something */ }
|
||||
|
||||
artalk.on('list-loaded', foo)
|
||||
artalk.off('list-loaded', foo)
|
||||
```
|
||||
@@ -0,0 +1,159 @@
|
||||
# Frontend API
|
||||
|
||||
## 安装依赖
|
||||
|
||||
用你喜欢的包管理器安装 Artalk:
|
||||
|
||||
```bash
|
||||
pnpm add artalk
|
||||
# 或者使用 npm
|
||||
npm install artalk
|
||||
```
|
||||
|
||||
## 创建实例 `init`
|
||||
|
||||
调用该函数将创建并得到一个 Artalk 的实例化对象,可用于后续操作。
|
||||
|
||||
```js
|
||||
import Artalk from 'artalk'
|
||||
|
||||
const artalk = Artalk.init({
|
||||
el: '#Comments',
|
||||
pageKey: '/post/1',
|
||||
pageTitle: '关于引入 Artalk 的这档子事',
|
||||
server: 'http://your_domain:8080',
|
||||
site: 'Artalk 的博客',
|
||||
})
|
||||
```
|
||||
|
||||
调用该函数会向后端发起请求:
|
||||
|
||||
1. 获取前端配置
|
||||
2. 获取评论列表
|
||||
|
||||
配置和评论加载完毕后会分别触发 `conf-loaded` 和 `list-loaded` 事件。
|
||||
|
||||
注:前端配置可能会被覆盖,详情见:[在后端控制前端](../guide/backend/fe-control.md)。
|
||||
|
||||
## 释放资源 `destroy`
|
||||
|
||||
销毁 Artalk 实例,用于资源释放。
|
||||
|
||||
```js
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
artalk.destroy()
|
||||
```
|
||||
|
||||
释放资源将执行 Artalk 挂载的 DOM 节点删除,以及解除 Artalk 事件监听等操作。
|
||||
|
||||
在 Vue / React 等框架中,务必在组件销毁时调用该函数,否则会造成内存泄漏:
|
||||
|
||||
```ts
|
||||
import { onUnmounted } from 'vue'
|
||||
|
||||
onUnmounted(() => {
|
||||
artalk.destroy()
|
||||
})
|
||||
```
|
||||
|
||||
## 更新配置 `update`
|
||||
|
||||
修改 Artalk 当前配置。
|
||||
|
||||
```js
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
artalk.update({
|
||||
// 新的配置...
|
||||
})
|
||||
```
|
||||
|
||||
调用该函数将触发 `conf-loaded` 事件。
|
||||
|
||||
更新配置不会自动刷新评论列表,可按需继续执行 `artalk.reload()` 函数。
|
||||
|
||||
请注意,该函数是一个实例化对象中的方法,并非全局函数。
|
||||
|
||||
前端配置参考:[前端配置](../guide/frontend/config.md)
|
||||
|
||||
## 重新加载 `reload`
|
||||
|
||||
重新从后端加载 Artalk 评论列表数据。
|
||||
|
||||
```js
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
artalk.reload()
|
||||
```
|
||||
|
||||
列表加载前将触发 `list-load` 事件,加载完毕后将触发 `list-loaded` 事件。
|
||||
|
||||
## 监听事件 `on`
|
||||
|
||||
添加 Artalk 事件监听。
|
||||
|
||||
```js
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
artalk.on('list-loaded', () => {
|
||||
alert('评论列表加载完毕')
|
||||
})
|
||||
```
|
||||
|
||||
可参考:[前端 Event](./event.md)。
|
||||
|
||||
## 解除监听 `off`
|
||||
|
||||
解除 Artalk 事件监听。
|
||||
|
||||
```js
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
const handler = () => {
|
||||
alert('评论列表加载完毕')
|
||||
}
|
||||
|
||||
artalk.on('list-loaded', handler)
|
||||
artalk.off('list-loaded', handler)
|
||||
```
|
||||
|
||||
## 触发事件 `trigger`
|
||||
|
||||
触发 Artalk 事件。
|
||||
|
||||
```js
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
artalk.trigger('list-loaded')
|
||||
```
|
||||
|
||||
## 加载插件 `use`
|
||||
|
||||
通过 `Artalk.use` 函数加载插件。请注意,该函数是一个全局函数,并非实例化对象中的方法。通过该函数加载的插件将对所有 Artalk 实例生效。
|
||||
|
||||
```js
|
||||
import Artalk from 'artalk'
|
||||
|
||||
Artalk.use((ctx) => {
|
||||
ctx.editor.setContent("Hello World")
|
||||
})
|
||||
|
||||
const artalk = Artalk.init({ ... })
|
||||
```
|
||||
|
||||
详情见:[插件开发](./plugs.md)
|
||||
|
||||
## 夜间模式 `setDarkMode`
|
||||
|
||||
修改夜间模式,可以配合博客主题调用,例如当用户点击夜间模式切换按钮。
|
||||
|
||||
```js
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
artalk.setDarkMode(true)
|
||||
```
|
||||
|
||||
## 浏览量组件 `loadCountWidget`
|
||||
|
||||
详情见:[浏览量统计](../guide/frontend/pv.md)
|
||||
@@ -23,6 +23,6 @@
|
||||
* [@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/packages/artalk/src/artalk.ts)
|
||||
* [@ArtalkJS/Artalk - types/event.d.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/types/event.d.ts)
|
||||
* [@ArtalkJS/Artalk - types/event.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/types/event.ts)
|
||||
|
||||
通过 Artalk 提供的 `API` 和 `Event`,你可以实现很多高级功能,比如编写评论管理机器人、评论提醒推送插件等。Artalk 并不为此提供技术指导,但鼓励你参考此处的文档自行定制。
|
||||
@@ -0,0 +1,64 @@
|
||||
# 插件开发
|
||||
|
||||
使用 `Artalk.use` 来扩展 Artalk。
|
||||
|
||||
```js
|
||||
import Artalk from 'artalk'
|
||||
|
||||
Artalk.use((ctx) => {
|
||||
ctx.on('inited', () => {
|
||||
ctx.get('editor').setContent("Hello World")
|
||||
})
|
||||
|
||||
ctx.on('list-loaded', () => {
|
||||
console.log('评论列表加载完毕')
|
||||
})
|
||||
})
|
||||
|
||||
const artalk = Artalk.init({ ... })
|
||||
```
|
||||
|
||||
请注意:
|
||||
|
||||
- `Artalk.use` 必须在 `Artalk.init` 之前调用。
|
||||
- 请勿依赖插件的加载顺序,请监听事件来执行插件逻辑。
|
||||
- 当所有的插件加载完毕后,会触发 `inited` 事件。
|
||||
|
||||
在 use 函数中,你可以通过 `ctx` 来访问 Artalk 的上下文。
|
||||
|
||||
## Context
|
||||
|
||||
Context 对象包含了 Artalk 的上下文信息。
|
||||
|
||||
| 成员 | 说明 |
|
||||
| --- | --- |
|
||||
| `ctx.$root` | Artalk 容器元素 |
|
||||
| `ctx.conf` | Artalk 配置 |
|
||||
| `ctx.fetch` | 加载数据数据 |
|
||||
| `ctx.reload` | 重载评论列表 |
|
||||
| `ctx.on` | 添加事件监听 |
|
||||
| `ctx.off` | 解除事件监听 |
|
||||
| `ctx.trigger` | 触发事件 |
|
||||
| `ctx.inject` | 依赖注入 |
|
||||
| `ctx.get` | 获取依赖 |
|
||||
|
||||
::: warning
|
||||
Context API 目前仍不稳定,开发可能会有变动,升级请关注 CHANGELOG。
|
||||
:::
|
||||
|
||||
参考:[@artalk/types/context.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/types/context.ts)
|
||||
|
||||
Artalk 拥有完整的 TypeScript 类型定义,你可以通过编辑器的自动补全来查看 API。
|
||||
|
||||
## 示例插件
|
||||
|
||||
Artalk 有很多内置的插件,你可以参考它们的源码来开发自己的插件。
|
||||
|
||||
[@ArtalkJS/Artalk - src/plugins](https://github.com/ArtalkJS/Artalk/tree/master/ui/packages/artalk/src/plugins)
|
||||
|
||||
我们还提供了一些外置的插件,同样可以参考:
|
||||
|
||||
| 插件 | 说明 |
|
||||
| --- | --- |
|
||||
| [@artalk/plugin-katex](https://github.com/ArtalkJS/Artalk/tree/master/ui/packages/plugin-katex) | LaTeX 公式插件 |
|
||||
| [@artalk/plugin-lightbox](https://github.com/ArtalkJS/Artalk/tree/master/ui/packages/plugin-lightbox) | 图片灯箱插件 |
|
||||
@@ -2,11 +2,11 @@
|
||||
layout: home
|
||||
|
||||
title: Artalk
|
||||
titleTemplate: The Selfhosted Comment System
|
||||
titleTemplate: A Self-hosted Comment System
|
||||
|
||||
hero:
|
||||
name: Artalk
|
||||
text: The Selfhosted Comment System
|
||||
text: A Self-hosted Comment System
|
||||
tagline: Elevate your online conversations with a comment system that embodies the trifecta of lightness, security, and refinement.
|
||||
actions:
|
||||
- theme: brand
|
||||
@@ -30,4 +30,3 @@ features:
|
||||
title: Flexible
|
||||
details: Use Golang to interpret the excellence of multiple platforms
|
||||
---
|
||||
|
||||
File renamed without changes.
@@ -113,7 +113,7 @@ admin_notify:
|
||||
|
||||

|
||||
|
||||
详情可参考:[“Bots: An introduction for developers - Telegram”](https://core.telegram.org/bots)
|
||||
详情可参考:[Bots: An introduction for developers - Telegram](https://core.telegram.org/bots)
|
||||
|
||||
::: tip
|
||||
|
||||
@@ -151,7 +151,7 @@ admin_notify:
|
||||
|
||||
<img src="/images/notify/lark-3.png" width="400px">
|
||||
|
||||
可参考:[“飞书帮助中心文档”](https://www.feishu.cn/hc/zh-CN/articles/360024984973)
|
||||
可参考:[飞书帮助中心文档](https://www.feishu.cn/hc/zh-CN/articles/360024984973)
|
||||
|
||||
## 钉钉
|
||||
|
||||
@@ -164,7 +164,7 @@ admin_notify:
|
||||
secret: ""
|
||||
```
|
||||
|
||||
可参考:[“钉钉开放文档”](https://open.dingtalk.com/document/robots/custom-robot-access)
|
||||
可参考:[钉钉开放文档](https://open.dingtalk.com/document/robots/custom-robot-access)
|
||||
|
||||
## Bark
|
||||
|
||||
@@ -227,7 +227,7 @@ admin_notify:
|
||||
{{link_to_reply}}
|
||||
```
|
||||
|
||||
可用变量和邮件模板相同,可参考:[“邮件模版”](./email.md#邮件模板)
|
||||
可用变量和邮件模板相同,可参考:[邮件模版](./email.md#邮件模板)
|
||||
|
||||
## 嘈杂模式 `noise_mode`
|
||||
|
||||
@@ -264,7 +264,7 @@ admin_notify:
|
||||
|`notify_subject`|通知标题 |String| 对应 admin_notify.notify_subject 配置项 |
|
||||
|`notify_body` |通知内容 |String| 根据 admin_notify.notify_tpl 模版渲染 |
|
||||
|`comment` |评论内容 |Object| 新创建的评论数据对象 |
|
||||
|`parent_comment`|评论回复的目标|Object| Root 根节点评论类型改项为 null |
|
||||
|`parent_comment`|评论回复的目标|Object| 如果是根节点评论值为 null |
|
||||
|
||||
**Body 数据样本**
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -12,6 +12,25 @@ 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)
|
||||
@@ -46,7 +65,7 @@ app_key: "<任意的字符>"
|
||||
locale: "zh-CN"
|
||||
```
|
||||
|
||||
详情参考:[“多语言”](../frontend/i18n.md)
|
||||
详情参考:[多语言](../frontend/i18n.md)
|
||||
|
||||
## 数据库 `db`
|
||||
|
||||
@@ -76,17 +95,30 @@ db:
|
||||
password: "" # 密码
|
||||
charset: "utf8mb4" # 编码格式
|
||||
table_prefix: "" # 表前缀 (例如:"atk_")
|
||||
ssl: false # 启用 SSL
|
||||
```
|
||||
|
||||
数据表将在 Artalk 启动时自动完成创建,无需额外操作。
|
||||
|
||||
#### 数据库连接字符串 (DSN)
|
||||
|
||||
如有需要,你还可以手动配置 `db.dsn` 来指定数据库连接字符串,例如:
|
||||
|
||||
```yaml
|
||||
db:
|
||||
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)
|
||||
|
||||
## 管理员 `admin_users`
|
||||
|
||||
你需要配置管理员账户,这样才能通过「[控制中心](../frontend/sidebar.md)」对站点内容进行管理。
|
||||
|
||||
Artalk 支持多站点,你可以创建多个管理员账户,为其分配站点,让你的朋友们共用同一个后端程序。
|
||||
|
||||
详情参考:[“管理员 × 多站点”](/guide/backend/multi-site.md)
|
||||
详情参考:[管理员 × 多站点](/guide/backend/multi-site.md)
|
||||
|
||||
## 可信域名 `trusted_domains`
|
||||
|
||||
@@ -146,38 +178,39 @@ Artalk.init({ site: "Artalk 官网" })
|
||||
|
||||
## 前端配置 `frontend`
|
||||
|
||||
增加 `frontend` 字段内容可以在后端控制前端的配置,详情可参考:[“在后端控制前端”](/guide/backend/fe-control)。
|
||||
增加 `frontend` 字段内容可以在后端控制前端的配置,详情可参考:[在后端控制前端](/guide/backend/fe-control)。
|
||||
|
||||
## 邮件通知 `email`
|
||||
|
||||
配置邮件通知,让回复通过邮件的形式通知目标用户,你可以自定义邮件发送者名称、标题、模版等。
|
||||
|
||||
详情参考:[“后端 · 邮件通知”](/guide/backend/email.md)
|
||||
详情参考:[后端 · 邮件通知](/guide/backend/email.md)
|
||||
|
||||
## 多元推送 `admin_notify`
|
||||
|
||||
你可以配置多种消息发送方式,例如飞书、Telegram 等,当收到新的评论时通知管理员。
|
||||
|
||||
详情参考:[“后端 · 多元推送”](/guide/backend/admin_notify.md)
|
||||
详情参考:[后端 · 多元推送](/guide/backend/admin_notify.md)
|
||||
|
||||
## 评论审核 `moderator`
|
||||
|
||||
配置评论审核来自动拦截垃圾评论。
|
||||
|
||||
详情参考:[“后端 · 评论审核”](/guide/backend/moderator.md)
|
||||
详情参考:[后端 · 评论审核](/guide/backend/moderator.md)
|
||||
|
||||
## 验证码 `captcha`
|
||||
|
||||
支持图片、滑动验证码,通过验证码对请求频率进行限制。
|
||||
|
||||
详情参考:[“后端 · 验证码”](/guide/backend/captcha.md)
|
||||
详情参考:[后端 · 验证码](/guide/backend/captcha.md)
|
||||
|
||||
## 缓存配置 `cache`
|
||||
## 高速缓存 `cache`
|
||||
|
||||
为了提高评论系统的响应速度和性能,Artalk 内置一套缓存机制,并且默认开启,无需额外配置。但如果有需要,你也可以连接外部缓存服务器,支持 Redis 和 Memcache。
|
||||
为节省内存资源占用,缓存默认关闭。如果你对网站性能有较高要求,请手动开启。你还可以连接外部缓存服务器,支持 Redis 和 Memcache。
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
enabled: true # 启用缓存 (默认关闭)
|
||||
type: "builtin" # 支持 redis, memcache, builtin (自带缓存)
|
||||
expires: 30 # 缓存过期时间 (单位:分钟)
|
||||
warm_up: false # 程序启动时预热缓存
|
||||
@@ -185,9 +218,7 @@ cache:
|
||||
```
|
||||
|
||||
- **warm_up**:缓存预热功能。设置为 `true`,在 Artalk 启动时会立刻对数据库内容进行全面缓存,如果你的评论数据较多,多达上万条,启动时间可能会延长。
|
||||
- **type**:缓存类型。可选:`redis`, `memcache`, `builtin`。
|
||||
|
||||
type 默认为 `builtin`,如遇特殊情况可将缓存关闭,将其设置为 `disabled`。
|
||||
- **type**:缓存类型,默认为 `builtin`。可选:`redis`, `memcache`, `builtin`。
|
||||
|
||||
注:如果在 Artalk 程序外部修改数据库内容,需要刷新 Artalk 缓存才能更新。
|
||||
|
||||
@@ -206,9 +237,8 @@ cache:
|
||||
db: 0 # 使用零号数据库
|
||||
```
|
||||
|
||||
技术细节:[Artalk 缓存机制 时序图.png](/images/artalk/artalk-cache.png)
|
||||
|
||||

|
||||
<!-- 技术细节:[Artalk 缓存机制 时序图.png](/images/artalk/artalk-cache.png) -->
|
||||
<!--  -->
|
||||
|
||||
## 监听地址 `host`
|
||||
|
||||
@@ -318,5 +348,5 @@ test_file: "./data/artalk.log"
|
||||
|
||||
配置文件相关代码:[/internal/config/config.go](https://github.com/ArtalkJS/Artalk/blob/master/internal/config/config.go)
|
||||
|
||||
前往:[“前端配置”](/guide/frontend/config.md)
|
||||
前往:[前端配置](/guide/frontend/config.md)
|
||||
:::
|
||||
@@ -0,0 +1,144 @@
|
||||
# 守护进程
|
||||
|
||||
## Systemd
|
||||
|
||||
前提条件:
|
||||
|
||||
- Artalk 二进制文件,可在 [GitHub Release](https://github.com/ArtalkJS/Artalk/releases) 下载
|
||||
- `systemctl --version` 232 或更新的版本
|
||||
- `sudo` 管理员权限
|
||||
|
||||
移动 Artalk 到 `$PATH`,例如:
|
||||
|
||||
```bash
|
||||
sudo mv artalk /usr/bin/
|
||||
```
|
||||
|
||||
测试是否有效:
|
||||
|
||||
```bash
|
||||
artalk version
|
||||
```
|
||||
|
||||
创建名为 artalk 的用户组:
|
||||
|
||||
```bash
|
||||
sudo groupadd --system artalk
|
||||
```
|
||||
|
||||
创建一个名为 artalk 的用户,并且拥有一个可写的 home 目录:
|
||||
|
||||
```bash
|
||||
sudo useradd --system \
|
||||
--gid artalk \
|
||||
--create-home \
|
||||
--home-dir /var/lib/artalk \
|
||||
--shell /usr/sbin/nologin \
|
||||
--comment "Artalk server" \
|
||||
artalk
|
||||
```
|
||||
|
||||
如果你有 Artalk 的配置文件,请确保刚刚创建的 artalk 用户有权限可以读取。
|
||||
|
||||
创建服务文件:
|
||||
|
||||
```bash
|
||||
sudo vim /etc/systemd/system/artalk.service
|
||||
```
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Artalk
|
||||
Documentation=https://artalk.js.org
|
||||
After=network.target network-online.target
|
||||
Requires=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
User=artalk
|
||||
Group=artalk
|
||||
ExecStart=/usr/bin/artalk server -w /var/lib/artalk -c /etc/artalk/artalk.yml
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
ExecStop=/bin/kill -s QUIT $MAINPID
|
||||
TimeoutStopSec=5s
|
||||
LimitNOFILE=1048576
|
||||
LimitNPROC=512
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
请仔细检查 `ExecStart` 和 `ExecReload`。 确保二进制文件的位置和程序启动参数是正确的
|
||||
|
||||
例如:更改 `-c` 参数的路径来指定配置文件,`-w` 参数可以更改工作目录。
|
||||
|
||||
请注意配置文件中的所有相对路径都是基于工作目录,例如配置文件中的 `./data/` 文件夹,如果启动参数 `-w /var/lib/artalk`,将读取 `/var/lib/artalk/data/` 目录。请确保该目录中的文件对于创建的 `artalk` 账户有权限可读写。
|
||||
|
||||
保存服务文件后,你可以设置自动启动服务:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now artalk
|
||||
```
|
||||
|
||||
验证服务是否正常运行:
|
||||
|
||||
```bash
|
||||
systemctl status artalk
|
||||
```
|
||||
|
||||
一些常用的命令:
|
||||
|
||||
- 启动服务:`systemctl start artalk`
|
||||
- 停止服务:`systemctl stop artalk`
|
||||
- 查看状态:`systemctl status artalk`
|
||||
- 查看日志:`journalctl -u artalk --no-pager | less +G`
|
||||
|
||||
## Tmux
|
||||
|
||||
tmux 将创建一个持续的命令行会话,在 SSH 或 tty 断开后保持在后台。
|
||||
|
||||
Note: 服务器关闭或重启后,tmux 会话将被清除,需要手动重新运行程序。
|
||||
|
||||
1. 创建会话 `tmux new -s artalk`
|
||||
2. 运行程序 `./artalk server`
|
||||
|
||||
恢复接入会话:`tmux attach -t artalk`
|
||||
|
||||
查看所有会话:`tmux ls`
|
||||
|
||||
## Supervisor
|
||||
|
||||
以宝塔面板举例:打开「软件商店」,搜索并安装「Supervisor管理器」:
|
||||
|
||||

|
||||
|
||||
安装后,打开插件,点击「添加守护程序」:
|
||||
|
||||

|
||||
|
||||
> - 启动用户:`root` 或其他
|
||||
> - 运行目录:点击右侧图标,选择 Artalk 所在目录
|
||||
> - 启动命令:`./artalk server`
|
||||
|
||||
## Docker
|
||||
|
||||
更新 Docker 容器的 [Restart 策略](https://docs.docker.com/config/containers/start-containers-automatically/#use-a-restart-policy) 以达到进程守护效果。
|
||||
|
||||
```bash
|
||||
docker update --restart=unless-stopped artalk
|
||||
```
|
||||
|
||||
## Docker Compose
|
||||
|
||||
在 `docker-compose.yml` 文件给服务添加 `restart: unless-stopped` 策略:
|
||||
|
||||
```diff
|
||||
version: '3'
|
||||
services:
|
||||
artalk:
|
||||
+ restart: unless-stopped
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
# 数据
|
||||
|
||||
## 备份
|
||||
|
||||
前往:[数据迁移 · 备份](/guide/transfer.md)
|
||||
@@ -12,11 +12,11 @@ Artalk 提供后端程序的 Docker 镜像,以便加速部署流程,提供
|
||||
|
||||
:::tip
|
||||
|
||||
推荐使用 Docker Compose:[“后端部署”](/guide/backend/install) 页面已详细讲解。
|
||||
推荐使用 Docker Compose,可参考 [程序部署](/guide/deploy) 页面的步骤。
|
||||
|
||||
:::
|
||||
|
||||
常规的 Docker 容器创建可参考:
|
||||
Docker 容器创建:
|
||||
|
||||
```bash
|
||||
# 为 Artalk 创建一个目录
|
||||
@@ -112,4 +112,4 @@ docker exec -it artalk bash
|
||||
|
||||
## 多平台兼容性
|
||||
|
||||
Docker 镜像暂仅提供 amd_64 构建,若需要在 ARM 架构运行,请下载 [二进制编译构建](/guide/backend/install.md#普通方式)
|
||||
Docker 镜像暂仅提供 x86、arm64 的镜像构建,如需更多平台架构版本,请下载 [二进制构建部署](/guide/deploy.md#普通方式部署)。
|
||||
@@ -310,7 +310,7 @@ email:
|
||||
</div>
|
||||
```
|
||||
|
||||
Artalk 内置许多预设的邮件模板,例如 `mail_tpl: "default"` 使用的就是:[/email-tpl/default.html](https://github.com/ArtalkJS/Artalk/blob/master/email-tpl/default.html)
|
||||
Artalk 内置许多预设的邮件模板,例如 `mail_tpl: "default"` 使用的就是:[@ArtalkJS/Artalk:/internal/template/email_tpl/default.html](https://github.com/ArtalkJS/Artalk/blob/master/internal/template/email_tpl/default.html)
|
||||
|
||||
## 发向管理员的邮件
|
||||
|
||||
@@ -324,4 +324,4 @@ admin_notify:
|
||||
|
||||
注:旧版 `email.mail_subject_to_admin` 配置项已弃用,请使用以上替代。
|
||||
|
||||
不局限于邮件,Artalk 支持多种方式向管理员发送通知,参考:[“多元推送”](./admin_notify.md#邮件通知)。
|
||||
不局限于邮件,Artalk 支持多种方式向管理员发送通知,参考:[多元推送](./admin_notify.md#邮件通知)。
|
||||
@@ -60,7 +60,7 @@ Artalk.init({
|
||||
|
||||
建议 `frontend.emoticons` 填入表情包的 URL,而非 Object。
|
||||
|
||||
参考文档:[“表情包”](/guide/frontend/emoticons)
|
||||
参考文档:[表情包](/guide/frontend/emoticons)
|
||||
|
||||
如需传递 Object,可以将其转为 JSON 字符串格式,例如:
|
||||
|
||||
@@ -41,7 +41,7 @@ img_upload:
|
||||
|
||||
频率限制跟随 `captcha` 验证码配置,当超出限制将弹出验证码。
|
||||
|
||||
可参考:[“后端 · 验证码”](/guide/backend/captcha.md)
|
||||
可参考:[后端 · 验证码](/guide/backend/captcha.md)
|
||||
|
||||
## path
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -63,7 +63,7 @@ moderator:
|
||||
|
||||
## 腾讯云文本内容安全
|
||||
|
||||
可参考:[“腾讯云文档”](https://cloud.tencent.com/document/product/1124/64508)
|
||||
可参考:[腾讯云文档](https://cloud.tencent.com/document/product/1124/64508)
|
||||
|
||||
开通「文本内容安全」后,在「访问管理」-「API 密钥管理」新增具有权限的 Secret,然后填入配置:
|
||||
|
||||
@@ -78,7 +78,7 @@ moderator:
|
||||
|
||||
## 阿里云内容安全
|
||||
|
||||
可参考:[“阿里云文档”](https://help.aliyun.com/document_detail/28417.html)
|
||||
可参考:[阿里云文档](https://help.aliyun.com/document_detail/28417.html)
|
||||
|
||||
开通「阿里云内容安全」后,阿里云后台创建 Access Key 并填入配置:
|
||||
|
||||
@@ -26,7 +26,7 @@ docker exec -it artalk artalk admin
|
||||
|
||||
## 站点的创建和管理
|
||||
|
||||
你可以在侧边栏「[控制中心](../frontend/sidebar.md#控制中心)」创建多个站点,管理站点和快速切换站点,详情可参考:[“侧边栏”](/guide/frontend/sidebar.html)。
|
||||
你可以在侧边栏「[控制中心](../frontend/sidebar.md#控制中心)」创建多个站点,管理站点和快速切换站点,详情可参考:[侧边栏](/guide/frontend/sidebar.html)。
|
||||
|
||||
## 管理员配置
|
||||
|
||||
@@ -66,7 +66,7 @@ admin_users:
|
||||
|
||||
然后配置填写:`"(bcrypt)$2y$10$ti4vZYIrxVN8rLcY..."`,以 `(bcrypt)` 开头。
|
||||
|
||||
命令解释参考:[“Compute bcrypt hash from command line”](https://unix.stackexchange.com/questions/307994/compute-bcrypt-hash-from-command-line#answer-419855)
|
||||
命令解释参考:[Compute bcrypt hash from command line](https://unix.stackexchange.com/questions/307994/compute-bcrypt-hash-from-command-line#answer-419855)
|
||||
|
||||
- **badge_name**:用户显示的头衔徽标文字。
|
||||
- **badge_color**:用户显示的头衔徽标背景颜色。
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,5 +1,25 @@
|
||||
# 反向代理
|
||||
|
||||
## Caddy
|
||||
|
||||
**/etc/caddy/Caddyfile**
|
||||
|
||||
```nginx
|
||||
artalk.your_domain.com {
|
||||
tls /etc/caddy/ssl/cert.pem /etc/caddy/ssl/cert.key
|
||||
|
||||
reverse_proxy http://localhost:23366 {
|
||||
header_up X-Forwarded-For {header.X-Forwarded-For}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
执行重载命令:
|
||||
|
||||
```sh
|
||||
sudo systemctl reload caddy
|
||||
```
|
||||
|
||||
## Nginx
|
||||
|
||||
假定:
|
||||
@@ -67,16 +87,6 @@ Artalk.init({ server: "http://artalk.your_domain.com" })
|
||||
尤其是运行在 Docker 容器内的 artalk,注意检查 IP 和端口是否能够被 Nginx 正常访问
|
||||
:::
|
||||
|
||||
## Caddy
|
||||
|
||||
创建 Caddyfile:
|
||||
|
||||
```
|
||||
artalk.your_domain.com {
|
||||
reverse_proxy / http://localhost:23366
|
||||
}
|
||||
```
|
||||
|
||||
## Apache
|
||||
|
||||
需要启用反代模块 `mod_proxy.c`
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
:::tip
|
||||
|
||||
执行 `./artalk upgrade -f` 携带参数 `-f` 来进行同版本号的补充更新。
|
||||
执行 `./artalk upgrade -f` 携带参数 `-f` 执行强制更新。
|
||||
|
||||
:::
|
||||
|
||||
## Docker 升级
|
||||
|
||||
可参考:[“Docker · 升级”](./docker.md#升级)
|
||||
可参考:[Docker · 升级](./docker.md#升级)
|
||||
|
||||
## 普通方式
|
||||
|
||||
File renamed without changes.
@@ -51,14 +51,11 @@ Artalk.init({
|
||||
|
||||
在控制台,你可以根据喜好配置评论系统、[将评论迁移到 Artalk](./transfer.md)。
|
||||
|
||||
祝贺!你已成功完成 Artalk 部署 🥳
|
||||
🥳 你已成功完成 Artalk 部署!
|
||||
|
||||
## 普通方式部署
|
||||
|
||||
1. 前往 [GitHub Release](https://github.com/ArtalkJS/Artalk/releases) 下载程序压缩包
|
||||
|
||||
> 注:我们已将 ArtalkGo 与主仓库合并,历史旧版可在[此页面](https://github.com/ArtalkJS/ArtalkGo/releases)查看,日后新版将在[新页面](https://github.com/ArtalkJS/Artalk/releases)发布。
|
||||
|
||||
2. 提取压缩包:`tar -zxvf artalk_版本号_系统_架构.tar.gz`
|
||||
3. 运行程序 `./artalk server`
|
||||
4. 前端配置
|
||||
@@ -67,25 +64,16 @@ Artalk.init({
|
||||
Artalk.init({ server: "http://your_domain:23366" })
|
||||
```
|
||||
|
||||
**其它可选操作:**
|
||||
**进一步操作:**
|
||||
|
||||
- [“反向代理端口到 80 / 443 (Nginx, Apache)”](./backend/reverse-proxy.md)
|
||||
- ["持久化运作 (tmux, systemd, supervisor)"](./backend/daemon.md)
|
||||
- [守护进程 (Systemd, Supervisor)](./backend/daemon.md)
|
||||
- [反向代理 (Caddy, Nginx, Apache)](./backend/reverse-proxy.md)
|
||||
|
||||
**附表:文件名释义表**
|
||||
如果有需要,你还可以自行编译程序,参考:[后端构建](./backend/build.md)。
|
||||
|
||||
|文件名|操作系统|CPU 架构|
|
||||
|:-|:-:|:-:|
|
||||
|artalk_linux_amd64.tar.gz|Linux|x86_64|
|
||||
|artalk_linux_arm64.tar.gz|Linux|ARM64|
|
||||
|artalk_linux_arm7.tar.gz|Linux|ARMv7|
|
||||
|artalk_windows_amd64.zip|Windows|x86_64|
|
||||
|artalk_darwin_arm64.tar.gz|macOS|Apple Silicon|
|
||||
|artalk_darwin_amd64.tar.gz|macOS|Intel Chip|
|
||||
## Compose 部署
|
||||
|
||||
## Docker Compose 部署
|
||||
|
||||
提供 docker-compose.yaml 文件可供参考:
|
||||
**compose.yaml**
|
||||
|
||||
```yaml
|
||||
version: "3.5"
|
||||
@@ -100,7 +88,7 @@ services:
|
||||
- ./data:/data
|
||||
```
|
||||
|
||||
在与配置文件相同的目录执行命令创建容器:
|
||||
执行命令创建容器:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
@@ -118,11 +106,7 @@ docker-compose exec artalk bash # 进入容器
|
||||
|
||||
:::
|
||||
|
||||
> 详细可见:[“后端 · Docker”](./backend/docker.md)
|
||||
|
||||
## 自行编译并运行
|
||||
|
||||
可参考:[“后端构建”](./backend/build.md)
|
||||
可参考:[Docker 部署文档](./backend/docker.md)
|
||||
|
||||
## CDN 资源
|
||||
|
||||
@@ -135,7 +119,21 @@ docker-compose exec artalk bash # 进入容器
|
||||
|
||||
Artalk 后端程序内嵌了前端 JS、CSS 文件,使用公共 CDN 资源请注意前后端版本的兼容性。
|
||||
|
||||
Artalk 静态资源通过上游 [CDNJS](https://cdnjs.com/) 分发,国内有许多镜像可供选择:
|
||||
Artalk 静态资源通过上游 CDNJS 分发,以下镜像资源可供选择:
|
||||
|
||||
**CDNJS**
|
||||
|
||||
> https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.js
|
||||
>
|
||||
> https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.css
|
||||
|
||||
**Staticfile CDN (国内)**
|
||||
|
||||
> https://cdn.staticfile.org/artalk/:ArtalkVersion:/Artalk.js
|
||||
>
|
||||
> https://cdn.staticfile.org/artalk/:ArtalkVersion:/Artalk.css
|
||||
|
||||
::: details 查看更多
|
||||
|
||||
**BootCDN (国内)**
|
||||
|
||||
@@ -143,18 +141,11 @@ Artalk 静态资源通过上游 [CDNJS](https://cdnjs.com/) 分发,国内有
|
||||
>
|
||||
> https://cdn.bootcdn.net/ajax/libs/artalk/:ArtalkVersion:/Artalk.css
|
||||
|
||||
**75CDN (国内)**
|
||||
|
||||
**ElemeCDN (国内)**
|
||||
|
||||
> https://npm.elemecdn.com/artalk@:ArtalkVersion:/dist/Artalk.js
|
||||
> https://lib.baomitu.com/artalk/:ArtalkVersion:/Artalk.js
|
||||
>
|
||||
> https://npm.elemecdn.com/artalk@:ArtalkVersion:/dist/Artalk.css
|
||||
|
||||
**CDNJS**
|
||||
|
||||
> https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.js
|
||||
>
|
||||
> https://cdnjs.cloudflare.com/ajax/libs/artalk/:ArtalkVersion:/Artalk.css
|
||||
> https://lib.baomitu.com/artalk/:ArtalkVersion:/Artalk.css
|
||||
|
||||
**UNPKG**
|
||||
|
||||
@@ -168,11 +159,9 @@ Artalk 静态资源通过上游 [CDNJS](https://cdnjs.com/) 分发,国内有
|
||||
>
|
||||
> https://cdn.jsdelivr.net/npm/artalk@:ArtalkVersion:/dist/Artalk.css
|
||||
|
||||
## ArtalkLite
|
||||
:::
|
||||
|
||||
可选择精简版 [ArtalkLite](./frontend/artalk-lite.md):体积更小、更简约。
|
||||
|
||||
## Node 环境
|
||||
## Node 项目
|
||||
|
||||
```bash
|
||||
pnpm add artalk
|
||||
@@ -189,13 +178,20 @@ Artalk.init({
|
||||
})
|
||||
```
|
||||
|
||||
## 何时引入、何时 init?
|
||||
可参考:
|
||||
|
||||
- 可以在任意位置引入 JS 和 CSS 资源,但需确保 JS 引入在执行 `Artalk.init({})` 前。
|
||||
- 执行 `Artalk.init({ el: '#x' })` 时,需要确保 `<div id="x"></div>` 存在于页面当中。
|
||||
|
||||
可参考:[“前端框架引入”](./frontend/import-framework.md) / [“博客引入”](./frontend/import-blog.md)
|
||||
- [置入框架文档](./frontend/import-framework.md)
|
||||
- [置入博客文档](./frontend/import-blog.md)
|
||||
- [前端 API](../develop/fe-api.md)
|
||||
|
||||
## 数据导入
|
||||
|
||||
从其他评论系统导入数据:[“数据迁移”](./transfer.md)
|
||||
从其他评论系统导入数据:[数据迁移](./transfer.md)
|
||||
|
||||
## ArtalkLite
|
||||
|
||||
可选择精简版 [ArtalkLite](./frontend/artalk-lite.md):体积更小、更简约。
|
||||
|
||||
## 开发环境
|
||||
|
||||
可参考:[开发者指南](https://github.com/ArtalkJS/Artalk/blob/master/CONTRIBUTING.md)
|
||||
File renamed without changes.
@@ -12,8 +12,11 @@ Artalk 离不开社区的支持与帮助,**是你们让 Artalk 走得更远!
|
||||
- [Nuxt.js如何部署Artalk和遇到的问题 (By @子舒)](https://imhan.cn/posts/20220218/)
|
||||
- [宝塔安装过程大概记录 (By @xiamuguizhi)](https://github.com/ArtalkJS/Artalk/discussions/46)
|
||||
- [Vuepress配置评论插件为Artalk](https://wiki.eryajf.net/pages/b74c2b/)
|
||||
- [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/)
|
||||
|
||||
更多新版读物正在撰写当中(
|
||||
更多新版读物正在撰写当中...
|
||||
|
||||
## Artalk v1
|
||||
|
||||
File renamed without changes.
@@ -1,18 +1,19 @@
|
||||
# 前端配置
|
||||
|
||||
```js
|
||||
Artalk.init({ 你的配置... })
|
||||
Artalk.update({ 更新配置... })
|
||||
const artalk = Artalk.init({ ... })
|
||||
|
||||
artalk.update({ ... })
|
||||
```
|
||||
|
||||
- 默认配置:[defaults.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/src/defaults.ts)
|
||||
- 声明文件:[artalk-config.d.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/types/artalk-config.d.ts)
|
||||
- 声明文件:[config.ts](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/types/config.ts)
|
||||
|
||||
## 轻松配置
|
||||
|
||||
推荐在侧边栏 “[控制中心](/guide/frontend/sidebar.md)” 通过图形界面修改前端的配置,而无需在代码中对界面进行设定。
|
||||
|
||||
注:前端的设定可能会被后端覆盖,更多内容参考:[“在后端控制前端”](/guide/backend/fe-control.md)
|
||||
注:前端的设定可能会被后端覆盖,更多内容参考:[在后端控制前端](/guide/backend/fe-control.md)
|
||||
|
||||
## 基本配置(必填项)
|
||||
|
||||
@@ -36,7 +37,7 @@ Artalk.update({ 更新配置... })
|
||||
|
||||
可以填写由博客系统生成的 `固定链接`,但建议使用相对路径以便日后切换域名。
|
||||
|
||||
参考:[“关于使用相对 / 绝对路径”](/guide/backend/relative-path.md)
|
||||
参考:[关于使用相对 / 绝对路径](/guide/backend/relative-path.md)
|
||||
|
||||
### pageTitle
|
||||
|
||||
@@ -84,7 +85,7 @@ Artalk 支持多站点统一管理,此项用于站点隔离。
|
||||
|
||||
可以在后端的配置文件中定义前端的配置,让前端配置始终跟随后端。
|
||||
|
||||
详情可参考:[“在后端控制前端”](/guide/backend/fe-control)
|
||||
详情可参考:[在后端控制前端](/guide/backend/fe-control)
|
||||
|
||||
## 国际化 (i18n)
|
||||
|
||||
@@ -99,7 +100,7 @@ Artalk 支持多站点统一管理,此项用于站点隔离。
|
||||
|
||||
欢迎提交 PR 帮助翻译 Artalk 的多语言,为社区贡献一份力量!
|
||||
|
||||
详情参考:[“多语言”](./i18n.md)
|
||||
详情参考:[多语言](./i18n.md)
|
||||
|
||||
## 请求
|
||||
|
||||
@@ -121,7 +122,7 @@ Artalk 支持多站点统一管理,此项用于站点隔离。
|
||||
- 类型:`Object|Array|String|Boolean`
|
||||
- 默认值:"[https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json](https://cdn.jsdelivr.net/gh/ArtalkJS/Emoticons/grps/default.json)"
|
||||
|
||||
详细内容:[“前端 · 表情包”](/guide/frontend/emoticons.md)
|
||||
详细内容:[前端 · 表情包](/guide/frontend/emoticons.md)
|
||||
|
||||
更新兼容 [OwO 格式](https://github.com/DIYgod/OwO),支持 URL 动态加载。
|
||||
|
||||
@@ -175,7 +176,7 @@ JS DELIVR 在中国大陆的 [ICP 牌照已被吊销](https://github.com/jsdeliv
|
||||
代码动态修改 darkMode:
|
||||
|
||||
```js
|
||||
Artalk.setDarkMode(true)
|
||||
artalk.setDarkMode(true)
|
||||
```
|
||||
|
||||
> 参考代码:“[index.html](https://github.com/ArtalkJS/Artalk/blob/master/ui/packages/artalk/index.html#L97-L150)”
|
||||
@@ -268,7 +269,7 @@ pvEl 和 countEl 元素标签都可以设置 `data-page-key` 属性值,来指
|
||||
**显示用户的 UserAgent 信息徽标**
|
||||
|
||||
- 类型:`Boolean`
|
||||
- 默认值:`true`
|
||||
- 默认值:`false`
|
||||
|
||||
### listSort
|
||||
|
||||
@@ -350,12 +351,24 @@ gravatar: {
|
||||
>
|
||||
> loli:https://gravatar.loli.net/avatar/
|
||||
|
||||
### gravatar.default
|
||||
### gravatar.params
|
||||
|
||||
**默认头像**(URL or [Gravatar Type](http://cn.gravatar.org/site/implement/images/#default-image))
|
||||
**Gravatar API 参数**
|
||||
|
||||
- 类型:`String`
|
||||
- 默认值:`"mp"`
|
||||
- 默认值:`"d=mp&s=240"`
|
||||
|
||||
例如,你可以通过该配置项设置默认头像 (`d=mp`) 和头像尺寸 (`s=240`)。
|
||||
|
||||
参考:[Gravatar API 文档](http://cn.gravatar.org/site/implement/images/)
|
||||
|
||||
该配置项格式为 HTTP Query。
|
||||
|
||||
::: warning 更新注意
|
||||
|
||||
v2.5.5 已废弃 `gravatar.default` 配置项,请使用 `gravatar.params` 替代。
|
||||
|
||||
:::
|
||||
|
||||
### avatarURLBuilder
|
||||
|
||||
@@ -9,7 +9,7 @@ frontend:
|
||||
|
||||
## 表情包预设
|
||||
|
||||
Artalk 社区提供许多表情包预设,你能够挑选几套喜欢的表情包,仅需简单的配置,轻松添加到你的评论系统中,前往仓库:[“@ArtalkJS/Emoticons”](https://github.com/ArtalkJS/Emoticons)。
|
||||
Artalk 社区提供许多表情包预设,你能够挑选几套喜欢的表情包,仅需简单的配置,轻松添加到你的评论系统中,前往仓库:[@ArtalkJS/Emoticons](https://github.com/ArtalkJS/Emoticons)。
|
||||
|
||||
## 格式支持
|
||||
|
||||
@@ -57,7 +57,7 @@ Artalk 除了支持 OwO 格式外,还内置支持一种标准的表情包列
|
||||
|
||||
::: warning
|
||||
|
||||
前端的配置将默认被后端覆盖,详情参考:[“在后端控制前端”](/guide/backend/fe-control.html)
|
||||
前端的配置将默认被后端覆盖,详情参考:[在后端控制前端](/guide/backend/fe-control.html)
|
||||
|
||||
:::
|
||||
|
||||
File renamed without changes.
@@ -4,6 +4,11 @@
|
||||
|
||||
<<< @/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`:
|
||||
@@ -99,66 +104,36 @@ NexT 主题可以安装 [Hexo NexT 主题的 Artalk 插件](https://github.com/l
|
||||
|
||||
:::
|
||||
|
||||
## 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
|
||||
|
||||
以 [VuePress v2](https://github.com/vuepress/vuepress-next) 为例,继承默认主题 `@vuepress/theme-default`
|
||||
(待补充)
|
||||
|
||||
可参考:[“/.vuepress/theme/Artalk.vue”](https://github.com/ArtalkJS/Docs/blob/eef37bca8cc0c9973bf121fdef4014dcd940f104/docs/.vuepress/theme/Artalk.vue) 创建 Artalk 评论组件。
|
||||
::: tip 提示
|
||||
|
||||
在 `/.vuepress/theme/clientAppEnhance.ts` 文件中全局注册组件:
|
||||
可参考:[置入框架](./import-framework.md)
|
||||
|
||||
```ts
|
||||
import { defineClientAppEnhance } from '@vuepress/client'
|
||||
|
||||
import Artalk from './Artalk.vue'
|
||||
|
||||
export default defineClientAppEnhance(({ app, router, siteData }) => {
|
||||
app.component('Artalk', Artalk)
|
||||
})
|
||||
```
|
||||
|
||||
主题布局 `/.vuepress/theme/Layout.vue`:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<Layout>
|
||||
<template #page-bottom>
|
||||
<div class="page-meta">
|
||||
<!-- Artalk -->
|
||||
<Artalk />
|
||||
</div>
|
||||
</template>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, nextTick } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import Layout from '@vuepress/theme-default/lib/client/layouts/Layout.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: { Layout },
|
||||
mounted: () => {
|
||||
}
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
主题配置文件 `/.vuepress/theme/index.ts`:
|
||||
|
||||
```ts
|
||||
import { path } from '@vuepress/utils'
|
||||
|
||||
export default ({
|
||||
name: 'vuepress-theme-local',
|
||||
extends: '@vuepress/theme-default',
|
||||
layouts: {
|
||||
Layout: path.resolve(__dirname, 'Layout.vue'),
|
||||
},
|
||||
clientAppEnhanceFiles: path.resolve(__dirname, 'clientAppEnhance.ts'),
|
||||
})
|
||||
```
|
||||
:::
|
||||
|
||||
## Typecho
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
# 置入框架
|
||||
|
||||
## 安装 Artalk
|
||||
|
||||
通过包管理工具引入 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>
|
||||
```
|
||||
|
||||
## 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>
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
# ArtalkJS
|
||||
|
||||
Artalk 拥有一个前端,[GitHub 代码仓库](https://github.com/ArtalkJS/Artalk)。
|
||||
|
||||
## 特性
|
||||
|
||||
可见:[README.md · 特性](https://github.com/ArtalkJS/Artalk#%E7%89%B9%E6%80%A7)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 661 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user