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.
Files changed (300) hide show
  1. package/dist/Artalk.css +1 -1
  2. package/dist/Artalk.es.js +7673 -7330
  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 +5304 -4961
  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 -59
  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 +41 -146
  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 +2 -7
  242. package/types/{artalk-config.d.ts → config.ts} +16 -2
  243. package/types/context.ts +84 -0
  244. package/{dist/types/artalk-data.d.ts → types/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/plug.d.ts +0 -4
  273. package/src/api/api-base.ts +0 -27
  274. package/src/comment/render-ctx.ts +0 -30
  275. package/src/editor/edit-mode.ts +0 -103
  276. package/src/editor/funcs.ts +0 -97
  277. package/src/editor/index.ts +0 -3
  278. package/src/editor/mover.ts +0 -43
  279. package/src/editor/plug-manager.ts +0 -172
  280. package/src/editor/plugs/editor-plug.ts +0 -69
  281. package/src/editor/plugs/header-input-plug.ts +0 -79
  282. package/src/editor/plugs/preview-plug.ts +0 -44
  283. package/src/editor/plugs/upload-plug.ts +0 -122
  284. package/src/editor/reply.ts +0 -62
  285. package/src/editor/submit.ts +0 -99
  286. package/src/lib/dark-mode.ts +0 -48
  287. package/src/lib/stat.ts +0 -71
  288. package/src/list/index.ts +0 -3
  289. package/src/list/list-lite.ts +0 -424
  290. package/src/list/list-ui.ts +0 -137
  291. package/src/list/paginator/adaptors/index.ts +0 -21
  292. package/src/list/paginator/adaptors/pagination.ts +0 -42
  293. package/src/list/paginator/adaptors/read-more.ts +0 -56
  294. package/src/list/paginator/holder.ts +0 -56
  295. package/types/artalk-data.d.ts +0 -230
  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
package/src/data.ts ADDED
@@ -0,0 +1,110 @@
1
+ import type { NotifyData, PageData, CommentData, DataManagerApi, ListFetchParams, ListLastFetchData, EventPayloadMap } from '~/types'
2
+ import EventManager from './lib/event-manager'
3
+
4
+ export class DataManager implements DataManagerApi {
5
+ private loading: boolean = false
6
+ private listLastFetch?: ListLastFetchData
7
+ private comments: CommentData[] = [] // Note: 无层级结构 + 无须排列
8
+ private unreads: NotifyData[] = []
9
+ private page?: PageData
10
+
11
+ constructor(
12
+ protected events: EventManager<EventPayloadMap>
13
+ ) {}
14
+
15
+ getLoading() {
16
+ return this.loading
17
+ }
18
+
19
+ setLoading(val: boolean) {
20
+ this.loading = val
21
+ }
22
+
23
+ getListLastFetch() {
24
+ return this.listLastFetch
25
+ }
26
+
27
+ setListLastFetch(val: ListLastFetchData) {
28
+ this.listLastFetch = val
29
+ }
30
+
31
+ // -------------------------------------------------------------------
32
+ // Comments
33
+ // -------------------------------------------------------------------
34
+ getComments() {
35
+ return this.comments
36
+ }
37
+
38
+ fetchComments(params: Partial<ListFetchParams>) {
39
+ this.events.trigger('list-fetch', params)
40
+ }
41
+
42
+ findComment(id: number) {
43
+ return this.comments.find(c => c.id === id)
44
+ }
45
+
46
+ clearComments() {
47
+ this.comments = []
48
+ this.events.trigger('list-loaded', this.comments)
49
+ }
50
+
51
+ loadComments(partialComments: CommentData[]) {
52
+ this.events.trigger('list-load', partialComments)
53
+
54
+ this.comments.push(...partialComments)
55
+
56
+ this.events.trigger('list-loaded', this.comments)
57
+ }
58
+
59
+ insertComment(comment: CommentData) {
60
+ this.comments.push(comment)
61
+
62
+ this.events.trigger('comment-inserted', comment)
63
+ this.events.trigger('list-loaded', this.comments) // list-loaded should always keep the last
64
+ }
65
+
66
+ updateComment(comment: CommentData) {
67
+ this.comments = this.comments.map(c => {
68
+ if (c.id === comment.id) return comment
69
+ return c
70
+ })
71
+
72
+ this.events.trigger('comment-updated', comment)
73
+ this.events.trigger('list-loaded', this.comments)
74
+ }
75
+
76
+ deleteComment(id: number) {
77
+ const comment = this.comments.find(c => c.id === id)
78
+ if (!comment) throw new Error(`Comment ${id} not found`)
79
+ this.comments = this.comments.filter(c => c.id !== id)
80
+
81
+ this.events.trigger('comment-deleted', comment)
82
+ this.events.trigger('list-loaded', this.comments)
83
+ }
84
+
85
+ // -------------------------------------------------------------------
86
+ // Unreads
87
+ // -------------------------------------------------------------------
88
+ getUnreads() {
89
+ return this.unreads
90
+ }
91
+
92
+ updateUnreads(unread: NotifyData[]) {
93
+ this.unreads = unread
94
+
95
+ this.events.trigger('unreads-updated', this.unreads)
96
+ }
97
+
98
+ // -------------------------------------------------------------------
99
+ // Page
100
+ // -------------------------------------------------------------------
101
+ getPage() {
102
+ return this.page
103
+ }
104
+
105
+ updatePage(pageData: PageData) {
106
+ this.page = pageData
107
+
108
+ this.events.trigger('page-loaded', pageData)
109
+ }
110
+ }
package/src/defaults.ts CHANGED
@@ -1,4 +1,4 @@
1
- import ArtalkConfig from "~/types/artalk-config"
1
+ import type { ArtalkConfig } from '~/types'
2
2
 
3
3
  const defaults: ArtalkConfig = {
4
4
  el: '',
@@ -1,106 +1,59 @@
1
- import type { CommentData } from '~/types/artalk-data'
2
- import type Context from '~/types/context'
1
+ import type { CommentData, ContextApi, EditorApi } from '~/types'
3
2
  import Component from '../lib/component'
4
- import * as Utils from '../lib/utils'
5
3
  import * as Ui from '../lib/ui'
6
4
  import marked from '../lib/marked'
7
- import User from '../lib/user'
8
- import initEditorFuncs from './funcs'
9
5
  import { render, EditorUI } from './ui'
10
- import { PlugManager } from './plug-manager'
11
- import { Mover } from './mover'
12
- import { ReplyManager } from './reply'
13
- import { EditModeManager } from './edit-mode'
14
- import { SubmitManager } from './submit'
15
-
16
- export default class Editor extends Component {
17
- /** 界面 */
6
+ import EditorStateManager from './state'
7
+
8
+ class Editor extends Component implements EditorApi {
18
9
  private ui: EditorUI
19
- public getUI() { return this.ui }
20
-
21
- /** 插件管理器 */
22
- private plugs?: PlugManager
23
- public getPlugs() { return this.plugs }
24
- public setPlugs(p: PlugManager) { this.plugs = p }
25
-
26
- /** 评论框移动 */
27
- private mover?: Mover
28
- public setMover(m: Mover) { this.mover = m }
29
-
30
- /** 回复评论 */
31
- private reply?: ReplyManager
32
- public setReplyManager(m: ReplyManager) { this.reply = m }
33
- public getReplyManager() { return this.reply }
34
- public get isReplyMode() { return !!this.reply?.comment }
35
-
36
- /** 编辑评论 */
37
- private editMode?: EditModeManager
38
- public setEditModeManager(m: EditModeManager) { this.editMode = m }
39
- public get isEditMode() { return !!this.editMode?.comment }
40
-
41
- /** 提交评论 */
42
- private submitManager?: SubmitManager
43
- public setSubmitManager(m: SubmitManager) { this.submitManager = m }
44
- public getSubmitManager() { return this.submitManager }
45
-
46
- public constructor(ctx: Context) {
10
+ private state: EditorStateManager
11
+
12
+ getUI() { return this.ui }
13
+ getPlugs() { return this.ctx.get('editorPlugs') }
14
+ getState() { return this.state.get() }
15
+
16
+ constructor(ctx: ContextApi) {
47
17
  super(ctx)
48
18
 
49
19
  // init editor ui
50
20
  this.ui = render()
51
21
  this.$el = this.ui.$el
52
22
 
53
- // event listen
54
- this.ctx.on('conf-loaded', () => {
55
- initEditorFuncs(this) // init editor funcs
56
- })
23
+ // init state manager
24
+ this.state = new EditorStateManager(this)
57
25
  }
58
26
 
59
- public getHeaderInputEls() {
27
+ getHeaderInputEls() {
60
28
  return { nick: this.ui.$nick, email: this.ui.$email, link: this.ui.$link }
61
29
  }
62
30
 
63
- public saveToLocalStorage() {
64
- window.localStorage.setItem('ArtalkContent', this.getContentOriginal().trim())
65
- }
66
-
67
- public refreshSendBtnText() {
68
- if (this.isEditMode) this.ui.$submitBtn.innerText = this.$t('save')
69
- else this.ui.$submitBtn.innerText = this.ctx.conf.sendBtn || this.$t('send')
70
- }
71
-
72
- /** 最终用于 submit 的数据 */
73
- public getFinalContent() {
74
- let content = this.getContentOriginal()
31
+ getContentFinal() {
32
+ let content = this.getContentRaw()
75
33
 
76
34
  // plug hook: final content transformer
77
- if (this.plugs) content = this.plugs.getTransformedContent(content)
35
+ const plugs = this.getPlugs()
36
+ if (plugs) content = plugs.getTransformedContent(content)
78
37
 
79
38
  return content
80
39
  }
81
40
 
82
- public getContentOriginal() {
83
- return this.ui.$textarea.value || '' // Tip: !!"0" === true
41
+ getContentRaw() {
42
+ return this.ui.$textarea.value || ''
84
43
  }
85
44
 
86
- public getContentMarked() {
87
- return marked(this.ctx, this.getFinalContent())
45
+ getContentMarked() {
46
+ return marked(this.getContentFinal())
88
47
  }
89
48
 
90
- public setContent(val: string) {
49
+ setContent(val: string) {
91
50
  this.ui.$textarea.value = val
92
- this.saveToLocalStorage()
93
51
 
94
52
  // plug hook: content updated
95
- if (this.plugs) this.plugs.triggerContentUpdatedEvt(val)
96
-
97
- // 延迟执行防止无效
98
- window.setTimeout(() => {
99
- this.adjustTextareaHeight()
100
- }, 80)
53
+ this.getPlugs()?.getEvents().trigger('content-updated', val)
101
54
  }
102
55
 
103
- public insertContent(val: string) {
56
+ insertContent(val: string) {
104
57
  if ((document as any).selection) {
105
58
  this.ui.$textarea.focus();
106
59
  (document as any).selection.createRange().text = val
@@ -120,100 +73,42 @@ export default class Editor extends Component {
120
73
  }
121
74
  }
122
75
 
123
- public adjustTextareaHeight() {
124
- const diff = this.ui.$textarea.offsetHeight - this.ui.$textarea.clientHeight
125
- this.ui.$textarea.style.height = '0px' // it's a magic. 若不加此行,内容减少,高度回不去
126
- this.ui.$textarea.style.height = `${this.ui.$textarea.scrollHeight + diff}px`
127
- }
128
-
129
- public focus() {
76
+ focus() {
130
77
  this.ui.$textarea.focus()
131
78
  }
132
79
 
133
- public reset() {
80
+ reset() {
134
81
  this.setContent('')
135
- this.cancelReply()
136
- this.cancelEditComment()
82
+ this.resetState()
137
83
  }
138
84
 
139
- /** 设置回复评论 */
140
- public setReply(commentData: CommentData, $comment: HTMLElement, scroll = true) {
141
- this.reply?.setReply(commentData, $comment, scroll)
85
+ resetState() {
86
+ this.state.switch('normal')
142
87
  }
143
88
 
144
- /** 取消回复评论 */
145
- public cancelReply() {
146
- this.reply?.cancelReply()
89
+ setReply(comment: CommentData, $comment: HTMLElement) {
90
+ this.state.switch('reply', { comment, $comment })
147
91
  }
148
92
 
149
- /** 设置编辑评论 */
150
- public setEditComment(commentData: CommentData, $comment: HTMLElement) {
151
- this.editMode?.setEdit(commentData, $comment)
93
+ setEditComment(comment: CommentData, $comment: HTMLElement) {
94
+ this.state.switch('edit', { comment, $comment })
152
95
  }
153
96
 
154
- /** 取消编辑评论 */
155
- public cancelEditComment() {
156
- this.editMode?.cancelEdit()
157
- }
158
-
159
- public showNotify(msg: string, type: "i"|"s"|"w"|"e") {
97
+ showNotify(msg: string, type: any) {
160
98
  Ui.showNotify(this.ui.$notifyWrap, msg, type)
161
99
  }
162
100
 
163
- public showLoading() {
101
+ showLoading() {
164
102
  Ui.showLoading(this.ui.$el)
165
103
  }
166
104
 
167
- public hideLoading() {
105
+ hideLoading() {
168
106
  Ui.hideLoading(this.ui.$el)
169
107
  }
170
108
 
171
- /** 点击评论提交按钮事件 */
172
- public async submit() {
173
- if (!this.submitManager) return
174
- await this.submitManager.do()
175
- }
176
-
177
- /** 关闭评论 */
178
- public close() {
179
- if (!this.ui.$textareaWrap.querySelector('.atk-comment-closed'))
180
- this.ui.$textareaWrap.prepend(Utils.createElement(`<div class="atk-comment-closed">${this.$t('onlyAdminCanReply')}</div>`))
181
-
182
- if (!User.data.isAdmin) {
183
- this.ui.$textarea.style.display = 'none'
184
- this.closePlugPanel()
185
- this.ui.$bottom.style.display = 'none'
186
- } else {
187
- // 管理员一直打开评论
188
- this.ui.$textarea.style.display = ''
189
- this.ui.$bottom.style.display = ''
190
- }
191
- }
192
-
193
- /** 打开评论 */
194
- public open() {
195
- this.ui.$textareaWrap.querySelector('.atk-comment-closed')?.remove()
196
- this.ui.$textarea.style.display = ''
197
- this.ui.$bottom.style.display = ''
198
- }
199
-
200
- /** 移动评论框到置顶元素之后 */
201
- public travel($afterEl: HTMLElement) {
202
- this.mover?.move($afterEl)
203
- }
204
-
205
- /** 评论框归位 */
206
- public travelBack() {
207
- this.mover?.back()
208
- }
209
-
210
- /** 展开插件面板 */
211
- public openPlugPanel(plugName: string) {
212
- this.plugs?.openPlugPanel(plugName)
213
- }
214
-
215
- /** 收起插件面板 */
216
- public closePlugPanel() {
217
- this.plugs?.closePlugPanel()
109
+ submit() {
110
+ this.ctx.trigger('editor-submit')
218
111
  }
219
112
  }
113
+
114
+ export default Editor
@@ -0,0 +1,52 @@
1
+ import type { EditorState, CommentData } from '~/types'
2
+ import * as Ui from '@/lib/ui'
3
+ import type Editor from './editor'
4
+ import Mover from '../plugins/editor/mover'
5
+
6
+ export default class EditorStateManager {
7
+ constructor(private editor: Editor) {}
8
+
9
+ private stateCurt: EditorState = 'normal'
10
+ private stateUnmountFn: (() => void)|null = null
11
+
12
+ /** Get current state */
13
+ get() {
14
+ return this.stateCurt
15
+ }
16
+
17
+ /**
18
+ * Switch editor state
19
+ *
20
+ * @param state The state to switch
21
+ * @param payload The cause of state switch
22
+ */
23
+ switch(state: EditorState, payload?: { $comment: HTMLElement, comment: CommentData }) {
24
+ // trigger unmount
25
+ if (this.stateUnmountFn) {
26
+ this.stateUnmountFn()
27
+ this.stateUnmountFn = null
28
+
29
+ // move editor back to the initial position
30
+ this.editor.getPlugs()?.get(Mover)?.back()
31
+ }
32
+
33
+ // invoke effect function and save unmount function
34
+ if (state !== 'normal' && payload) {
35
+ // move editor position
36
+ let moveAfterEl = payload.$comment
37
+ if (!this.editor.conf.flatMode) moveAfterEl = moveAfterEl.querySelector<HTMLElement>('.atk-footer')!
38
+ this.editor.getPlugs()?.get(Mover)?.move(moveAfterEl)
39
+
40
+ const $relative = this.editor.ctx.conf.scrollRelativeTo && this.editor.ctx.conf.scrollRelativeTo()
41
+ Ui.scrollIntoView(this.editor.getUI().$el, true, $relative)
42
+
43
+ const plugin = this.editor.getPlugs()?.getPlugs().find(p => p.editorStateEffectWhen === state)
44
+ if (plugin && plugin.editorStateEffect) {
45
+ this.stateUnmountFn = plugin.editorStateEffect(payload.comment)
46
+ }
47
+ }
48
+
49
+ // change current state
50
+ this.stateCurt = state
51
+ }
52
+ }
package/src/i18n/zh-CN.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { I18n } from '.'
1
+ import type { I18n } from '.'
2
2
 
3
3
  const zhCN: I18n = {
4
4
  /* Editor */
@@ -1,4 +1,4 @@
1
- import Layer, { getLayerWrap } from './layer'
2
-
3
- export default Layer
4
- export { getLayerWrap }
1
+ export * from './layer'
2
+ export * from './wrap'
3
+ export * from './scrollbar-helper'
4
+ export * from './layer-manager'
@@ -0,0 +1,32 @@
1
+ import type { ContextApi } from '~/types'
2
+ import { getScrollbarHelper } from './scrollbar-helper'
3
+ import { LayerWrap } from './wrap'
4
+ import { Layer } from './layer'
5
+
6
+ export class LayerManager {
7
+ private wrap: LayerWrap
8
+ private ctx: ContextApi
9
+
10
+ constructor(ctx: ContextApi) {
11
+ this.ctx = ctx
12
+
13
+ this.wrap = new LayerWrap()
14
+ document.body.appendChild(this.wrap.getWrap())
15
+
16
+ ctx.on('destroy', () => {
17
+ this.wrap.getWrap().remove()
18
+ })
19
+
20
+ // 记录页面原始 CSS 属性
21
+ getScrollbarHelper().init()
22
+ }
23
+
24
+ getEl() {
25
+ return this.wrap.getWrap()
26
+ }
27
+
28
+ create(name: string, el?: HTMLElement | undefined) {
29
+ const layer = new Layer(this.wrap, name, el)
30
+ return layer
31
+ }
32
+ }
@@ -1,51 +1,17 @@
1
- import Context from '~/types/context'
2
- import Component from '../lib/component'
3
- import * as Utils from '../lib/utils'
4
- import * as Ui from '../lib/ui'
1
+ import type { LayerWrap } from './wrap'
5
2
 
6
- export default class Layer extends Component {
7
- private name: string
8
- private $wrap: HTMLElement
9
- private $mask: HTMLElement
3
+ export class Layer {
4
+ private $el: HTMLElement
5
+ private wrap: LayerWrap
6
+ private onAfterHide?: () => void
10
7
 
11
- private maskClickHideEnable: boolean = true
12
-
13
- public static BodyOrgOverflow: string
14
- public static BodyOrgPaddingRight: string
15
-
16
- public afterHide?: Function
17
-
18
- constructor (ctx: Context, name: string, el?: HTMLElement) {
19
- super(ctx)
20
-
21
- this.name = name
22
- const { $wrap, $mask } = getLayerWrap()
23
- this.$wrap = $wrap
24
- this.$mask = $mask
25
-
26
- this.$el = this.$wrap.querySelector(`[data-layer-name="${name}"].atk-layer-item`)!
27
- if (this.$el === null) {
28
- // 若传递 layer 元素为空
29
- if (!el) {
30
- this.$el = Utils.createElement()
31
- this.$el.classList.add('atk-layer-item')
32
- } else {
33
- this.$el = el
34
- }
35
- }
36
- this.$el.setAttribute('data-layer-name', name)
37
- this.$el.style.display = 'none'
38
-
39
- // 添加到 layers wrap 中
40
- this.$wrap.append(this.$el)
41
- }
42
-
43
- getName() {
44
- return this.name
8
+ constructor(wrap: LayerWrap, name: string, el?: HTMLElement) {
9
+ this.wrap = wrap
10
+ this.$el = this.wrap.createItem(name, el)
45
11
  }
46
12
 
47
- getWrapEl() {
48
- return this.$wrap
13
+ setOnAfterHide(func: () => void) {
14
+ this.onAfterHide = func
49
15
  }
50
16
 
51
17
  getEl() {
@@ -53,111 +19,21 @@ export default class Layer extends Component {
53
19
  }
54
20
 
55
21
  show() {
56
- this.fireAllActionTimer()
57
-
58
- this.$wrap.style.display = 'block'
59
- this.$mask.style.display = 'block'
60
- this.$mask.classList.add('atk-fade-in')
61
22
  this.$el.style.display = ''
62
-
63
- this.$mask.onclick = () => {
64
- if (this.maskClickHideEnable) this.hide()
65
- }
66
-
67
- // body style 禁止滚动 + 防抖
68
- this.pageBodyScrollBarHide()
69
- }
70
-
71
- hide () {
72
- if (this.afterHide) this.afterHide()
73
- this.$wrap.classList.add('atk-fade-out')
74
- this.$el.style.display = 'none'
75
-
76
- // body style 禁止滚动解除
77
- this.pageBodyScrollBarShow()
78
-
79
- this.newActionTimer(() => {
80
- this.$wrap.style.display = 'none'
81
- this.checkCleanLayer()
82
- }, 450)
83
- this.newActionTimer(() => {
84
- this.$wrap.style.display = 'none'
85
- this.$wrap.classList.remove('atk-fade-out')
86
- }, 200)
23
+ this.wrap.show()
87
24
  }
88
25
 
89
- setMaskClickHide (enable: boolean) {
90
- this.maskClickHideEnable = enable
91
- }
92
-
93
- // 页面滚动条隐藏
94
- pageBodyScrollBarHide() {
95
- document.body.style.overflow = 'hidden'
96
-
97
- const bpr = parseInt(window.getComputedStyle(document.body, null).getPropertyValue('padding-right'), 10)
98
- document.body.style.paddingRight = `${Ui.getScrollBarWidth() + bpr || 0}px`
99
- }
100
-
101
- // 页面滚动条显示
102
- pageBodyScrollBarShow() {
103
- document.body.style.overflow = Layer.BodyOrgOverflow
104
- document.body.style.paddingRight = Layer.BodyOrgPaddingRight
105
- }
106
-
107
- // Timers
108
- private static actionTimers: {act: Function, tid: number}[] = []
109
-
110
- private newActionTimer(func: Function, delay: number) {
111
- const act = () => {
112
- func() // 执行
113
- Layer.actionTimers = Layer.actionTimers.filter(o => o.act !== act) // 删除
114
- }
115
-
116
- const tid = window.setTimeout(() => act(), delay)
117
-
118
- Layer.actionTimers.push({ act, tid })
119
- }
120
-
121
- private fireAllActionTimer() {
122
- Layer.actionTimers.forEach(item => {
123
- clearTimeout(item.tid)
124
- item.act() // 立即执行
26
+ hide() {
27
+ this.wrap.hide(() => {
28
+ this.$el.style.display = 'none'
29
+ this.onAfterHide && this.onAfterHide()
125
30
  })
126
31
  }
127
32
 
128
- /** 销毁 - 无动画 */
129
- disposeNow() {
130
- this.$el.remove()
131
- this.pageBodyScrollBarShow()
132
- // this.$el dispose
133
- this.checkCleanLayer()
134
- }
135
-
136
- /** 销毁 */
137
- dispose() {
138
- this.hide()
139
- this.$el.remove()
140
- // this.$el dispose
141
- this.checkCleanLayer()
142
- }
143
-
144
- checkCleanLayer() {
145
- if (this.getWrapEl().querySelectorAll('.atk-layer-item').length === 0) {
146
- this.$wrap.style.display = 'none'
147
- }
148
- }
149
- }
150
-
151
- export function getLayerWrap(): { $wrap: HTMLElement, $mask: HTMLElement } {
152
- let $wrap = document.querySelector<HTMLElement>(`.atk-layer-wrap`)
153
- if (!$wrap) {
154
- $wrap = Utils.createElement(
155
- `<div class="atk-layer-wrap" style="display: none;"><div class="atk-layer-mask"></div></div>`
156
- )
157
- document.body.appendChild($wrap)
33
+ destroy() {
34
+ this.wrap.hide(() => {
35
+ this.$el.remove()
36
+ this.onAfterHide && this.onAfterHide()
37
+ })
158
38
  }
159
-
160
- const $mask = $wrap.querySelector<HTMLElement>('.atk-layer-mask')!
161
-
162
- return { $wrap, $mask }
163
39
  }
@@ -0,0 +1,24 @@
1
+ import * as Ui from '@/lib/ui'
2
+
3
+ let bodyOrgOverflow: string
4
+ let bodyOrgPaddingRight: string
5
+
6
+ export function getScrollbarHelper() {
7
+ return {
8
+ init() {
9
+ bodyOrgOverflow = document.body.style.overflow
10
+ bodyOrgPaddingRight = document.body.style.paddingRight
11
+ },
12
+
13
+ unlock() {
14
+ document.body.style.overflow = bodyOrgOverflow
15
+ document.body.style.paddingRight = bodyOrgPaddingRight
16
+ },
17
+
18
+ lock() {
19
+ document.body.style.overflow = 'hidden'
20
+ const barPaddingRight = parseInt(window.getComputedStyle(document.body, null).getPropertyValue('padding-right'), 10)
21
+ document.body.style.paddingRight = `${Ui.getScrollBarWidth() + barPaddingRight || 0}px`
22
+ }
23
+ }
24
+ }