artalk 2.6.3 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +7673 -7330
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/dist/ArtalkLite.css +1 -1
- package/dist/ArtalkLite.es.js +5304 -4961
- package/dist/ArtalkLite.iife.js +1 -1
- package/dist/ArtalkLite.js +1 -1
- package/dist/src/api/{api-base.d.ts → _base.d.ts} +3 -7
- package/dist/src/api/_options.d.ts +19 -0
- package/dist/src/api/{request.d.ts → _request.d.ts} +3 -3
- package/dist/src/api/admin.d.ts +1 -1
- package/dist/src/api/captcha.d.ts +1 -1
- package/dist/src/api/comment.d.ts +2 -2
- package/dist/src/api/index.d.ts +2 -4
- package/dist/src/api/page.d.ts +3 -3
- package/dist/src/api/site.d.ts +2 -2
- package/dist/src/api/system.d.ts +13 -3
- package/dist/src/api/upload.d.ts +1 -1
- package/dist/src/api/user.d.ts +2 -2
- package/dist/src/artalk.d.ts +14 -37
- package/dist/src/comment/actions.d.ts +1 -1
- package/dist/src/comment/comment.d.ts +3 -4
- package/dist/src/comment/render.d.ts +21 -3
- package/dist/src/comment/renders/actions.d.ts +2 -2
- package/dist/src/comment/renders/avatar.d.ts +2 -2
- package/dist/src/comment/renders/content.d.ts +2 -2
- package/dist/src/comment/renders/header.d.ts +2 -2
- package/dist/src/comment/renders/index.d.ts +2 -2
- package/dist/src/comment/renders/pending.d.ts +2 -2
- package/dist/src/comment/renders/reply-at.d.ts +2 -2
- package/dist/src/comment/renders/reply-to.d.ts +2 -2
- package/dist/src/components/action-btn.d.ts +3 -5
- package/dist/src/{lib → components}/checker/admin.d.ts +1 -1
- package/dist/src/{lib → components}/checker/captcha-renders.d.ts +1 -1
- package/dist/src/{lib → components}/checker/captcha.d.ts +1 -1
- package/dist/src/{lib → components}/checker/index.d.ts +10 -7
- package/dist/src/components/dark-mode.d.ts +2 -0
- package/dist/src/components/dialog.d.ts +1 -3
- package/dist/src/components/error-dialog.d.ts +8 -0
- package/dist/src/components/pagination.d.ts +4 -3
- package/dist/src/components/read-more-btn.d.ts +3 -3
- package/dist/src/config.d.ts +24 -8
- package/dist/src/context.d.ts +16 -35
- package/dist/src/data.d.ts +27 -0
- package/dist/src/defaults.d.ts +1 -1
- package/dist/src/editor/editor.d.ts +14 -59
- package/dist/src/editor/state.d.ts +20 -0
- package/dist/src/i18n/zh-CN.d.ts +1 -1
- package/dist/src/layer/index.d.ts +4 -3
- package/dist/src/layer/layer-manager.d.ts +9 -0
- package/dist/src/layer/layer.d.ts +8 -28
- package/dist/src/layer/scrollbar-helper.d.ts +5 -0
- package/dist/src/layer/sidebar-layer.d.ts +6 -6
- package/dist/src/layer/wrap.d.ts +13 -0
- package/dist/src/lib/component.d.ts +3 -8
- package/dist/src/lib/event-manager.d.ts +28 -0
- package/dist/src/lib/highlight.d.ts +1 -0
- package/dist/src/lib/marked-renderer.d.ts +4 -0
- package/dist/src/lib/marked.d.ts +4 -2
- package/dist/src/lib/sanitizer.d.ts +1 -0
- package/dist/src/lib/ui.d.ts +3 -2
- package/dist/src/lib/user.d.ts +8 -5
- package/dist/src/lib/utils.d.ts +11 -5
- package/dist/src/list/comment.d.ts +3 -0
- package/dist/src/list/layout.d.ts +23 -0
- package/dist/src/list/list.d.ts +13 -25
- package/dist/src/list/{list-nest.d.ts → nest.d.ts} +1 -1
- package/dist/src/list/page.d.ts +2 -0
- package/dist/src/list/paginator/index.d.ts +22 -7
- package/dist/src/list/paginator/read-more.d.ts +18 -0
- package/dist/src/list/paginator/up-down.d.ts +14 -0
- package/dist/src/main.d.ts +2 -0
- package/dist/src/plugins/admin-only-elem.d.ts +2 -0
- package/dist/src/plugins/conf-remoter.d.ts +2 -0
- package/dist/src/plugins/dark-mode.d.ts +2 -0
- package/dist/src/plugins/editor/_kit.d.ts +27 -0
- package/dist/src/plugins/editor/_plug.d.ts +29 -0
- package/dist/src/plugins/editor/_sample.d.ts +5 -0
- package/dist/src/plugins/editor/closable.d.ts +7 -0
- package/dist/src/{editor/plugs/emoticons-plug.d.ts → plugins/editor/emoticons.d.ts} +10 -16
- package/dist/src/plugins/editor/header-event.d.ts +6 -0
- package/dist/src/plugins/editor/header-link.d.ts +6 -0
- package/dist/src/plugins/editor/header-user.d.ts +16 -0
- package/dist/src/plugins/editor/index.d.ts +6 -0
- package/dist/src/plugins/editor/local-storage.d.ts +6 -0
- package/dist/src/plugins/editor/mover.d.ts +6 -0
- package/dist/src/plugins/editor/preview.d.ts +7 -0
- package/dist/src/plugins/editor/state-edit.d.ts +11 -0
- package/dist/src/plugins/editor/state-reply.d.ts +8 -0
- package/dist/src/plugins/editor/submit-add.d.ts +18 -0
- package/dist/src/plugins/editor/submit-btn.d.ts +5 -0
- package/dist/src/plugins/editor/submit.d.ts +17 -0
- package/dist/src/plugins/editor/textarea.d.ts +8 -0
- package/dist/src/plugins/editor/upload.d.ts +9 -0
- package/dist/src/plugins/editor-kit.d.ts +42 -0
- package/dist/src/plugins/index.d.ts +2 -0
- package/dist/src/plugins/list/copyright.d.ts +2 -0
- package/dist/src/plugins/list/count.d.ts +2 -0
- package/dist/src/plugins/list/dropdown.d.ts +2 -0
- package/dist/src/plugins/list/error-dialog.d.ts +2 -0
- package/dist/src/plugins/list/fetch.d.ts +2 -0
- package/dist/src/plugins/list/goto-first.d.ts +3 -0
- package/dist/src/plugins/list/goto.d.ts +2 -0
- package/dist/src/plugins/list/index.d.ts +3 -0
- package/dist/src/plugins/list/loading.d.ts +2 -0
- package/dist/src/plugins/list/no-comment.d.ts +2 -0
- package/dist/src/plugins/list/reach-bottom.d.ts +2 -0
- package/dist/src/plugins/list/sidebar-btn.d.ts +2 -0
- package/dist/src/plugins/list/time-ticking.d.ts +3 -0
- package/dist/src/plugins/list/unread-badge.d.ts +2 -0
- package/dist/src/plugins/list/unread.d.ts +2 -0
- package/dist/src/plugins/list/with-editor.d.ts +2 -0
- package/dist/src/plugins/markdown.d.ts +2 -0
- package/dist/src/plugins/stat.d.ts +13 -0
- package/dist/src/plugins/version-check.d.ts +2 -0
- package/dist/src/service.d.ts +19 -23
- package/dist/tests/e2e/comment-add.spec.d.ts +1 -0
- package/dist/types/config.d.ts +110 -0
- package/dist/types/context.d.ts +56 -136
- package/dist/types/data.d.ts +194 -0
- package/dist/types/editor.d.ts +76 -0
- package/dist/types/event.d.ts +36 -25
- package/dist/types/index.d.ts +7 -0
- package/dist/types/plugin.d.ts +2 -0
- package/dist/types/sidebar.d.ts +3 -0
- package/package.json +5 -2
- package/src/api/_base.ts +18 -0
- package/src/api/_options.ts +25 -0
- package/src/api/{request.ts → _request.ts} +19 -18
- package/src/api/admin.ts +1 -1
- package/src/api/captcha.ts +1 -1
- package/src/api/comment.ts +4 -4
- package/src/api/index.ts +3 -12
- package/src/api/page.ts +5 -5
- package/src/api/site.ts +2 -2
- package/src/api/system.ts +19 -7
- package/src/api/upload.ts +3 -3
- package/src/api/user.ts +3 -3
- package/src/artalk.ts +49 -97
- package/src/comment/actions.ts +1 -4
- package/src/comment/comment.ts +9 -6
- package/src/comment/render.ts +27 -5
- package/src/comment/renders/actions.ts +45 -45
- package/src/comment/renders/avatar.ts +7 -7
- package/src/comment/renders/content.ts +18 -18
- package/src/comment/renders/header.ts +13 -13
- package/src/comment/renders/index.ts +3 -3
- package/src/comment/renders/pending.ts +5 -5
- package/src/comment/renders/reply-at.ts +8 -8
- package/src/comment/renders/reply-to.ts +13 -13
- package/src/components/action-btn.ts +11 -13
- package/src/{lib → components}/checker/admin.ts +6 -6
- package/src/{lib → components}/checker/captcha-renders.ts +7 -6
- package/src/{lib → components}/checker/captcha.ts +1 -1
- package/src/{lib → components}/checker/index.ts +21 -26
- package/src/components/dark-mode.ts +30 -0
- package/src/components/dialog.ts +4 -9
- package/src/components/error-dialog.ts +35 -0
- package/src/components/pagination.ts +10 -6
- package/src/components/read-more-btn.ts +7 -7
- package/src/config.ts +60 -6
- package/src/context.ts +39 -144
- package/src/data.ts +110 -0
- package/src/defaults.ts +1 -1
- package/src/editor/editor.ts +41 -146
- package/src/editor/state.ts +52 -0
- package/src/i18n/zh-CN.ts +1 -1
- package/src/layer/index.ts +4 -4
- package/src/layer/layer-manager.ts +32 -0
- package/src/layer/layer.ts +20 -144
- package/src/layer/scrollbar-helper.ts +24 -0
- package/src/layer/sidebar-layer.ts +74 -64
- package/src/layer/wrap.ts +77 -0
- package/src/lib/component.ts +4 -11
- package/src/lib/detect.ts +1 -1
- package/src/lib/event-manager.ts +47 -0
- package/src/lib/highlight.ts +5 -0
- package/src/lib/marked-renderer.ts +32 -0
- package/src/lib/marked.ts +43 -104
- package/src/lib/sanitizer.ts +57 -0
- package/src/lib/ui.ts +22 -15
- package/src/lib/user.ts +21 -16
- package/src/lib/utils.ts +29 -18
- package/src/list/comment.ts +20 -0
- package/src/list/layout.ts +120 -0
- package/src/list/list.html +3 -1
- package/src/list/list.ts +56 -200
- package/src/list/{list-nest.ts → nest.ts} +1 -1
- package/src/list/page.ts +97 -0
- package/src/list/paginator/index.ts +20 -8
- package/src/list/paginator/read-more.ts +67 -0
- package/src/list/paginator/up-down.ts +51 -0
- package/src/main.ts +2 -0
- package/src/plugins/admin-only-elem.ts +40 -0
- package/src/plugins/conf-remoter.ts +54 -0
- package/src/plugins/dark-mode.ts +12 -0
- package/src/plugins/editor/_kit.ts +57 -0
- package/src/plugins/editor/_plug.ts +60 -0
- package/src/plugins/editor/_sample.ts +8 -0
- package/src/plugins/editor/closable.ts +44 -0
- package/src/{editor/plugs/emoticons-plug.ts → plugins/editor/emoticons.ts} +51 -52
- package/src/plugins/editor/header-event.ts +35 -0
- package/src/plugins/editor/header-link.ts +31 -0
- package/src/plugins/editor/header-user.ts +98 -0
- package/src/plugins/editor/index.ts +40 -0
- package/src/plugins/editor/local-storage.ts +36 -0
- package/src/plugins/editor/mover.ts +29 -0
- package/src/plugins/editor/preview.ts +41 -0
- package/src/plugins/editor/state-edit.ts +116 -0
- package/src/plugins/editor/state-reply.ts +91 -0
- package/src/plugins/editor/submit-add.ts +33 -0
- package/src/plugins/editor/submit-btn.ts +25 -0
- package/src/plugins/editor/submit.ts +73 -0
- package/src/plugins/editor/textarea.ts +55 -0
- package/src/plugins/editor/upload.ts +145 -0
- package/src/plugins/editor-kit.ts +161 -0
- package/src/plugins/index.ts +16 -0
- package/src/plugins/list/copyright.ts +16 -0
- package/src/plugins/list/count.ts +31 -0
- package/src/plugins/list/dropdown.ts +95 -0
- package/src/plugins/list/error-dialog.ts +22 -0
- package/src/plugins/list/fetch.ts +64 -0
- package/src/plugins/list/goto-first.ts +23 -0
- package/src/plugins/list/goto.ts +72 -0
- package/src/plugins/list/index.ts +25 -0
- package/src/plugins/list/loading.ts +17 -0
- package/src/plugins/list/no-comment.ts +25 -0
- package/src/plugins/list/reach-bottom.ts +46 -0
- package/src/plugins/list/sidebar-btn.ts +39 -0
- package/src/plugins/list/time-ticking.ts +22 -0
- package/src/plugins/list/unread-badge.ts +26 -0
- package/src/plugins/list/unread.ts +38 -0
- package/src/plugins/list/with-editor.ts +59 -0
- package/src/plugins/markdown.ts +10 -0
- package/src/plugins/stat.ts +79 -0
- package/src/plugins/version-check.ts +37 -0
- package/src/service.ts +34 -61
- package/src/style/comment.scss +5 -7
- package/src/style/editor.scss +5 -0
- package/src/style/list.scss +2 -7
- package/types/{artalk-config.d.ts → config.ts} +16 -2
- package/types/context.ts +84 -0
- package/{dist/types/artalk-data.d.ts → types/data.ts} +41 -0
- package/types/editor.ts +95 -0
- package/types/event.ts +40 -0
- package/types/index.ts +7 -0
- package/types/plugin.ts +3 -0
- package/types/sidebar.ts +3 -0
- package/dist/src/comment/render-ctx.d.ts +0 -23
- package/dist/src/editor/edit-mode.d.ts +0 -9
- package/dist/src/editor/funcs.d.ts +0 -2
- package/dist/src/editor/index.d.ts +0 -2
- package/dist/src/editor/mover.d.ts +0 -8
- package/dist/src/editor/plug-manager.d.ts +0 -17
- package/dist/src/editor/plugs/editor-plug.d.ts +0 -38
- package/dist/src/editor/plugs/header-input-plug.d.ts +0 -13
- package/dist/src/editor/plugs/preview-plug.d.ts +0 -10
- package/dist/src/editor/plugs/upload-plug.d.ts +0 -10
- package/dist/src/editor/reply.d.ts +0 -9
- package/dist/src/editor/submit.d.ts +0 -16
- package/dist/src/lib/dark-mode.d.ts +0 -4
- package/dist/src/lib/stat.d.ts +0 -15
- package/dist/src/list/index.d.ts +0 -2
- package/dist/src/list/list-lite.d.ts +0 -77
- package/dist/src/list/list-ui.d.ts +0 -16
- package/dist/src/list/paginator/adaptors/index.d.ts +0 -12
- package/dist/src/list/paginator/adaptors/pagination.d.ts +0 -9
- package/dist/src/list/paginator/adaptors/read-more.d.ts +0 -10
- package/dist/src/list/paginator/holder.d.ts +0 -16
- package/dist/types/artalk-config.d.ts +0 -139
- package/dist/types/plug.d.ts +0 -4
- package/src/api/api-base.ts +0 -27
- package/src/comment/render-ctx.ts +0 -30
- package/src/editor/edit-mode.ts +0 -103
- package/src/editor/funcs.ts +0 -97
- package/src/editor/index.ts +0 -3
- package/src/editor/mover.ts +0 -43
- package/src/editor/plug-manager.ts +0 -172
- package/src/editor/plugs/editor-plug.ts +0 -69
- package/src/editor/plugs/header-input-plug.ts +0 -79
- package/src/editor/plugs/preview-plug.ts +0 -44
- package/src/editor/plugs/upload-plug.ts +0 -122
- package/src/editor/reply.ts +0 -62
- package/src/editor/submit.ts +0 -99
- package/src/lib/dark-mode.ts +0 -48
- package/src/lib/stat.ts +0 -71
- package/src/list/index.ts +0 -3
- package/src/list/list-lite.ts +0 -424
- package/src/list/list-ui.ts +0 -137
- package/src/list/paginator/adaptors/index.ts +0 -21
- package/src/list/paginator/adaptors/pagination.ts +0 -42
- package/src/list/paginator/adaptors/read-more.ts +0 -56
- package/src/list/paginator/holder.ts +0 -56
- package/types/artalk-data.d.ts +0 -230
- package/types/context.d.ts +0 -142
- package/types/event.d.ts +0 -28
- package/types/plug.d.ts +0 -4
- /package/src/{editor/plugs/emoticons-plug.scss → plugins/editor/emoticons.scss} +0 -0
- /package/src/{editor/plugs/preview-plug.scss → plugins/editor/preview.scss} +0 -0
package/src/list/page.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { ArtalkConfig, ContextApi } from '~/types'
|
|
2
|
+
import $t from '@/i18n'
|
|
3
|
+
import { Paginator } from './paginator'
|
|
4
|
+
import ReadMorePaginator from './paginator/read-more'
|
|
5
|
+
import UpDownPaginator from './paginator/up-down'
|
|
6
|
+
|
|
7
|
+
function createPaginatorByConf(conf: ArtalkConfig): Paginator {
|
|
8
|
+
if (conf.pagination.readMore) return new ReadMorePaginator()
|
|
9
|
+
return new UpDownPaginator()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getPageDataByLastData(ctx: ContextApi): { offset: number, total: number } {
|
|
13
|
+
const last = ctx.getData().getListLastFetch()
|
|
14
|
+
const r = { offset: 0, total: 0 }
|
|
15
|
+
if (!last) return r
|
|
16
|
+
|
|
17
|
+
r.offset = last.params.offset
|
|
18
|
+
if (last.data) r.total = last.params.flatMode ? last.data.total : last.data.total_roots
|
|
19
|
+
|
|
20
|
+
return r
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const initListPaginatorFunc = (ctx: ContextApi) => {
|
|
24
|
+
let paginator: Paginator|null = null
|
|
25
|
+
|
|
26
|
+
// Init paginator when conf loaded
|
|
27
|
+
ctx.on('conf-loaded', (conf) => {
|
|
28
|
+
const list = ctx.get('list')
|
|
29
|
+
|
|
30
|
+
if (paginator) paginator.dispose() // if had been init, dispose it
|
|
31
|
+
|
|
32
|
+
// create paginator instance
|
|
33
|
+
paginator = createPaginatorByConf(conf)
|
|
34
|
+
|
|
35
|
+
// create paginator dom
|
|
36
|
+
const { offset, total } = getPageDataByLastData(ctx)
|
|
37
|
+
const $paginator = paginator.create({
|
|
38
|
+
ctx, pageSize: conf.pagination.pageSize, total,
|
|
39
|
+
|
|
40
|
+
readMoreAutoLoad: conf.pagination.autoLoad,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// mount paginator dom
|
|
44
|
+
list.$commentsWrap.after($paginator)
|
|
45
|
+
|
|
46
|
+
// update paginator info
|
|
47
|
+
paginator?.update(offset, total)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// When list loaded
|
|
51
|
+
ctx.on('list-loaded', (comments) => {
|
|
52
|
+
// update paginator info
|
|
53
|
+
const { offset, total } = getPageDataByLastData(ctx)
|
|
54
|
+
paginator?.update(offset, total)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
// When list fetch
|
|
58
|
+
ctx.on('list-fetch', (params) => {
|
|
59
|
+
// if clear comments when fetch new page data
|
|
60
|
+
if (ctx.getData().getComments().length > 0 && paginator?.getIsClearComments(params)) {
|
|
61
|
+
ctx.getData().clearComments()
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// When list error
|
|
66
|
+
ctx.on('list-error', () => {
|
|
67
|
+
paginator?.showErr?.($t('loadFail'))
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// List goto auto next page when comment not found
|
|
71
|
+
const autoSwitchPageForFindComment = (commentID: number) => {
|
|
72
|
+
const comment = ctx.getData().findComment(commentID)
|
|
73
|
+
if (!!comment || !paginator?.getHasMore()) return
|
|
74
|
+
|
|
75
|
+
// wait for list loaded
|
|
76
|
+
ctx.on('list-loaded', () => {
|
|
77
|
+
autoSwitchPageForFindComment(commentID) // recursive, until comment found or no more page
|
|
78
|
+
}, { once: true })
|
|
79
|
+
|
|
80
|
+
// TODO 自动范围改为直接跳转到计算后的页面
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
paginator?.next()
|
|
83
|
+
}, 80)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ctx.on('list-goto', (commentID) => {
|
|
87
|
+
autoSwitchPageForFindComment(commentID)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
// loading
|
|
91
|
+
ctx.on('list-fetch', (params) => {
|
|
92
|
+
paginator?.setLoading(true)
|
|
93
|
+
})
|
|
94
|
+
ctx.on('list-fetched', ({ params }) => {
|
|
95
|
+
paginator?.setLoading(false)
|
|
96
|
+
})
|
|
97
|
+
}
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import type { ContextApi, ListFetchParams } from '~/types'
|
|
2
|
+
import UpDownPaginator from './up-down'
|
|
3
|
+
import ReadMorePaginator from './read-more'
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
export interface IPgHolderConf {
|
|
7
|
-
list: ListLite
|
|
8
|
-
mode: TPgMode
|
|
5
|
+
export interface IPgHolderOpt {
|
|
6
|
+
ctx: ContextApi
|
|
9
7
|
total: number
|
|
10
8
|
pageSize: number
|
|
9
|
+
|
|
10
|
+
readMoreAutoLoad?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Paginator {
|
|
14
|
+
create(opts: IPgHolderOpt): HTMLElement
|
|
15
|
+
setLoading(val: boolean): void
|
|
16
|
+
update(offset: number, total: number): void
|
|
17
|
+
next(): void
|
|
18
|
+
showErr?(msg: string): void
|
|
19
|
+
getHasMore(): boolean
|
|
20
|
+
/** Clear comments when fetch new page data */
|
|
21
|
+
getIsClearComments(params: Partial<ListFetchParams>): boolean
|
|
22
|
+
dispose(): void
|
|
11
23
|
}
|
|
12
24
|
|
|
13
|
-
export default
|
|
25
|
+
export default { UpDownPaginator, ReadMorePaginator }
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ListFetchParams } from '~/types'
|
|
2
|
+
import ReadMoreBtn from '@/components/read-more-btn'
|
|
3
|
+
import $t from '@/i18n'
|
|
4
|
+
import type { Paginator, IPgHolderOpt } from '.'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 阅读更多形式的分页
|
|
8
|
+
*/
|
|
9
|
+
export default class ReadMorePaginator implements Paginator {
|
|
10
|
+
private instance!: ReadMoreBtn
|
|
11
|
+
private onReachedBottom: (() => void) | null = null
|
|
12
|
+
private opt!: IPgHolderOpt
|
|
13
|
+
|
|
14
|
+
create(opt: IPgHolderOpt) {
|
|
15
|
+
this.opt = opt
|
|
16
|
+
|
|
17
|
+
this.instance = new ReadMoreBtn({
|
|
18
|
+
pageSize: opt.pageSize,
|
|
19
|
+
onClick: async (o) => {
|
|
20
|
+
opt.ctx.fetch({
|
|
21
|
+
offset: o,
|
|
22
|
+
})
|
|
23
|
+
},
|
|
24
|
+
text: $t('loadMore'),
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// 滚动到底部自动加载
|
|
28
|
+
if (opt.readMoreAutoLoad) {
|
|
29
|
+
this.onReachedBottom = () => {
|
|
30
|
+
if (!this.instance.hasMore || this.opt.ctx.getData().getLoading()) return
|
|
31
|
+
this.instance.click()
|
|
32
|
+
}
|
|
33
|
+
this.opt.ctx.on('list-reach-bottom', this.onReachedBottom)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return this.instance.$el
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setLoading(val: boolean) {
|
|
40
|
+
this.instance.setLoading(val)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
update(offset: number, total: number) {
|
|
44
|
+
this.instance.update(offset, total)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
showErr(msg: string) {
|
|
48
|
+
this.instance.showErr(msg)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
next() {
|
|
52
|
+
this.instance.click()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getHasMore(): boolean {
|
|
56
|
+
return this.instance.hasMore
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getIsClearComments(params: Partial<ListFetchParams>): boolean {
|
|
60
|
+
return params.offset === 0
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
dispose(): void {
|
|
64
|
+
this.onReachedBottom && this.opt.ctx.off('list-reach-bottom', this.onReachedBottom)
|
|
65
|
+
this.instance.$el.remove()
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import PaginationComponent from '@/components/pagination'
|
|
2
|
+
import type { Paginator, IPgHolderOpt } from '.'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 翻页形式的分页
|
|
6
|
+
*/
|
|
7
|
+
export default class UpDownPaginator implements Paginator {
|
|
8
|
+
private instance!: PaginationComponent
|
|
9
|
+
|
|
10
|
+
create(opt: IPgHolderOpt) {
|
|
11
|
+
this.instance = new PaginationComponent(opt.total, {
|
|
12
|
+
pageSize: opt.pageSize,
|
|
13
|
+
onChange: async (o) => {
|
|
14
|
+
opt.ctx.editorResetState() // 防止评论框被吞
|
|
15
|
+
|
|
16
|
+
opt.ctx.fetch({
|
|
17
|
+
offset: o,
|
|
18
|
+
onSuccess: () => {
|
|
19
|
+
opt.ctx.listGotoFirst()
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
return this.instance.$el
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setLoading(val: boolean) {
|
|
29
|
+
this.instance.setLoading(val)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
update(offset: number, total: number) {
|
|
33
|
+
this.instance.update(offset, total)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
next() {
|
|
37
|
+
this.instance.next()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getHasMore(): boolean {
|
|
41
|
+
return this.instance.getHasMore()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getIsClearComments(): boolean {
|
|
45
|
+
return true
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
dispose(): void {
|
|
49
|
+
this.instance.$el.remove()
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/main.ts
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ArtalkPlugin } from '~/types'
|
|
2
|
+
|
|
3
|
+
export const AdminOnlyElem: ArtalkPlugin = (ctx) => {
|
|
4
|
+
const scanApply = () => {
|
|
5
|
+
applyAdminOnlyEls(ctx.get('user').data.isAdmin, getAdminOnlyEls({
|
|
6
|
+
$root: ctx.$root
|
|
7
|
+
}))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
ctx.on('list-loaded', () => {
|
|
11
|
+
scanApply()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
ctx.on('user-changed', (user) => {
|
|
15
|
+
scanApply()
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getAdminOnlyEls(opts: { $root: HTMLElement }): HTMLElement[] {
|
|
20
|
+
const els: HTMLElement[] = []
|
|
21
|
+
|
|
22
|
+
// elements in $root
|
|
23
|
+
opts.$root.querySelectorAll<HTMLElement>(`[atk-only-admin-show]`).forEach(item => els.push(item))
|
|
24
|
+
|
|
25
|
+
// TODO provide a Artalk.conf hook to set whitelist of admin-only elements,
|
|
26
|
+
// and move following code to that hook (move into packages/artalk-sidebar)
|
|
27
|
+
|
|
28
|
+
// elements in sidebar
|
|
29
|
+
const $sidebarEl = document.querySelector<HTMLElement>('.atk-sidebar')
|
|
30
|
+
if ($sidebarEl) $sidebarEl.querySelectorAll<HTMLElement>(`[atk-only-admin-show]`).forEach(item => els.push(item))
|
|
31
|
+
|
|
32
|
+
return els
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function applyAdminOnlyEls(isAdmin: boolean, els: HTMLElement[]) {
|
|
36
|
+
els.forEach(($item: HTMLElement) => {
|
|
37
|
+
if (isAdmin) $item.classList.remove('atk-hide')
|
|
38
|
+
else $item.classList.add('atk-hide')
|
|
39
|
+
})
|
|
40
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ArtalkConfig, ArtalkPlugin, ContextApi } from '~/types'
|
|
2
|
+
import { handleConfFormServer } from '@/config'
|
|
3
|
+
import { showErrorDialog } from '../components/error-dialog'
|
|
4
|
+
|
|
5
|
+
export const ConfRemoter: ArtalkPlugin = (ctx) => {
|
|
6
|
+
ctx.on('inited', () => {
|
|
7
|
+
loadConf(ctx)
|
|
8
|
+
})
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function loadConf(ctx: ContextApi) {
|
|
12
|
+
ctx.getApi().system.conf().then((data) => {
|
|
13
|
+
let conf: Partial<ArtalkConfig> = {
|
|
14
|
+
apiVersion: data.version.version, // version info
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// reference conf from backend
|
|
18
|
+
if (ctx.conf.useBackendConf) {
|
|
19
|
+
if (!data.frontend_conf) throw new Error('The remote backend does not respond to the frontend conf, but `useBackendConf` conf is enabled')
|
|
20
|
+
conf = { ...conf, ...handleConfFormServer(data.frontend_conf) }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// apply conf modifier
|
|
24
|
+
ctx.conf.remoteConfModifier && ctx.conf.remoteConfModifier(conf)
|
|
25
|
+
|
|
26
|
+
ctx.updateConf(conf)
|
|
27
|
+
}).catch((err) => {
|
|
28
|
+
ctx.updateConf({})
|
|
29
|
+
|
|
30
|
+
let sidebarOpenView = ''
|
|
31
|
+
|
|
32
|
+
// if response err_no_site, modify the sidebar open view to create site
|
|
33
|
+
if (err.data?.err_no_site) {
|
|
34
|
+
const viewLoadParam = { create_name: ctx.conf.site, create_urls: `${window.location.protocol}//${window.location.host}` }
|
|
35
|
+
sidebarOpenView = `sites|${JSON.stringify(viewLoadParam)}`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
showErrorDialog({
|
|
39
|
+
$err: ctx.get('list').$el,
|
|
40
|
+
errMsg: err.msg || String(err),
|
|
41
|
+
errData: err.data,
|
|
42
|
+
retryFn: () => loadConf(ctx),
|
|
43
|
+
onOpenSidebar:() => ctx.showSidebar({
|
|
44
|
+
view: sidebarOpenView as any
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
throw err
|
|
49
|
+
}).then(() => {
|
|
50
|
+
// 评论获取
|
|
51
|
+
if (ctx.conf.remoteConfModifier) return // only auto fetch when no remoteConfModifier
|
|
52
|
+
ctx.fetch({ offset: 0 })
|
|
53
|
+
}).catch(() => {})
|
|
54
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ArtalkPlugin } from '~/types'
|
|
2
|
+
import { applyDarkMode } from '@/components/dark-mode'
|
|
3
|
+
|
|
4
|
+
export const DarkMode: ArtalkPlugin = (ctx) => {
|
|
5
|
+
const sync = () => {
|
|
6
|
+
applyDarkMode([ctx.$root, ctx.get('layerManager').getEl()], ctx.conf.darkMode)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
ctx.on('inited', () => sync())
|
|
10
|
+
ctx.on('conf-loaded', () => sync())
|
|
11
|
+
ctx.on('dark-mode-changed', () => sync())
|
|
12
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { PlugManager } from '../editor-kit'
|
|
2
|
+
import type EditorPlug from "./_plug"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PlugKit provides a set of methods to help you develop editor plug
|
|
6
|
+
*/
|
|
7
|
+
export default class PlugKit {
|
|
8
|
+
constructor(
|
|
9
|
+
private plugs: PlugManager
|
|
10
|
+
) {
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Use the editor */
|
|
14
|
+
useEditor() {
|
|
15
|
+
return this.plugs.editor
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Use the context of global */
|
|
19
|
+
useGlobalCtx() {
|
|
20
|
+
return this.plugs.editor.ctx
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Use the config of Artalk */
|
|
24
|
+
useConf() {
|
|
25
|
+
return this.plugs.editor.ctx.conf
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Use the http api client */
|
|
29
|
+
useApi() {
|
|
30
|
+
return this.plugs.editor.ctx.getApi()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Use the ui of editor */
|
|
34
|
+
useUI() {
|
|
35
|
+
return this.plugs.editor.getUI()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Use the events in editor scope */
|
|
39
|
+
useEvents() {
|
|
40
|
+
return this.plugs.getEvents()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Listen the event when plug is mounted */
|
|
44
|
+
useMounted(func: () => void) {
|
|
45
|
+
this.useEvents().on('mounted', func)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Listen the event when plug is unmounted */
|
|
49
|
+
useUnmounted(func: () => void) {
|
|
50
|
+
this.useEvents().on('unmounted', func)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Use the deps of other plug */
|
|
54
|
+
useDeps<T extends typeof EditorPlug>(plug: T) {
|
|
55
|
+
return this.plugs.get(plug)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { CommentData, EditorState } from '~/types'
|
|
2
|
+
import * as Utils from '@/lib/utils'
|
|
3
|
+
import type PlugKit from './_kit'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Editor 插件
|
|
7
|
+
*/
|
|
8
|
+
interface EditorPlug {
|
|
9
|
+
$btn?: HTMLElement
|
|
10
|
+
$panel?: HTMLElement
|
|
11
|
+
contentTransformer?(rawContent: string): string
|
|
12
|
+
editorStateEffectWhen?: EditorState
|
|
13
|
+
editorStateEffect?(comment: CommentData): () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class EditorPlug {
|
|
17
|
+
constructor(
|
|
18
|
+
protected kit: PlugKit
|
|
19
|
+
) {
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Use plug btn will add a btn on the bottom of editor */
|
|
23
|
+
useBtn(html: string = '<div></div>') {
|
|
24
|
+
this.$btn = Utils.createElement(`<span class="atk-plug-btn">${html}</span>`)
|
|
25
|
+
return this.$btn
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Use plug panel will show the panel when btn is clicked */
|
|
29
|
+
usePanel(html: string = '<div></div>') {
|
|
30
|
+
this.$panel = Utils.createElement(html)
|
|
31
|
+
return this.$panel
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Use the content transformer to handle the content of the last submit by the editor */
|
|
35
|
+
useContentTransformer(func: (raw: string) => string) {
|
|
36
|
+
this.contentTransformer = func
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Listen the event of panel show */
|
|
40
|
+
usePanelShow(func: () => void) {
|
|
41
|
+
this.kit.useEvents().on('panel-show', (aPlug) => {
|
|
42
|
+
if (aPlug === this) func()
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Listen the event of panel hide */
|
|
47
|
+
usePanelHide(func: () => void) {
|
|
48
|
+
this.kit.useEvents().on('panel-hide', (aPlug) => {
|
|
49
|
+
if (aPlug === this) func()
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Use editor state modifier */
|
|
54
|
+
useEditorStateEffect(stateName: EditorState, effectFn: (comment: CommentData) => () => void) {
|
|
55
|
+
this.editorStateEffectWhen = stateName
|
|
56
|
+
this.editorStateEffect = effectFn
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default EditorPlug
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import User from '@/lib/user'
|
|
2
|
+
import * as Utils from '@/lib/utils'
|
|
3
|
+
import $t from '@/i18n'
|
|
4
|
+
import EditorPlug from './_plug'
|
|
5
|
+
import type PlugKit from './_kit'
|
|
6
|
+
|
|
7
|
+
export default class Closable extends EditorPlug {
|
|
8
|
+
constructor(kit: PlugKit) {
|
|
9
|
+
super(kit)
|
|
10
|
+
|
|
11
|
+
const onOpen = () => this.open()
|
|
12
|
+
const onClose = () => this.close()
|
|
13
|
+
|
|
14
|
+
this.kit.useMounted(() => {
|
|
15
|
+
this.kit.useEvents().on('editor-open', onOpen)
|
|
16
|
+
this.kit.useEvents().on('editor-close', onClose)
|
|
17
|
+
})
|
|
18
|
+
this.kit.useUnmounted(() => {
|
|
19
|
+
this.kit.useEvents().off('editor-open', onOpen)
|
|
20
|
+
this.kit.useEvents().off('editor-close', onClose)
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private open() {
|
|
25
|
+
this.kit.useUI().$textareaWrap.querySelector('.atk-comment-closed')?.remove()
|
|
26
|
+
this.kit.useUI().$textarea.style.display = ''
|
|
27
|
+
this.kit.useUI().$bottom.style.display = ''
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private close() {
|
|
31
|
+
if (!this.kit.useUI().$textareaWrap.querySelector('.atk-comment-closed'))
|
|
32
|
+
this.kit.useUI().$textareaWrap.prepend(Utils.createElement(`<div class="atk-comment-closed">${$t('onlyAdminCanReply')}</div>`))
|
|
33
|
+
|
|
34
|
+
if (!User.data.isAdmin) {
|
|
35
|
+
this.kit.useUI().$textarea.style.display = 'none'
|
|
36
|
+
this.kit.useEvents().trigger('panel-close')
|
|
37
|
+
this.kit.useUI().$bottom.style.display = 'none'
|
|
38
|
+
} else {
|
|
39
|
+
// 管理员一直打开评论
|
|
40
|
+
this.kit.useUI().$textarea.style.display = ''
|
|
41
|
+
this.kit.useUI().$bottom.style.display = ''
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|