artalk 2.6.4 → 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.
Files changed (300) hide show
  1. package/dist/Artalk.css +1 -1
  2. package/dist/Artalk.es.js +7794 -7483
  3. package/dist/Artalk.iife.js +1 -1
  4. package/dist/Artalk.js +1 -1
  5. package/dist/ArtalkLite.css +1 -1
  6. package/dist/ArtalkLite.es.js +5587 -5276
  7. package/dist/ArtalkLite.iife.js +1 -1
  8. package/dist/ArtalkLite.js +1 -1
  9. package/dist/src/api/{api-base.d.ts → _base.d.ts} +3 -7
  10. package/dist/src/api/_options.d.ts +19 -0
  11. package/dist/src/api/{request.d.ts → _request.d.ts} +3 -3
  12. package/dist/src/api/admin.d.ts +1 -1
  13. package/dist/src/api/captcha.d.ts +1 -1
  14. package/dist/src/api/comment.d.ts +2 -2
  15. package/dist/src/api/index.d.ts +2 -4
  16. package/dist/src/api/page.d.ts +3 -3
  17. package/dist/src/api/site.d.ts +2 -2
  18. package/dist/src/api/system.d.ts +13 -3
  19. package/dist/src/api/upload.d.ts +1 -1
  20. package/dist/src/api/user.d.ts +2 -2
  21. package/dist/src/artalk.d.ts +14 -37
  22. package/dist/src/comment/actions.d.ts +1 -1
  23. package/dist/src/comment/comment.d.ts +3 -4
  24. package/dist/src/comment/render.d.ts +21 -3
  25. package/dist/src/comment/renders/actions.d.ts +2 -2
  26. package/dist/src/comment/renders/avatar.d.ts +2 -2
  27. package/dist/src/comment/renders/content.d.ts +2 -2
  28. package/dist/src/comment/renders/header.d.ts +2 -2
  29. package/dist/src/comment/renders/index.d.ts +2 -2
  30. package/dist/src/comment/renders/pending.d.ts +2 -2
  31. package/dist/src/comment/renders/reply-at.d.ts +2 -2
  32. package/dist/src/comment/renders/reply-to.d.ts +2 -2
  33. package/dist/src/components/action-btn.d.ts +3 -5
  34. package/dist/src/{lib → components}/checker/admin.d.ts +1 -1
  35. package/dist/src/{lib → components}/checker/captcha-renders.d.ts +1 -1
  36. package/dist/src/{lib → components}/checker/captcha.d.ts +1 -1
  37. package/dist/src/{lib → components}/checker/index.d.ts +10 -7
  38. package/dist/src/components/dark-mode.d.ts +2 -0
  39. package/dist/src/components/dialog.d.ts +1 -3
  40. package/dist/src/components/error-dialog.d.ts +8 -0
  41. package/dist/src/components/pagination.d.ts +4 -3
  42. package/dist/src/components/read-more-btn.d.ts +3 -3
  43. package/dist/src/config.d.ts +24 -8
  44. package/dist/src/context.d.ts +16 -35
  45. package/dist/src/data.d.ts +27 -0
  46. package/dist/src/defaults.d.ts +1 -1
  47. package/dist/src/editor/editor.d.ts +14 -61
  48. package/dist/src/editor/state.d.ts +20 -0
  49. package/dist/src/i18n/zh-CN.d.ts +1 -1
  50. package/dist/src/layer/index.d.ts +4 -3
  51. package/dist/src/layer/layer-manager.d.ts +9 -0
  52. package/dist/src/layer/layer.d.ts +8 -28
  53. package/dist/src/layer/scrollbar-helper.d.ts +5 -0
  54. package/dist/src/layer/sidebar-layer.d.ts +6 -6
  55. package/dist/src/layer/wrap.d.ts +13 -0
  56. package/dist/src/lib/component.d.ts +3 -8
  57. package/dist/src/lib/event-manager.d.ts +28 -0
  58. package/dist/src/lib/highlight.d.ts +1 -0
  59. package/dist/src/lib/marked-renderer.d.ts +4 -0
  60. package/dist/src/lib/marked.d.ts +4 -2
  61. package/dist/src/lib/sanitizer.d.ts +1 -0
  62. package/dist/src/lib/ui.d.ts +3 -2
  63. package/dist/src/lib/user.d.ts +8 -5
  64. package/dist/src/lib/utils.d.ts +11 -5
  65. package/dist/src/list/comment.d.ts +3 -0
  66. package/dist/src/list/layout.d.ts +23 -0
  67. package/dist/src/list/list.d.ts +13 -25
  68. package/dist/src/list/{list-nest.d.ts → nest.d.ts} +1 -1
  69. package/dist/src/list/page.d.ts +2 -0
  70. package/dist/src/list/paginator/index.d.ts +22 -7
  71. package/dist/src/list/paginator/read-more.d.ts +18 -0
  72. package/dist/src/list/paginator/up-down.d.ts +14 -0
  73. package/dist/src/main.d.ts +2 -0
  74. package/dist/src/plugins/admin-only-elem.d.ts +2 -0
  75. package/dist/src/plugins/conf-remoter.d.ts +2 -0
  76. package/dist/src/plugins/dark-mode.d.ts +2 -0
  77. package/dist/src/plugins/editor/_kit.d.ts +27 -0
  78. package/dist/src/plugins/editor/_plug.d.ts +29 -0
  79. package/dist/src/plugins/editor/_sample.d.ts +5 -0
  80. package/dist/src/plugins/editor/closable.d.ts +7 -0
  81. package/dist/src/{editor/plugs/emoticons-plug.d.ts → plugins/editor/emoticons.d.ts} +10 -16
  82. package/dist/src/plugins/editor/header-event.d.ts +6 -0
  83. package/dist/src/plugins/editor/header-link.d.ts +6 -0
  84. package/dist/src/plugins/editor/header-user.d.ts +16 -0
  85. package/dist/src/plugins/editor/index.d.ts +6 -0
  86. package/dist/src/plugins/editor/local-storage.d.ts +6 -0
  87. package/dist/src/plugins/editor/mover.d.ts +6 -0
  88. package/dist/src/plugins/editor/preview.d.ts +7 -0
  89. package/dist/src/plugins/editor/state-edit.d.ts +11 -0
  90. package/dist/src/plugins/editor/state-reply.d.ts +8 -0
  91. package/dist/src/plugins/editor/submit-add.d.ts +18 -0
  92. package/dist/src/plugins/editor/submit-btn.d.ts +5 -0
  93. package/dist/src/plugins/editor/submit.d.ts +17 -0
  94. package/dist/src/plugins/editor/textarea.d.ts +8 -0
  95. package/dist/src/plugins/editor/upload.d.ts +9 -0
  96. package/dist/src/plugins/editor-kit.d.ts +42 -0
  97. package/dist/src/plugins/index.d.ts +2 -0
  98. package/dist/src/plugins/list/copyright.d.ts +2 -0
  99. package/dist/src/plugins/list/count.d.ts +2 -0
  100. package/dist/src/plugins/list/dropdown.d.ts +2 -0
  101. package/dist/src/plugins/list/error-dialog.d.ts +2 -0
  102. package/dist/src/plugins/list/fetch.d.ts +2 -0
  103. package/dist/src/plugins/list/goto-first.d.ts +3 -0
  104. package/dist/src/plugins/list/goto.d.ts +2 -0
  105. package/dist/src/plugins/list/index.d.ts +3 -0
  106. package/dist/src/plugins/list/loading.d.ts +2 -0
  107. package/dist/src/plugins/list/no-comment.d.ts +2 -0
  108. package/dist/src/plugins/list/reach-bottom.d.ts +2 -0
  109. package/dist/src/plugins/list/sidebar-btn.d.ts +2 -0
  110. package/dist/src/plugins/list/time-ticking.d.ts +3 -0
  111. package/dist/src/plugins/list/unread-badge.d.ts +2 -0
  112. package/dist/src/plugins/list/unread.d.ts +2 -0
  113. package/dist/src/plugins/list/with-editor.d.ts +2 -0
  114. package/dist/src/plugins/markdown.d.ts +2 -0
  115. package/dist/src/plugins/stat.d.ts +13 -0
  116. package/dist/src/plugins/version-check.d.ts +2 -0
  117. package/dist/src/service.d.ts +19 -23
  118. package/dist/tests/e2e/comment-add.spec.d.ts +1 -0
  119. package/dist/types/config.d.ts +110 -0
  120. package/dist/types/context.d.ts +56 -136
  121. package/dist/types/data.d.ts +194 -0
  122. package/dist/types/editor.d.ts +76 -0
  123. package/dist/types/event.d.ts +36 -25
  124. package/dist/types/index.d.ts +7 -0
  125. package/dist/types/plugin.d.ts +2 -0
  126. package/dist/types/sidebar.d.ts +3 -0
  127. package/package.json +5 -2
  128. package/src/api/_base.ts +18 -0
  129. package/src/api/_options.ts +25 -0
  130. package/src/api/{request.ts → _request.ts} +19 -18
  131. package/src/api/admin.ts +1 -1
  132. package/src/api/captcha.ts +1 -1
  133. package/src/api/comment.ts +4 -4
  134. package/src/api/index.ts +3 -12
  135. package/src/api/page.ts +5 -5
  136. package/src/api/site.ts +2 -2
  137. package/src/api/system.ts +19 -7
  138. package/src/api/upload.ts +3 -3
  139. package/src/api/user.ts +3 -3
  140. package/src/artalk.ts +49 -97
  141. package/src/comment/actions.ts +1 -4
  142. package/src/comment/comment.ts +9 -6
  143. package/src/comment/render.ts +27 -5
  144. package/src/comment/renders/actions.ts +45 -45
  145. package/src/comment/renders/avatar.ts +7 -7
  146. package/src/comment/renders/content.ts +18 -18
  147. package/src/comment/renders/header.ts +13 -13
  148. package/src/comment/renders/index.ts +3 -3
  149. package/src/comment/renders/pending.ts +5 -5
  150. package/src/comment/renders/reply-at.ts +8 -8
  151. package/src/comment/renders/reply-to.ts +13 -13
  152. package/src/components/action-btn.ts +11 -13
  153. package/src/{lib → components}/checker/admin.ts +6 -6
  154. package/src/{lib → components}/checker/captcha-renders.ts +7 -6
  155. package/src/{lib → components}/checker/captcha.ts +1 -1
  156. package/src/{lib → components}/checker/index.ts +21 -26
  157. package/src/components/dark-mode.ts +30 -0
  158. package/src/components/dialog.ts +4 -9
  159. package/src/components/error-dialog.ts +35 -0
  160. package/src/components/pagination.ts +10 -6
  161. package/src/components/read-more-btn.ts +7 -7
  162. package/src/config.ts +60 -6
  163. package/src/context.ts +39 -144
  164. package/src/data.ts +110 -0
  165. package/src/defaults.ts +1 -1
  166. package/src/editor/editor.ts +39 -152
  167. package/src/editor/state.ts +52 -0
  168. package/src/i18n/zh-CN.ts +1 -1
  169. package/src/layer/index.ts +4 -4
  170. package/src/layer/layer-manager.ts +32 -0
  171. package/src/layer/layer.ts +20 -144
  172. package/src/layer/scrollbar-helper.ts +24 -0
  173. package/src/layer/sidebar-layer.ts +74 -64
  174. package/src/layer/wrap.ts +77 -0
  175. package/src/lib/component.ts +4 -11
  176. package/src/lib/detect.ts +1 -1
  177. package/src/lib/event-manager.ts +47 -0
  178. package/src/lib/highlight.ts +5 -0
  179. package/src/lib/marked-renderer.ts +32 -0
  180. package/src/lib/marked.ts +43 -104
  181. package/src/lib/sanitizer.ts +57 -0
  182. package/src/lib/ui.ts +22 -15
  183. package/src/lib/user.ts +21 -16
  184. package/src/lib/utils.ts +29 -18
  185. package/src/list/comment.ts +20 -0
  186. package/src/list/layout.ts +120 -0
  187. package/src/list/list.html +3 -1
  188. package/src/list/list.ts +56 -200
  189. package/src/list/{list-nest.ts → nest.ts} +1 -1
  190. package/src/list/page.ts +97 -0
  191. package/src/list/paginator/index.ts +20 -8
  192. package/src/list/paginator/read-more.ts +67 -0
  193. package/src/list/paginator/up-down.ts +51 -0
  194. package/src/main.ts +2 -0
  195. package/src/plugins/admin-only-elem.ts +40 -0
  196. package/src/plugins/conf-remoter.ts +54 -0
  197. package/src/plugins/dark-mode.ts +12 -0
  198. package/src/plugins/editor/_kit.ts +57 -0
  199. package/src/plugins/editor/_plug.ts +60 -0
  200. package/src/plugins/editor/_sample.ts +8 -0
  201. package/src/plugins/editor/closable.ts +44 -0
  202. package/src/{editor/plugs/emoticons-plug.ts → plugins/editor/emoticons.ts} +51 -52
  203. package/src/plugins/editor/header-event.ts +35 -0
  204. package/src/plugins/editor/header-link.ts +31 -0
  205. package/src/plugins/editor/header-user.ts +98 -0
  206. package/src/plugins/editor/index.ts +40 -0
  207. package/src/plugins/editor/local-storage.ts +36 -0
  208. package/src/plugins/editor/mover.ts +29 -0
  209. package/src/plugins/editor/preview.ts +41 -0
  210. package/src/plugins/editor/state-edit.ts +116 -0
  211. package/src/plugins/editor/state-reply.ts +91 -0
  212. package/src/plugins/editor/submit-add.ts +33 -0
  213. package/src/plugins/editor/submit-btn.ts +25 -0
  214. package/src/plugins/editor/submit.ts +73 -0
  215. package/src/plugins/editor/textarea.ts +55 -0
  216. package/src/plugins/editor/upload.ts +145 -0
  217. package/src/plugins/editor-kit.ts +161 -0
  218. package/src/plugins/index.ts +16 -0
  219. package/src/plugins/list/copyright.ts +16 -0
  220. package/src/plugins/list/count.ts +31 -0
  221. package/src/plugins/list/dropdown.ts +95 -0
  222. package/src/plugins/list/error-dialog.ts +22 -0
  223. package/src/plugins/list/fetch.ts +64 -0
  224. package/src/plugins/list/goto-first.ts +23 -0
  225. package/src/plugins/list/goto.ts +72 -0
  226. package/src/plugins/list/index.ts +25 -0
  227. package/src/plugins/list/loading.ts +17 -0
  228. package/src/plugins/list/no-comment.ts +25 -0
  229. package/src/plugins/list/reach-bottom.ts +46 -0
  230. package/src/plugins/list/sidebar-btn.ts +39 -0
  231. package/src/plugins/list/time-ticking.ts +22 -0
  232. package/src/plugins/list/unread-badge.ts +26 -0
  233. package/src/plugins/list/unread.ts +38 -0
  234. package/src/plugins/list/with-editor.ts +59 -0
  235. package/src/plugins/markdown.ts +10 -0
  236. package/src/plugins/stat.ts +79 -0
  237. package/src/plugins/version-check.ts +37 -0
  238. package/src/service.ts +34 -61
  239. package/src/style/comment.scss +5 -7
  240. package/src/style/editor.scss +5 -0
  241. package/src/style/list.scss +1 -1
  242. package/types/{artalk-config.d.ts → config.ts} +16 -2
  243. package/types/context.ts +84 -0
  244. package/types/{artalk-data.d.ts → data.ts} +41 -0
  245. package/types/editor.ts +95 -0
  246. package/types/event.ts +40 -0
  247. package/types/index.ts +7 -0
  248. package/types/plugin.ts +3 -0
  249. package/types/sidebar.ts +3 -0
  250. package/dist/src/comment/render-ctx.d.ts +0 -23
  251. package/dist/src/editor/edit-mode.d.ts +0 -9
  252. package/dist/src/editor/funcs.d.ts +0 -2
  253. package/dist/src/editor/index.d.ts +0 -2
  254. package/dist/src/editor/mover.d.ts +0 -8
  255. package/dist/src/editor/plug-manager.d.ts +0 -17
  256. package/dist/src/editor/plugs/editor-plug.d.ts +0 -38
  257. package/dist/src/editor/plugs/header-input-plug.d.ts +0 -13
  258. package/dist/src/editor/plugs/preview-plug.d.ts +0 -10
  259. package/dist/src/editor/plugs/upload-plug.d.ts +0 -10
  260. package/dist/src/editor/reply.d.ts +0 -9
  261. package/dist/src/editor/submit.d.ts +0 -16
  262. package/dist/src/lib/dark-mode.d.ts +0 -4
  263. package/dist/src/lib/stat.d.ts +0 -15
  264. package/dist/src/list/index.d.ts +0 -2
  265. package/dist/src/list/list-lite.d.ts +0 -77
  266. package/dist/src/list/list-ui.d.ts +0 -16
  267. package/dist/src/list/paginator/adaptors/index.d.ts +0 -12
  268. package/dist/src/list/paginator/adaptors/pagination.d.ts +0 -9
  269. package/dist/src/list/paginator/adaptors/read-more.d.ts +0 -10
  270. package/dist/src/list/paginator/holder.d.ts +0 -16
  271. package/dist/types/artalk-config.d.ts +0 -139
  272. package/dist/types/artalk-data.d.ts +0 -230
  273. package/dist/types/plug.d.ts +0 -4
  274. package/src/api/api-base.ts +0 -27
  275. package/src/comment/render-ctx.ts +0 -30
  276. package/src/editor/edit-mode.ts +0 -105
  277. package/src/editor/funcs.ts +0 -150
  278. package/src/editor/index.ts +0 -3
  279. package/src/editor/mover.ts +0 -43
  280. package/src/editor/plug-manager.ts +0 -172
  281. package/src/editor/plugs/editor-plug.ts +0 -69
  282. package/src/editor/plugs/header-input-plug.ts +0 -79
  283. package/src/editor/plugs/preview-plug.ts +0 -44
  284. package/src/editor/plugs/upload-plug.ts +0 -122
  285. package/src/editor/reply.ts +0 -62
  286. package/src/editor/submit.ts +0 -99
  287. package/src/lib/dark-mode.ts +0 -48
  288. package/src/lib/stat.ts +0 -71
  289. package/src/list/index.ts +0 -3
  290. package/src/list/list-lite.ts +0 -424
  291. package/src/list/list-ui.ts +0 -137
  292. package/src/list/paginator/adaptors/index.ts +0 -21
  293. package/src/list/paginator/adaptors/pagination.ts +0 -42
  294. package/src/list/paginator/adaptors/read-more.ts +0 -56
  295. package/src/list/paginator/holder.ts +0 -56
  296. package/types/context.d.ts +0 -142
  297. package/types/event.d.ts +0 -28
  298. package/types/plug.d.ts +0 -4
  299. /package/src/{editor/plugs/emoticons-plug.scss → plugins/editor/emoticons.scss} +0 -0
  300. /package/src/{editor/plugs/preview-plug.scss → plugins/editor/preview.scss} +0 -0
@@ -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 ListLite from '../list-lite'
2
- import PgHolder from './holder'
1
+ import type { ContextApi, ListFetchParams } from '~/types'
2
+ import UpDownPaginator from './up-down'
3
+ import ReadMorePaginator from './read-more'
3
4
 
4
- export type TPgMode = 'pagination'|'read-more'
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 PgHolder
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
@@ -1,3 +1,5 @@
1
1
  import Artalk from './artalk'
2
+ import * as ArtalkType from '../types'
2
3
 
4
+ export { ArtalkType }
3
5
  export default Artalk
@@ -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,8 @@
1
+ import EditorPlug from './_plug'
2
+ import type PlugKit from './_kit'
3
+
4
+ export default class SamplePlug extends EditorPlug {
5
+ constructor(kit: PlugKit) {
6
+ super(kit)
7
+ }
8
+ }
@@ -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
+ }