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
@@ -1,10 +1,11 @@
1
- import './emoticons-plug.scss'
1
+ import './emoticons.scss'
2
2
 
3
- import * as Utils from '~/src/lib/utils'
4
- import * as Ui from '~/src/lib/ui'
5
- import { EmoticonListData, EmoticonGrpData } from '~/types/artalk-data'
6
- import EditorPlug from './editor-plug'
7
- import Editor from '../editor'
3
+ import type { EmoticonListData, EmoticonGrpData } from '~/types'
4
+ import * as Utils from '@/lib/utils'
5
+ import * as Ui from '@/lib/ui'
6
+ import $t from '@/i18n'
7
+ import EditorPlug from './_plug'
8
+ import type PlugKit from './_kit'
8
9
 
9
10
  type OwOFormatType = {
10
11
  [key: string] : {
@@ -13,23 +14,42 @@ type OwOFormatType = {
13
14
  }
14
15
  }
15
16
 
16
- export default class EmoticonsPlug extends EditorPlug {
17
- public static Name = 'emoticons'
17
+ export default class Emoticons extends EditorPlug {
18
+ private emoticons: EmoticonListData = []
19
+ private loadingTask: Promise<void>|null = null
18
20
 
19
- declare protected $panel: HTMLElement
21
+ private $grpWrap!: HTMLElement
22
+ private $grpSwitcher!: HTMLElement
20
23
 
21
- public emoticons: EmoticonListData = []
22
- public loadingTask: Promise<void>|null = null
24
+ constructor(kit: PlugKit) {
25
+ super(kit)
23
26
 
24
- public $grpWrap!: HTMLElement
25
- public $grpSwitcher!: HTMLElement
27
+ this.kit.useMounted(() => {
28
+ this.usePanel(`<div class="atk-editor-plug-emoticons"></div>`)
29
+ this.useBtn($t('emoticon'))
30
+ })
31
+ this.kit.useUnmounted(() => {})
26
32
 
27
- public constructor(public editor: Editor) {
28
- super(editor)
33
+ this.useContentTransformer((raw) => this.transEmoticonImageText(raw))
34
+ this.usePanelShow(() => {
35
+ ;(async () => {
36
+ await this.loadEmoticonsData()
29
37
 
30
- this.registerPanel(`<div class="atk-editor-plug-emoticons"></div>`)
31
- this.registerBtn(this.ctx.$t('emoticon'))
32
- this.registerContentTransformer((raw) => this.transEmoticonImageText(raw))
38
+ // 初始化元素
39
+ if (!this.isImgLoaded) {
40
+ this.initEmoticonsList()
41
+ this.isImgLoaded = true
42
+ }
43
+
44
+ // 延迟执行,防止无法读取高度
45
+ setTimeout(() => {
46
+ this.changeListHeight()
47
+ }, 30)
48
+ })()
49
+ })
50
+ this.usePanelHide(() => {
51
+ this.$panel!.parentElement!.style.height = ''
52
+ })
33
53
 
34
54
  // 表情包预加载
35
55
  window.setTimeout(() => {
@@ -37,29 +57,8 @@ export default class EmoticonsPlug extends EditorPlug {
37
57
  }, 1000) // 延迟 1s 加载
38
58
  }
39
59
 
40
- public onPanelShow() {
41
- ;(async () => {
42
- await this.loadEmoticonsData()
43
-
44
- // 初始化元素
45
- if (!this.isImgLoaded) {
46
- this.initEmoticonsList()
47
- this.isImgLoaded = true
48
- }
49
-
50
- // 延迟执行,防止无法读取高度
51
- setTimeout(() => {
52
- this.changeListHeight()
53
- }, 30)
54
- })()
55
- }
56
-
57
- public onPanelHide() {
58
- this.$panel.parentElement!.style.height = ''
59
- }
60
-
61
- isListLoaded = false
62
- isImgLoaded = false
60
+ private isListLoaded = false
61
+ private isImgLoaded = false
63
62
 
64
63
  public async loadEmoticonsData() {
65
64
  if (this.isListLoaded) return
@@ -70,9 +69,9 @@ export default class EmoticonsPlug extends EditorPlug {
70
69
 
71
70
  // 数据处理
72
71
  this.loadingTask = (async () => {
73
- Ui.showLoading(this.$panel)
74
- this.emoticons = await this.handleData(this.ctx.conf.emoticons)
75
- Ui.hideLoading(this.$panel)
72
+ Ui.showLoading(this.$panel!)
73
+ this.emoticons = await this.handleData(this.kit.useConf().emoticons)
74
+ Ui.hideLoading(this.$panel!)
76
75
  this.loadingTask = null
77
76
  this.isListLoaded = true
78
77
  })()
@@ -85,8 +84,8 @@ export default class EmoticonsPlug extends EditorPlug {
85
84
  }
86
85
 
87
86
  if (!Array.isArray(data)) {
88
- Ui.setError(this.$panel, "表情包数据必须为 Array/Object/String 类型")
89
- Ui.hideLoading(this.$panel)
87
+ Ui.setError(this.$panel!, "表情包数据必须为 Array/Object/String 类型")
88
+ Ui.hideLoading(this.$panel!)
90
89
  return []
91
90
  }
92
91
 
@@ -143,8 +142,8 @@ export default class EmoticonsPlug extends EditorPlug {
143
142
  const json = await resp.json()
144
143
  return json
145
144
  } catch (err) {
146
- Ui.hideLoading(this.$panel)
147
- Ui.setError(this.$panel, `表情加载失败 ${String(err)}`)
145
+ Ui.hideLoading(this.$panel!)
146
+ Ui.setError(this.$panel!, `表情加载失败 ${String(err)}`)
148
147
  return []
149
148
  }
150
149
  }
@@ -204,7 +203,7 @@ export default class EmoticonsPlug extends EditorPlug {
204
203
  private initEmoticonsList() {
205
204
  // 表情列表
206
205
  this.$grpWrap = Utils.createElement(`<div class="atk-grp-wrap"></div>`)
207
- this.$panel.append(this.$grpWrap)
206
+ this.$panel!.append(this.$grpWrap)
208
207
 
209
208
  this.emoticons.forEach((grp, index) => {
210
209
  const $grp = Utils.createElement(`<div class="atk-grp" style="display: none;"></div>`)
@@ -230,9 +229,9 @@ export default class EmoticonsPlug extends EditorPlug {
230
229
 
231
230
  $item.onclick = () => {
232
231
  if (grp.type === 'image') {
233
- this.editor.insertContent(`:[${item.key}]`)
232
+ this.kit.useEditor().insertContent(`:[${item.key}]`)
234
233
  } else {
235
- this.editor.insertContent(item.val || '')
234
+ this.kit.useEditor().insertContent(item.val || '')
236
235
  }
237
236
  }
238
237
  })
@@ -241,7 +240,7 @@ export default class EmoticonsPlug extends EditorPlug {
241
240
  // 表情分类切换 bar
242
241
  if (this.emoticons.length > 1) {
243
242
  this.$grpSwitcher = Utils.createElement(`<div class="atk-grp-switcher"></div>`)
244
- this.$panel.append(this.$grpSwitcher)
243
+ this.$panel!.append(this.$grpSwitcher)
245
244
  this.emoticons.forEach((grp, index) => {
246
245
  const $item = Utils.createElement('<span />')
247
246
  $item.innerText = grp.name
@@ -0,0 +1,35 @@
1
+ import EditorPlug from './_plug'
2
+ import type PlugKit from './_kit'
3
+
4
+ export default class HeaderEvent extends EditorPlug {
5
+ private get $inputs() {
6
+ return this.kit.useEditor().getHeaderInputEls()
7
+ }
8
+
9
+ constructor(kit: PlugKit) {
10
+ super(kit)
11
+
12
+ const inputEventFns: {[name: string]: () => void} = {}
13
+ const changeEventFns: {[name: string]: () => void} = {}
14
+
15
+ const trigger = (evt: 'header-input'|'header-change', $input: HTMLInputElement, field: string) => () => {
16
+ this.kit.useEvents().trigger(evt, { field, $input })
17
+ }
18
+
19
+ this.kit.useMounted(() => {
20
+ // batch bind the events
21
+ Object.entries(this.$inputs).forEach(([key, $input]) => {
22
+ $input.addEventListener('input', inputEventFns[key] = trigger('header-input', $input, key))
23
+ $input.addEventListener('change', changeEventFns[key] = trigger('header-change', $input, key))
24
+ })
25
+ })
26
+
27
+ this.kit.useUnmounted(() => {
28
+ // unmount the event
29
+ Object.entries(this.$inputs).forEach(([key, $input]) => {
30
+ $input.removeEventListener('input', inputEventFns[key])
31
+ $input.removeEventListener('change', changeEventFns[key])
32
+ })
33
+ })
34
+ }
35
+ }
@@ -0,0 +1,31 @@
1
+ import User from '@/lib/user'
2
+ import EditorPlug from './_plug'
3
+ import type PlugKit from './_kit'
4
+
5
+ export default class HeaderLink extends EditorPlug {
6
+ constructor(kit: PlugKit) {
7
+ super(kit)
8
+
9
+ const onLinkChange = ({ field }: { field: string }) => {
10
+ if (field === 'link') this.onLinkInputChange()
11
+ }
12
+
13
+ // bind events
14
+ this.kit.useMounted(() => {
15
+ this.kit.useEvents().on('header-change', onLinkChange)
16
+ })
17
+
18
+ this.kit.useUnmounted(() => {
19
+ this.kit.useEvents().off('header-change', onLinkChange)
20
+ })
21
+ }
22
+
23
+ private onLinkInputChange() {
24
+ // auto and force add protocol prefix for user input link
25
+ const link = this.kit.useUI().$link.value.trim()
26
+ if (!!link && !/^(http|https):\/\//.test(link)) {
27
+ this.kit.useUI().$link.value = `https://${link}`
28
+ User.update({ link: this.kit.useUI().$link.value })
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,98 @@
1
+ import User from '@/lib/user'
2
+ import $t from '@/i18n'
3
+ import EditorPlug from './_plug'
4
+ import type PlugKit from './_kit'
5
+
6
+ export default class HeaderUser extends EditorPlug {
7
+ constructor(kit: PlugKit) {
8
+ super(kit)
9
+
10
+ const onInput = ({ $input, field }: { $input: HTMLInputElement, field: string }) => {
11
+ if (this.kit.useEditor().getState() === 'edit')
12
+ return // TODO prevent execute when editing, since update comment.user not support
13
+
14
+ // update user data
15
+ User.update({ [field]: $input.value.trim() })
16
+
17
+ // remote fetch user info
18
+ if (field === 'nick' || field === 'email')
19
+ this.fetchUserInfo() // must after update user data, since fetchUserInfo() will use User.data
20
+ }
21
+
22
+ this.kit.useMounted(() => {
23
+ Object.entries(this.kit.useEditor().getHeaderInputEls())
24
+ .forEach(([key, $input]) => {
25
+ // set placeholder
26
+ $input.placeholder = `${$t(key as any)}`
27
+
28
+ // sync header values from User.data
29
+ $input.value = User.data[key] || ''
30
+ })
31
+
32
+ // bind events
33
+ this.kit.useEvents().on('header-input', onInput)
34
+ })
35
+
36
+ this.kit.useUnmounted(() => {
37
+ this.kit.useEvents().off('header-input', onInput)
38
+ })
39
+ }
40
+
41
+ private query = {
42
+ timer: <number|null>null,
43
+ abortFn: <(() => void)|null>null
44
+ }
45
+
46
+ /**
47
+ * Fetch user info from server
48
+ */
49
+ private fetchUserInfo() {
50
+ User.logout() // clear login status
51
+
52
+ if (this.query.timer) window.clearTimeout(this.query.timer) // clear the not executed timeout task
53
+ if (this.query.abortFn) this.query.abortFn() // abort the last request (if request is pending not finished)
54
+
55
+ this.query.timer = window.setTimeout(() => {
56
+ this.query.timer = null // clear the timer (clarify the timer is executing)
57
+
58
+ const {req, abort} = this.kit.useApi().user.userGet(
59
+ User.data.nick, User.data.email
60
+ )
61
+ this.query.abortFn = abort
62
+ req.then(data => this.onUserInfoFetched(data))
63
+ .catch((err) => {})
64
+ .finally(() => {
65
+ this.query.abortFn = null // clear the abort function (clarify the request is finished)
66
+ })
67
+ }, 400) // delay to reduce request
68
+ }
69
+
70
+ /**
71
+ * Function called when user info fetched
72
+ *
73
+ * @param data The response data from server
74
+ */
75
+ private onUserInfoFetched(
76
+ data: any // TODO fix type
77
+ ) {
78
+ // If api response is not login, logout
79
+ if (!data.is_login) User.logout()
80
+
81
+ // Update unread notifies
82
+ this.kit.useGlobalCtx().getData().updateUnreads(data.unread)
83
+
84
+ // If user is admin and not login,
85
+ if (User.checkHasBasicUserInfo() && !data.is_login && data.user?.is_admin) {
86
+ // then show login window
87
+ this.kit.useGlobalCtx().checkAdmin({
88
+ onSuccess: () => {}
89
+ })
90
+ }
91
+
92
+ // Auto fill user link from server
93
+ if (data.user && data.user.link) {
94
+ this.kit.useUI().$link.value = data.user.link
95
+ User.update({ link: data.user.link })
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,40 @@
1
+ import type { ArtalkConfig } from '~/types'
2
+ import type EditorPlug from './_plug'
3
+ import LocalStorage from './local-storage'
4
+ import Textarea from './textarea'
5
+ import SubmitBtn from './submit-btn'
6
+ import Submit from './submit'
7
+ import StateReply from './state-reply'
8
+ import StateEdit from './state-edit'
9
+ import Closable from './closable'
10
+ import HeaderEvent from './header-event'
11
+ import HeaderUser from './header-user'
12
+ import HeaderLink from './header-link'
13
+ import Mover from './mover'
14
+ import Emoticons from './emoticons'
15
+ import Upload from './upload'
16
+ import Preview from './preview'
17
+
18
+ /** The default enabled plugs */
19
+ export const ENABLED_PLUGS: (typeof EditorPlug)[] = [
20
+ // Core
21
+ LocalStorage,
22
+ HeaderEvent, HeaderUser, HeaderLink,
23
+ Textarea,
24
+ Submit, SubmitBtn,
25
+ Mover, StateReply, StateEdit,
26
+ Closable,
27
+
28
+ // Extensions
29
+ Emoticons, Upload, Preview
30
+ ]
31
+
32
+ /** Get the name list of disabled plugs */
33
+ export function getDisabledPlugByConf(conf: ArtalkConfig): (typeof EditorPlug)[] {
34
+ return [
35
+ {k: Upload, v: conf.imgUpload},
36
+ {k: Emoticons, v: conf.emoticons},
37
+ {k: Preview, v: conf.preview},
38
+ {k: Mover, v: conf.editorTravel},
39
+ ].filter(n => !n.v).flatMap(n => n.k)
40
+ }
@@ -0,0 +1,36 @@
1
+ import $t from '@/i18n'
2
+ import type PlugKit from './_kit'
3
+ import EditorPlug from './_plug'
4
+
5
+ const LocalStorageKey = 'ArtalkContent'
6
+
7
+ export default class LocalStorage extends EditorPlug {
8
+ constructor(kit: PlugKit) {
9
+ super(kit)
10
+
11
+ const onContentUpdated = () => {
12
+ this.save()
13
+ }
14
+
15
+ this.kit.useMounted(() => {
16
+ // load editor content from localStorage when init
17
+ const localContent = window.localStorage.getItem(LocalStorageKey) || ''
18
+ if (localContent.trim() !== '') {
19
+ this.kit.useEditor().showNotify($t('restoredMsg'), 'i')
20
+ this.kit.useEditor().setContent(localContent)
21
+ }
22
+
23
+ // bind event
24
+ this.kit.useEvents().on('content-updated', onContentUpdated)
25
+ })
26
+
27
+ this.kit.useUnmounted(() => {
28
+ this.kit.useEvents().off('content-updated', onContentUpdated)
29
+ })
30
+ }
31
+
32
+ // Save editor content to localStorage
33
+ public save() {
34
+ window.localStorage.setItem(LocalStorageKey, this.kit.useEditor().getContentRaw().trim())
35
+ }
36
+ }
@@ -0,0 +1,29 @@
1
+ import * as Utils from '@/lib/utils'
2
+ import EditorPlug from './_plug'
3
+
4
+ export default class Mover extends EditorPlug {
5
+ private isMoved = false
6
+
7
+ move(afterEl: HTMLElement) {
8
+ if (this.isMoved) return
9
+ this.isMoved = true
10
+
11
+ const editorEl = this.kit.useUI().$el
12
+
13
+ editorEl.after(Utils.createElement('<div class="atk-editor-travel-placeholder"></div>'))
14
+
15
+ const $travelPlace = Utils.createElement('<div></div>')
16
+ afterEl.after($travelPlace)
17
+ $travelPlace.replaceWith(editorEl)
18
+
19
+ editorEl.classList.add('atk-fade-in') // 添加渐入动画
20
+ editorEl.classList.add('editor-traveling')
21
+ }
22
+
23
+ back() {
24
+ if (!this.isMoved) return
25
+ this.isMoved = false
26
+ this.kit.useGlobalCtx().$root.querySelector('.atk-editor-travel-placeholder')?.replaceWith(this.kit.useUI().$el)
27
+ this.kit.useUI().$el.classList.remove('editor-traveling')
28
+ }
29
+ }
@@ -0,0 +1,41 @@
1
+ import './preview.scss'
2
+
3
+ import * as marked from '@/lib/marked'
4
+ import $t from '@/i18n'
5
+ import EditorPlug from './_plug'
6
+ import type PlugKit from './_kit'
7
+
8
+ export default class Preview extends EditorPlug {
9
+ private isPlugPanelShow = false
10
+
11
+ constructor(kit: PlugKit) {
12
+ super(kit)
13
+
14
+ this.kit.useMounted(() => {
15
+ this.usePanel(`<div class="atk-editor-plug-preview"></div>`)
16
+
17
+ // initialize plug button
18
+ let btnText = $t('preview')
19
+ if (marked.getInstance()) btnText += ` <i title="Markdown is supported"><svg class="markdown" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path></svg></i>`
20
+ this.useBtn(btnText)
21
+ })
22
+ this.kit.useUnmounted(() => {})
23
+
24
+ // function to update content
25
+ this.kit.useEvents().on('content-updated', (content) => {
26
+ this.isPlugPanelShow && this.updateContent()
27
+ })
28
+
29
+ this.usePanelShow(() => {
30
+ this.isPlugPanelShow = true
31
+ this.updateContent()
32
+ })
33
+ this.usePanelHide(() => {
34
+ this.isPlugPanelShow = false
35
+ })
36
+ }
37
+
38
+ updateContent() {
39
+ this.$panel!.innerHTML = this.kit.useEditor().getContentMarked()
40
+ }
41
+ }
@@ -0,0 +1,116 @@
1
+ import type { CommentData } from '~/types'
2
+ import $t from '@/i18n'
3
+ import * as Utils from '@/lib/utils'
4
+ import User from '@/lib/user'
5
+ import type PlugKit from './_kit'
6
+ import EditorPlug from './_plug'
7
+ import Submit from './submit'
8
+
9
+ export default class StateEdit extends EditorPlug {
10
+ private comment?: CommentData
11
+
12
+ constructor(kit: PlugKit) {
13
+ super(kit)
14
+
15
+ // add effect when state switch to `edit`
16
+ this.useEditorStateEffect('edit', (comment) => {
17
+ this.edit(comment)
18
+
19
+ return () => {
20
+ this.cancelEdit()
21
+ }
22
+ })
23
+
24
+ // register submit preset
25
+ this.kit.useMounted(() => {
26
+ const submitPlug = this.kit.useDeps(Submit)
27
+ if (!submitPlug) throw Error("SubmitPlug not initialized")
28
+
29
+ submitPlug.registerCustom({
30
+ activeCond: () => !!this.comment, // active this custom submit when edit mode
31
+ req: async () => {
32
+ const saveData = {
33
+ content: this.kit.useEditor().getContentFinal(),
34
+ nick: this.kit.useUI().$nick.value,
35
+ email: this.kit.useUI().$email.value,
36
+ link: this.kit.useUI().$link.value,
37
+ }
38
+ const nComment = await this.kit.useApi().comment.commentEdit({
39
+ ...this.comment, ...saveData
40
+ })
41
+ return nComment
42
+ },
43
+ post: (nComment: CommentData) => {
44
+ this.kit.useGlobalCtx().getData().updateComment(nComment)
45
+ }
46
+ })
47
+ })
48
+ }
49
+
50
+ private edit(comment: CommentData) {
51
+ const ui = this.kit.useUI()
52
+ if (!ui.$editCancelBtn) {
53
+ const $btn = Utils.createElement(
54
+ `<div class="atk-send-reply">` +
55
+ `${$t('editCancel')} ` +
56
+ `<span class="atk-cancel">×</span>` +
57
+ `</div>`
58
+ )
59
+ $btn.onclick = () => {
60
+ this.kit.useEditor().resetState()
61
+ }
62
+ ui.$textareaWrap.append($btn)
63
+ ui.$editCancelBtn = $btn
64
+ }
65
+ this.comment = comment
66
+
67
+ ui.$header.style.display = 'none' // TODO support modify header information
68
+
69
+ ui.$nick.value = comment.nick || ''
70
+ ui.$email.value = comment.email || ''
71
+ ui.$link.value = comment.link || ''
72
+
73
+ this.kit.useEditor().setContent(comment.content)
74
+ ui.$textarea.focus()
75
+
76
+ this.updateSubmitBtnText($t('save'))
77
+ }
78
+
79
+ private cancelEdit() {
80
+ if (!this.comment) return
81
+
82
+ const ui = this.kit.useUI()
83
+
84
+ if (ui.$editCancelBtn) {
85
+ ui.$editCancelBtn.remove()
86
+ ui.$editCancelBtn = undefined
87
+ }
88
+
89
+ this.comment = undefined
90
+
91
+ const { nick, email, link } = User.data
92
+ ui.$nick.value = nick
93
+ ui.$email.value = email
94
+ ui.$link.value = link
95
+
96
+ this.kit.useEditor().setContent('')
97
+ this.restoreSubmitBtnText()
98
+
99
+ ui.$header.style.display = '' // TODO support modify header information
100
+ }
101
+
102
+ // -------------------------------------------------------------------
103
+ // Submit Btn Text Modifier
104
+ // -------------------------------------------------------------------
105
+
106
+ private originalSubmitBtnText = 'Send'
107
+
108
+ private updateSubmitBtnText(text: string) {
109
+ this.originalSubmitBtnText = this.kit.useUI().$submitBtn.innerText
110
+ this.kit.useUI().$submitBtn.innerText = text
111
+ }
112
+
113
+ private restoreSubmitBtnText() {
114
+ this.kit.useUI().$submitBtn.innerText = this.originalSubmitBtnText
115
+ }
116
+ }
@@ -0,0 +1,91 @@
1
+ import type { CommentData } from '~/types'
2
+ import * as Utils from '@/lib/utils'
3
+ import * as Ui from '@/lib/ui'
4
+ import $t from '@/i18n'
5
+ import EditorPlug from './_plug'
6
+ import type PlugKit from './_kit'
7
+ import Submit from './submit'
8
+ import SubmitAddPreset from './submit-add'
9
+
10
+ export default class StateReply extends EditorPlug {
11
+ private comment?: CommentData
12
+
13
+ constructor(kit: PlugKit) {
14
+ super(kit)
15
+
16
+ // add effect when state switch to `reply`
17
+ this.useEditorStateEffect('reply', (commentData) => {
18
+ this.setReply(commentData)
19
+
20
+ return () => {
21
+ this.cancelReply()
22
+ }
23
+ })
24
+
25
+ // register submit preset
26
+ this.kit.useEvents().on('mounted', () => {
27
+ const submitPlug = this.kit.useDeps(Submit)
28
+ if (!submitPlug) throw Error("SubmitPlug not initialized")
29
+
30
+ const defaultPreset = new SubmitAddPreset(this.kit)
31
+
32
+ submitPlug.registerCustom({
33
+ activeCond: () => !!this.comment, // active this custom submit when reply mode
34
+ req: async () => {
35
+ if (!this.comment) throw new Error('reply comment cannot be empty')
36
+
37
+ const nComment = await this.kit.useApi().comment.add({
38
+ ...defaultPreset.getSubmitAddParams(),
39
+ rid: this.comment.id,
40
+ page_key: this.comment.page_key,
41
+ page_title: undefined,
42
+ site_name: this.comment.site_name
43
+ })
44
+
45
+ return nComment
46
+ },
47
+ post: (nComment: CommentData) => {
48
+ // open another page when reply comment is not the same pageKey
49
+ const conf = this.kit.useConf()
50
+ if (nComment.page_key !== conf.pageKey) {
51
+ window.open(`${nComment.page_url}#atk-comment-${nComment.id}`)
52
+ }
53
+
54
+ defaultPreset.postSubmitAdd(nComment)
55
+ }
56
+ })
57
+ })
58
+ }
59
+
60
+ private setReply(commentData: CommentData) {
61
+ const ui = this.kit.useUI()
62
+ if (!ui.$sendReply) {
63
+ ui.$sendReply = Utils.createElement(
64
+ `<div class="atk-send-reply">` +
65
+ `${$t('reply')} ` +
66
+ `<span class="atk-text"></span><span class="atk-cancel">×</span>` +
67
+ `</div>`
68
+ )
69
+ ui.$sendReply.querySelector<HTMLElement>('.atk-text')!.innerText = `@${commentData.nick}`
70
+ ui.$sendReply.addEventListener('click', () => {
71
+ this.kit.useEditor().resetState()
72
+ })
73
+ ui.$textareaWrap.append(ui.$sendReply)
74
+ }
75
+
76
+ this.comment = commentData
77
+
78
+ ui.$textarea.focus()
79
+ }
80
+
81
+ private cancelReply() {
82
+ if (!this.comment) return
83
+
84
+ const ui = this.kit.useUI()
85
+ if (ui.$sendReply) {
86
+ ui.$sendReply.remove()
87
+ ui.$sendReply = undefined
88
+ }
89
+ this.comment = undefined
90
+ }
91
+ }