artalk 2.6.4 → 2.7.1

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 (316) hide show
  1. package/dist/Artalk.css +1 -1
  2. package/dist/Artalk.es.js +7756 -7432
  3. package/dist/Artalk.es.js.map +1 -0
  4. package/dist/Artalk.iife.js +2 -1
  5. package/dist/Artalk.iife.js.map +1 -0
  6. package/dist/Artalk.js +2 -1
  7. package/dist/Artalk.js.map +1 -0
  8. package/dist/ArtalkLite.css +1 -1
  9. package/dist/ArtalkLite.es.js +5576 -5252
  10. package/dist/ArtalkLite.es.js.map +1 -0
  11. package/dist/ArtalkLite.iife.js +2 -1
  12. package/dist/ArtalkLite.iife.js.map +1 -0
  13. package/dist/ArtalkLite.js +2 -1
  14. package/dist/ArtalkLite.js.map +1 -0
  15. package/dist/i18n/jp.js +1 -1
  16. package/dist/i18n/zh-TW.js +1 -1
  17. package/dist/src/api/{api-base.d.ts → _base.d.ts} +3 -7
  18. package/dist/src/api/_options.d.ts +19 -0
  19. package/dist/src/api/{request.d.ts → _request.d.ts} +3 -3
  20. package/dist/src/api/admin.d.ts +1 -1
  21. package/dist/src/api/captcha.d.ts +1 -1
  22. package/dist/src/api/comment.d.ts +2 -2
  23. package/dist/src/api/index.d.ts +2 -4
  24. package/dist/src/api/page.d.ts +3 -3
  25. package/dist/src/api/site.d.ts +2 -2
  26. package/dist/src/api/system.d.ts +13 -3
  27. package/dist/src/api/upload.d.ts +1 -1
  28. package/dist/src/api/user.d.ts +2 -2
  29. package/dist/src/artalk.d.ts +12 -37
  30. package/dist/src/comment/actions.d.ts +1 -1
  31. package/dist/src/comment/comment.d.ts +3 -4
  32. package/dist/src/comment/render.d.ts +21 -3
  33. package/dist/src/comment/renders/actions.d.ts +2 -2
  34. package/dist/src/comment/renders/avatar.d.ts +2 -2
  35. package/dist/src/comment/renders/content.d.ts +2 -2
  36. package/dist/src/comment/renders/header.d.ts +2 -2
  37. package/dist/src/comment/renders/index.d.ts +2 -2
  38. package/dist/src/comment/renders/pending.d.ts +2 -2
  39. package/dist/src/comment/renders/reply-at.d.ts +2 -2
  40. package/dist/src/comment/renders/reply-to.d.ts +2 -2
  41. package/dist/src/components/action-btn.d.ts +3 -5
  42. package/dist/src/{lib → components}/checker/admin.d.ts +1 -1
  43. package/dist/src/{lib → components}/checker/captcha-renders.d.ts +1 -1
  44. package/dist/src/{lib → components}/checker/captcha.d.ts +1 -1
  45. package/dist/src/{lib → components}/checker/index.d.ts +10 -7
  46. package/dist/src/components/dark-mode.d.ts +2 -0
  47. package/dist/src/components/dialog.d.ts +1 -3
  48. package/dist/src/components/error-dialog.d.ts +8 -0
  49. package/dist/src/components/pagination.d.ts +4 -3
  50. package/dist/src/components/read-more-btn.d.ts +3 -3
  51. package/dist/src/config.d.ts +24 -8
  52. package/dist/src/context.d.ts +16 -35
  53. package/dist/src/data.d.ts +27 -0
  54. package/dist/src/defaults.d.ts +1 -1
  55. package/dist/src/editor/editor.d.ts +14 -61
  56. package/dist/src/editor/state.d.ts +20 -0
  57. package/dist/src/i18n/en.d.ts +3 -0
  58. package/dist/src/i18n/external.d.ts +3 -0
  59. package/dist/src/i18n/index.d.ts +9 -0
  60. package/dist/src/i18n/jp.d.ts +3 -0
  61. package/dist/src/i18n/zh-CN.d.ts +1 -1
  62. package/dist/src/i18n/zh-TW.d.ts +3 -0
  63. package/dist/src/layer/index.d.ts +4 -3
  64. package/dist/src/layer/layer-manager.d.ts +9 -0
  65. package/dist/src/layer/layer.d.ts +8 -28
  66. package/dist/src/layer/scrollbar-helper.d.ts +5 -0
  67. package/dist/src/layer/sidebar-layer.d.ts +6 -6
  68. package/dist/src/layer/wrap.d.ts +13 -0
  69. package/dist/src/lib/component.d.ts +3 -8
  70. package/dist/src/lib/event-manager.d.ts +28 -0
  71. package/dist/src/lib/highlight.d.ts +1 -0
  72. package/dist/src/lib/marked-renderer.d.ts +4 -0
  73. package/dist/src/lib/marked.d.ts +4 -2
  74. package/dist/src/lib/sanitizer.d.ts +1 -0
  75. package/dist/src/lib/ui.d.ts +3 -2
  76. package/dist/src/lib/user.d.ts +8 -5
  77. package/dist/src/lib/utils.d.ts +11 -5
  78. package/dist/src/list/comment.d.ts +3 -0
  79. package/dist/src/list/layout.d.ts +23 -0
  80. package/dist/src/list/list.d.ts +13 -25
  81. package/dist/src/list/{list-nest.d.ts → nest.d.ts} +1 -1
  82. package/dist/src/list/page.d.ts +2 -0
  83. package/dist/src/list/paginator/index.d.ts +22 -7
  84. package/dist/src/list/paginator/read-more.d.ts +18 -0
  85. package/dist/src/list/paginator/up-down.d.ts +14 -0
  86. package/dist/src/main.d.ts +5 -0
  87. package/dist/src/plugins/admin-only-elem.d.ts +2 -0
  88. package/dist/src/plugins/conf-remoter.d.ts +2 -0
  89. package/dist/src/plugins/dark-mode.d.ts +2 -0
  90. package/dist/src/plugins/editor/_kit.d.ts +27 -0
  91. package/dist/src/plugins/editor/_plug.d.ts +29 -0
  92. package/dist/src/plugins/editor/_sample.d.ts +5 -0
  93. package/dist/src/plugins/editor/closable.d.ts +7 -0
  94. package/dist/src/{editor/plugs/emoticons-plug.d.ts → plugins/editor/emoticons.d.ts} +10 -16
  95. package/dist/src/plugins/editor/header-event.d.ts +6 -0
  96. package/dist/src/plugins/editor/header-link.d.ts +6 -0
  97. package/dist/src/plugins/editor/header-user.d.ts +16 -0
  98. package/dist/src/plugins/editor/index.d.ts +6 -0
  99. package/dist/src/plugins/editor/local-storage.d.ts +6 -0
  100. package/dist/src/plugins/editor/mover.d.ts +6 -0
  101. package/dist/src/plugins/editor/preview.d.ts +7 -0
  102. package/dist/src/plugins/editor/state-edit.d.ts +11 -0
  103. package/dist/src/plugins/editor/state-reply.d.ts +8 -0
  104. package/dist/src/plugins/editor/submit-add.d.ts +18 -0
  105. package/dist/src/plugins/editor/submit-btn.d.ts +5 -0
  106. package/dist/src/plugins/editor/submit.d.ts +17 -0
  107. package/dist/src/plugins/editor/textarea.d.ts +8 -0
  108. package/dist/src/plugins/editor/upload.d.ts +9 -0
  109. package/dist/src/plugins/editor-kit.d.ts +42 -0
  110. package/dist/src/plugins/index.d.ts +2 -0
  111. package/dist/src/plugins/list/copyright.d.ts +2 -0
  112. package/dist/src/plugins/list/count.d.ts +2 -0
  113. package/dist/src/plugins/list/dropdown.d.ts +2 -0
  114. package/dist/src/plugins/list/error-dialog.d.ts +2 -0
  115. package/dist/src/plugins/list/fetch.d.ts +2 -0
  116. package/dist/src/plugins/list/goto-first.d.ts +3 -0
  117. package/dist/src/plugins/list/goto.d.ts +2 -0
  118. package/dist/src/plugins/list/index.d.ts +3 -0
  119. package/dist/src/plugins/list/loading.d.ts +2 -0
  120. package/dist/src/plugins/list/no-comment.d.ts +2 -0
  121. package/dist/src/plugins/list/reach-bottom.d.ts +2 -0
  122. package/dist/src/plugins/list/sidebar-btn.d.ts +2 -0
  123. package/dist/src/plugins/list/time-ticking.d.ts +3 -0
  124. package/dist/src/plugins/list/unread-badge.d.ts +2 -0
  125. package/dist/src/plugins/list/unread.d.ts +2 -0
  126. package/dist/src/plugins/list/with-editor.d.ts +2 -0
  127. package/dist/src/plugins/markdown.d.ts +2 -0
  128. package/dist/src/plugins/stat.d.ts +13 -0
  129. package/dist/src/plugins/version-check.d.ts +2 -0
  130. package/dist/src/service.d.ts +19 -23
  131. package/dist/tests/e2e/comment-add.spec.d.ts +1 -0
  132. package/dist/types/config.d.ts +110 -0
  133. package/dist/types/context.d.ts +56 -136
  134. package/dist/types/data.d.ts +194 -0
  135. package/dist/types/editor.d.ts +76 -0
  136. package/dist/types/event.d.ts +36 -25
  137. package/dist/types/index.d.ts +7 -0
  138. package/dist/types/plugin.d.ts +2 -0
  139. package/dist/types/sidebar.d.ts +3 -0
  140. package/package.json +5 -2
  141. package/src/api/_base.ts +18 -0
  142. package/src/api/_options.ts +25 -0
  143. package/src/api/{request.ts → _request.ts} +19 -18
  144. package/src/api/admin.ts +1 -1
  145. package/src/api/captcha.ts +1 -1
  146. package/src/api/comment.ts +4 -4
  147. package/src/api/index.ts +3 -12
  148. package/src/api/page.ts +5 -5
  149. package/src/api/site.ts +2 -2
  150. package/src/api/system.ts +19 -7
  151. package/src/api/upload.ts +3 -3
  152. package/src/api/user.ts +3 -3
  153. package/src/artalk.ts +47 -99
  154. package/src/comment/actions.ts +1 -4
  155. package/src/comment/comment.ts +9 -6
  156. package/src/comment/render.ts +27 -5
  157. package/src/comment/renders/actions.ts +45 -45
  158. package/src/comment/renders/avatar.ts +7 -7
  159. package/src/comment/renders/content.ts +18 -18
  160. package/src/comment/renders/header.ts +13 -13
  161. package/src/comment/renders/index.ts +3 -3
  162. package/src/comment/renders/pending.ts +5 -5
  163. package/src/comment/renders/reply-at.ts +8 -8
  164. package/src/comment/renders/reply-to.ts +13 -13
  165. package/src/components/action-btn.ts +11 -13
  166. package/src/{lib → components}/checker/admin.ts +6 -6
  167. package/src/{lib → components}/checker/captcha-renders.ts +7 -6
  168. package/src/{lib → components}/checker/captcha.ts +1 -1
  169. package/src/{lib → components}/checker/index.ts +21 -26
  170. package/src/components/dark-mode.ts +30 -0
  171. package/src/components/dialog.ts +4 -9
  172. package/src/components/error-dialog.ts +35 -0
  173. package/src/components/pagination.ts +10 -6
  174. package/src/components/read-more-btn.ts +7 -7
  175. package/src/config.ts +60 -6
  176. package/src/context.ts +39 -144
  177. package/src/data.ts +110 -0
  178. package/src/defaults.ts +1 -1
  179. package/src/editor/editor.ts +39 -152
  180. package/src/editor/state.ts +52 -0
  181. package/src/i18n/en.ts +3 -0
  182. package/src/i18n/jp.ts +3 -0
  183. package/src/i18n/zh-CN.ts +4 -1
  184. package/src/i18n/zh-TW.ts +3 -0
  185. package/src/layer/index.ts +4 -4
  186. package/src/layer/layer-manager.ts +32 -0
  187. package/src/layer/layer.ts +20 -144
  188. package/src/layer/scrollbar-helper.ts +24 -0
  189. package/src/layer/sidebar-layer.ts +74 -64
  190. package/src/layer/wrap.ts +77 -0
  191. package/src/lib/component.ts +4 -11
  192. package/src/lib/detect.ts +1 -1
  193. package/src/lib/event-manager.ts +47 -0
  194. package/src/lib/highlight.ts +5 -0
  195. package/src/lib/marked-renderer.ts +32 -0
  196. package/src/lib/marked.ts +43 -104
  197. package/src/lib/sanitizer.ts +57 -0
  198. package/src/lib/ui.ts +22 -15
  199. package/src/lib/user.ts +21 -16
  200. package/src/lib/utils.ts +29 -18
  201. package/src/list/comment.ts +20 -0
  202. package/src/list/layout.ts +120 -0
  203. package/src/list/list.html +3 -1
  204. package/src/list/list.ts +56 -200
  205. package/src/list/{list-nest.ts → nest.ts} +1 -1
  206. package/src/list/page.ts +97 -0
  207. package/src/list/paginator/index.ts +20 -8
  208. package/src/list/paginator/read-more.ts +67 -0
  209. package/src/list/paginator/up-down.ts +51 -0
  210. package/src/main.ts +11 -0
  211. package/src/plugins/admin-only-elem.ts +40 -0
  212. package/src/plugins/conf-remoter.ts +54 -0
  213. package/src/plugins/dark-mode.ts +12 -0
  214. package/src/plugins/editor/_kit.ts +57 -0
  215. package/src/plugins/editor/_plug.ts +60 -0
  216. package/src/plugins/editor/_sample.ts +8 -0
  217. package/src/plugins/editor/closable.ts +44 -0
  218. package/src/{editor/plugs/emoticons-plug.ts → plugins/editor/emoticons.ts} +51 -52
  219. package/src/plugins/editor/header-event.ts +35 -0
  220. package/src/plugins/editor/header-link.ts +31 -0
  221. package/src/plugins/editor/header-user.ts +98 -0
  222. package/src/plugins/editor/index.ts +40 -0
  223. package/src/plugins/editor/local-storage.ts +36 -0
  224. package/src/plugins/editor/mover.ts +29 -0
  225. package/src/plugins/editor/preview.ts +41 -0
  226. package/src/plugins/editor/state-edit.ts +116 -0
  227. package/src/plugins/editor/state-reply.ts +91 -0
  228. package/src/plugins/editor/submit-add.ts +33 -0
  229. package/src/plugins/editor/submit-btn.ts +25 -0
  230. package/src/plugins/editor/submit.ts +73 -0
  231. package/src/plugins/editor/textarea.ts +55 -0
  232. package/src/plugins/editor/upload.ts +145 -0
  233. package/src/plugins/editor-kit.ts +161 -0
  234. package/src/plugins/index.ts +16 -0
  235. package/src/plugins/list/copyright.ts +16 -0
  236. package/src/plugins/list/count.ts +31 -0
  237. package/src/plugins/list/dropdown.ts +95 -0
  238. package/src/plugins/list/error-dialog.ts +22 -0
  239. package/src/plugins/list/fetch.ts +64 -0
  240. package/src/plugins/list/goto-first.ts +23 -0
  241. package/src/plugins/list/goto.ts +72 -0
  242. package/src/plugins/list/index.ts +25 -0
  243. package/src/plugins/list/loading.ts +17 -0
  244. package/src/plugins/list/no-comment.ts +25 -0
  245. package/src/plugins/list/reach-bottom.ts +46 -0
  246. package/src/plugins/list/sidebar-btn.ts +39 -0
  247. package/src/plugins/list/time-ticking.ts +22 -0
  248. package/src/plugins/list/unread-badge.ts +26 -0
  249. package/src/plugins/list/unread.ts +38 -0
  250. package/src/plugins/list/with-editor.ts +59 -0
  251. package/src/plugins/markdown.ts +10 -0
  252. package/src/plugins/stat.ts +82 -0
  253. package/src/plugins/version-check.ts +36 -0
  254. package/src/service.ts +34 -61
  255. package/src/style/comment.scss +5 -7
  256. package/src/style/editor.scss +5 -0
  257. package/src/style/list.scss +1 -1
  258. package/types/{artalk-config.d.ts → config.ts} +16 -2
  259. package/types/context.ts +84 -0
  260. package/types/{artalk-data.d.ts → data.ts} +41 -0
  261. package/types/editor.ts +95 -0
  262. package/types/event.ts +40 -0
  263. package/types/index.ts +7 -0
  264. package/types/plugin.ts +3 -0
  265. package/types/sidebar.ts +3 -0
  266. package/dist/src/comment/render-ctx.d.ts +0 -23
  267. package/dist/src/editor/edit-mode.d.ts +0 -9
  268. package/dist/src/editor/funcs.d.ts +0 -2
  269. package/dist/src/editor/index.d.ts +0 -2
  270. package/dist/src/editor/mover.d.ts +0 -8
  271. package/dist/src/editor/plug-manager.d.ts +0 -17
  272. package/dist/src/editor/plugs/editor-plug.d.ts +0 -38
  273. package/dist/src/editor/plugs/header-input-plug.d.ts +0 -13
  274. package/dist/src/editor/plugs/preview-plug.d.ts +0 -10
  275. package/dist/src/editor/plugs/upload-plug.d.ts +0 -10
  276. package/dist/src/editor/reply.d.ts +0 -9
  277. package/dist/src/editor/submit.d.ts +0 -16
  278. package/dist/src/lib/dark-mode.d.ts +0 -4
  279. package/dist/src/lib/stat.d.ts +0 -15
  280. package/dist/src/list/index.d.ts +0 -2
  281. package/dist/src/list/list-lite.d.ts +0 -77
  282. package/dist/src/list/list-ui.d.ts +0 -16
  283. package/dist/src/list/paginator/adaptors/index.d.ts +0 -12
  284. package/dist/src/list/paginator/adaptors/pagination.d.ts +0 -9
  285. package/dist/src/list/paginator/adaptors/read-more.d.ts +0 -10
  286. package/dist/src/list/paginator/holder.d.ts +0 -16
  287. package/dist/types/artalk-config.d.ts +0 -139
  288. package/dist/types/artalk-data.d.ts +0 -230
  289. package/dist/types/plug.d.ts +0 -4
  290. package/src/api/api-base.ts +0 -27
  291. package/src/comment/render-ctx.ts +0 -30
  292. package/src/editor/edit-mode.ts +0 -105
  293. package/src/editor/funcs.ts +0 -150
  294. package/src/editor/index.ts +0 -3
  295. package/src/editor/mover.ts +0 -43
  296. package/src/editor/plug-manager.ts +0 -172
  297. package/src/editor/plugs/editor-plug.ts +0 -69
  298. package/src/editor/plugs/header-input-plug.ts +0 -79
  299. package/src/editor/plugs/preview-plug.ts +0 -44
  300. package/src/editor/plugs/upload-plug.ts +0 -122
  301. package/src/editor/reply.ts +0 -62
  302. package/src/editor/submit.ts +0 -99
  303. package/src/lib/dark-mode.ts +0 -48
  304. package/src/lib/stat.ts +0 -71
  305. package/src/list/index.ts +0 -3
  306. package/src/list/list-lite.ts +0 -424
  307. package/src/list/list-ui.ts +0 -137
  308. package/src/list/paginator/adaptors/index.ts +0 -21
  309. package/src/list/paginator/adaptors/pagination.ts +0 -42
  310. package/src/list/paginator/adaptors/read-more.ts +0 -56
  311. package/src/list/paginator/holder.ts +0 -56
  312. package/types/context.d.ts +0 -142
  313. package/types/event.d.ts +0 -28
  314. package/types/plug.d.ts +0 -4
  315. /package/src/{editor/plugs/emoticons-plug.scss → plugins/editor/emoticons.scss} +0 -0
  316. /package/src/{editor/plugs/preview-plug.scss → plugins/editor/preview.scss} +0 -0
package/src/list/list.ts CHANGED
@@ -1,223 +1,79 @@
1
- import { ListData, NotifyData } from '~/types/artalk-data'
2
- import Context from '~/types/context'
3
- import { version as ARTALK_VERSION } from '../../package.json'
1
+ import type { ContextApi } from '~/types'
2
+ import Component from '../lib/component'
4
3
  import * as Utils from '../lib/utils'
5
- import * as Ui from '../lib/ui'
6
- import User from '../lib/user'
4
+ import CommentNode from '../comment/comment'
7
5
  import ListHTML from './list.html?raw'
8
- import ListLite from './list-lite'
9
- import * as ListUi from './list-ui'
6
+ import ListLayout from './layout'
7
+ import { createComment as createCommentNode } from './comment'
8
+ import { initListPaginatorFunc } from './page'
10
9
 
11
- export default class List extends ListLite {
12
- private $closeCommentBtn!: HTMLElement
13
- private $openSidebarBtn!: HTMLElement
14
- private $unreadBadge!: HTMLElement
15
- private $commentCount!: HTMLElement
16
- private $commentCountNum!: HTMLElement
17
- private $dropdownWrap?: HTMLElement
10
+ export default class List extends Component {
11
+ /** 列表评论集区域元素 */
12
+ $commentsWrap!: HTMLElement
13
+ public getCommentsWrapEl() { return this.$commentsWrap }
18
14
 
19
- constructor (ctx: Context) {
20
- const el = Utils.createElement(ListHTML)
15
+ protected commentNodes: CommentNode[] = []
16
+ getCommentNodes() { return this.commentNodes }
21
17
 
18
+ constructor (ctx: ContextApi) {
22
19
  super(ctx)
23
20
 
24
- // 把 listLite $el 变为子元素
25
- el.querySelector('.atk-list-body')!.append(this.$el)
26
- this.$el = el
21
+ // Init base element
22
+ this.$el = Utils.createElement(ListHTML)
23
+ this.$commentsWrap = this.$el.querySelector('.atk-list-comments-wrap')!
27
24
 
28
- // 分页模式
29
- this.repositionAt = this.$el
25
+ // Init paginator
26
+ initListPaginatorFunc(ctx)
30
27
 
31
- // 操作按钮
32
- this.initListActionBtn()
33
-
34
- const countNumHTML = '<span class="atk-comment-count-num">0</span>'
35
- this.$commentCount = this.$el.querySelector('.atk-comment-count')!
36
-
37
- const refreshCountNumEl = () => {
38
- this.$commentCount.innerHTML = this.$t('counter', {
39
- count: countNumHTML,
40
- })
41
- this.$commentCountNum = this.$commentCount.querySelector('.atk-comment-count-num')!
42
- }
43
- refreshCountNumEl()
44
-
45
- // copyright
46
- this.$el.querySelector<HTMLElement>('.atk-copyright')!.innerHTML = `Powered By <a href="https://artalk.js.org" target="_blank" title="Artalk v${ARTALK_VERSION}">Artalk</a>`
28
+ // Bind events
29
+ this.initCrudEvents()
30
+ }
47
31
 
48
- // event listen
49
- this.ctx.on('conf-loaded', () => {
50
- // i18n support when locale changed
51
- refreshCountNumEl()
52
- this.refreshUI()
32
+ getListLayout() {
33
+ return new ListLayout({
34
+ $commentsWrap: this.$commentsWrap,
35
+ nestSortBy: this.ctx.conf.nestSort,
36
+ nestMax: this.ctx.conf.nestMax,
37
+ flatMode: this.ctx.conf.flatMode as boolean,
38
+ // flatMode must be boolean because it had been handled when Artalk.init
39
+ createCommentNode: (d, c) => {
40
+ const node = createCommentNode(this.ctx, d, c)
41
+ this.commentNodes.push(node)
42
+ return node
43
+ },
44
+ findCommentNode: (id) => this.commentNodes.find(c => c.getID() === id),
45
+ getCommentDataList: () => this.ctx.getData().getComments(),
53
46
  })
54
47
  }
55
48
 
56
- private initListActionBtn() {
57
- // 侧边栏呼出按钮
58
- this.$openSidebarBtn = this.$el.querySelector('[data-action="open-sidebar"]')!
59
- this.$closeCommentBtn = this.$el.querySelector('[data-action="admin-close-comment"]')!
60
- this.$unreadBadge = this.$el.querySelector('.atk-unread-badge')!
61
-
62
- this.$openSidebarBtn.addEventListener('click', () => {
63
- this.ctx.showSidebar()
49
+ private initCrudEvents() {
50
+ this.ctx.on('list-load', (comments) => {
51
+ // 导入数据
52
+ this.getListLayout().import(comments)
64
53
  })
65
54
 
66
- // 关闭评论按钮
67
- this.$closeCommentBtn.addEventListener('click', () => {
68
- if (!this.data) return
69
-
70
- this.data.page.admin_only = !this.data.page.admin_only
71
- this.adminPageEditSave()
55
+ this.ctx.on('list-loaded', (comments) => {
56
+ if (comments.length === 0) this.$commentsWrap.innerHTML = ''
72
57
  })
73
- }
74
-
75
- /** 刷新界面 */
76
- public refreshUI() {
77
- super.refreshUI()
78
-
79
- this.$commentCountNum.innerText = String(Number(this.data?.total) || 0)
80
-
81
- // 已输入个人信息
82
- if (!!User.data.nick && !!User.data.email) {
83
- this.$openSidebarBtn.classList.remove('atk-hide')
84
- } else {
85
- this.$openSidebarBtn.classList.add('atk-hide')
86
- }
87
-
88
- this.$openSidebarBtn.querySelector<HTMLElement>('.atk-text')!
89
- .innerText = (!User.data.isAdmin) ? this.$t('msgCenter') : this.$t('ctrlCenter')
90
-
91
- // 关闭评论
92
- if (!!this.data && !!this.data.page && this.data.page.admin_only === true) {
93
- this.ctx.editorClose()
94
- this.$closeCommentBtn.innerHTML = this.$t('openComment')
95
- } else {
96
- this.ctx.editorOpen()
97
- this.$closeCommentBtn.innerHTML = this.$t('closeComment')
98
- }
99
-
100
- // 评论列表排序 Dropdown 下拉选择层
101
- if (this.ctx.conf.listSort) {
102
- this.initDropdown()
103
- } else {
104
- ListUi.removeDropdown({
105
- $dropdownWrap: this.$commentCount
106
- })
107
- }
108
- }
109
-
110
- protected onLoad(data: ListData, offset: number) {
111
- super.onLoad(data, offset)
112
-
113
- // 检测锚点跳转
114
- if (!this.goToCommentFounded) this.checkGoToCommentByUrlHash()
115
-
116
- // 防止评论框被吞
117
- if (this.ctx.conf.editorTravel === true) {
118
- this.ctx.editorTravelBack()
119
- }
120
- }
121
58
 
122
- private goToCommentFounded = false
123
- public goToCommentDelay = true
124
-
125
- /** 跳到评论项位置 - 根据 `location.hash` */
126
- public checkGoToCommentByUrlHash() {
127
- let commentId = Number(Utils.getQueryParam('atk_comment')) // same as backend GetReplyLink()
128
- if (!commentId) {
129
- const match = window.location.hash.match(/#atk-comment-([0-9]+)/)
130
- if (!match || !match[1] || Number.isNaN(Number(match[1]))) return
131
- commentId = Number(match[1])
132
- }
133
- if (!commentId) return
134
-
135
- const comment = this.ctx.findComment(commentId)
136
- if (!comment) { // 若找不到评论
137
- // 自动翻页
138
- this.pgHolder?.next()
139
- return
140
- }
141
-
142
- // 已阅 API
143
- const notifyKey = Utils.getQueryParam('atk_notify_key')
144
- if (notifyKey) {
145
- this.ctx.getApi().user.markRead(commentId, notifyKey)
146
- .then(() => {
147
- this.unread = this.unread.filter(o => o.comment_id !== commentId)
148
- this.updateUnread(this.unread)
149
- })
150
- }
151
-
152
- // 若父评论存在 “子评论部分” 限高,取消限高
153
- comment.getParents().forEach((p) => {
154
- p.getRender().heightLimitRemoveForChildren()
59
+ // When comment insert
60
+ this.ctx.on('comment-inserted', (comment) => {
61
+ this.getListLayout().insert(comment)
155
62
  })
156
63
 
157
- const goTo = () => {
158
- Ui.scrollIntoView(comment.getEl(), false)
159
-
160
- comment.getEl().classList.remove('atk-flash-once')
161
- window.setTimeout(() => {
162
- comment.getEl().classList.add('atk-flash-once')
163
- }, 150)
164
- }
165
-
166
- if (!this.goToCommentDelay) goTo()
167
- else window.setTimeout(() => goTo(), 350)
168
-
169
- this.goToCommentFounded = true
170
- this.goToCommentDelay = true // reset
171
- }
172
-
173
- /** 管理员设置页面信息 */
174
- public adminPageEditSave () {
175
- if (!this.data || !this.data.page) return
176
-
177
- this.ctx.editorShowLoading()
178
- this.ctx.getApi().page.pageEdit(this.data.page)
179
- .then((page) => {
180
- if (this.data)
181
- this.data.page = { ...page }
182
- this.refreshUI()
183
- })
184
- .catch(err => {
185
- this.ctx.editorShowNotify(`${this.$t('editFail')}: ${err.msg || String(err)}`, 'e')
186
- })
187
- .finally(() => {
188
- this.ctx.editorHideLoading()
189
- })
190
- }
191
-
192
- public showUnreadBadge(count: number) {
193
- if (count > 0) {
194
- this.$unreadBadge.innerText = `${Number(count || 0)}`
195
- this.$unreadBadge.style.display = 'block'
196
- } else {
197
- this.$unreadBadge.style.display = 'none'
198
- }
199
- }
200
-
201
- /** 初始化选择下拉层 */
202
- protected initDropdown() {
203
- const reloadUseParamsEditor = (func: (p: any) => void) => {
204
- this.paramsEditor = func
205
- this.fetchComments(0)
206
- }
207
-
208
- ListUi.renderDropdown({
209
- $dropdownWrap: this.$commentCount,
210
- dropdownList: [
211
- [this.$t('sortLatest'), () => { reloadUseParamsEditor(p => { p.sort_by = 'date_desc' }) }],
212
- [this.$t('sortBest'), () => { reloadUseParamsEditor(p => { p.sort_by = 'vote' }) }],
213
- [this.$t('sortOldest'), () => { reloadUseParamsEditor(p => { p.sort_by = 'date_asc' }) }],
214
- [this.$t('sortAuthor'), () => { reloadUseParamsEditor(p => { p.view_only_admin = true }) }],
215
- ]
64
+ // When comment delete
65
+ this.ctx.on('comment-deleted', (comment) => {
66
+ const node = this.commentNodes.find(c => c.getID() === comment.id)
67
+ if (!node) { console.error(`comment node id=${comment.id} not found`);return }
68
+ node.getEl().remove()
69
+ this.commentNodes = this.commentNodes.filter(c => c.getID() !== comment.id)
70
+ // TODO remove child nodes
216
71
  })
217
- }
218
72
 
219
- public updateUnread(notifies: NotifyData[]): void {
220
- super.updateUnread(notifies)
221
- this.showUnreadBadge(notifies?.length || 0)
73
+ // When comment update
74
+ this.ctx.on('comment-updated', (comment) => {
75
+ const node = this.commentNodes.find(c => c.getID() === comment.id)
76
+ node && node.setData(comment)
77
+ })
222
78
  }
223
79
  }
@@ -1,4 +1,4 @@
1
- import { CommentData } from '~/types/artalk-data'
1
+ import type { CommentData } from '~/types'
2
2
 
3
3
  export type CommentNode = {
4
4
  id: number
@@ -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,14 @@
1
1
  import Artalk from './artalk'
2
+ import * as ArtalkType from '../types'
2
3
 
4
+ export { ArtalkType }
3
5
  export default Artalk
6
+
7
+ // Expose the static methods from the Artalk class
8
+ // because direct export of static methods is not supported
9
+ // for adapting to different environments like CommonJS and browser IIFE
10
+ // for example, we can use `Artalk.init()` rather than `Artalk.default.init()`
11
+ // therefore, we need to manually expose the static methods in the Artalk class.
12
+ export const init = Artalk.init
13
+ export const use = Artalk.use
14
+ export const loadCountWidget = Artalk.loadCountWidget
@@ -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
+ }