artalk 2.2.11 → 2.3.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 (78) hide show
  1. package/dist/Artalk.css +1 -1
  2. package/dist/Artalk.es.js +1872 -1143
  3. package/dist/Artalk.iife.js +1 -1
  4. package/dist/Artalk.js +1 -1
  5. package/dist/ArtalkLite.css +1 -0
  6. package/dist/ArtalkLite.es.js +5123 -0
  7. package/dist/ArtalkLite.iife.js +1 -0
  8. package/dist/ArtalkLite.js +1 -0
  9. package/index.html +5 -3
  10. package/package.json +7 -5
  11. package/src/api/index.ts +24 -4
  12. package/src/api/request.ts +50 -81
  13. package/src/artalk.ts +131 -127
  14. package/src/comment/actions.ts +86 -0
  15. package/src/{components/html → comment}/comment.html +1 -1
  16. package/src/comment/comment.ts +191 -0
  17. package/src/comment/index.ts +3 -0
  18. package/src/comment/render.ts +425 -0
  19. package/src/components/action-btn.ts +6 -3
  20. package/src/components/dialog.ts +7 -3
  21. package/src/components/read-more-btn.ts +6 -2
  22. package/src/context.ts +204 -13
  23. package/src/defaults.ts +15 -4
  24. package/src/editor/editor.html +18 -0
  25. package/src/editor/editor.ts +419 -0
  26. package/src/editor/index.ts +3 -0
  27. package/src/editor/plugs/editor-plug.ts +51 -0
  28. package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.less +2 -1
  29. package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.ts +65 -63
  30. package/src/editor/plugs/header-input-plug.ts +78 -0
  31. package/src/{components/editor-plugs → editor/plugs}/preview-plug.less +0 -0
  32. package/src/editor/plugs/preview-plug.ts +40 -0
  33. package/src/editor/plugs/upload-plug.ts +124 -0
  34. package/src/i18n/en.ts +78 -0
  35. package/src/i18n/index.ts +21 -0
  36. package/src/i18n/zh-CN.ts +82 -0
  37. package/src/layer/index.ts +4 -0
  38. package/src/{components → layer}/layer.ts +9 -9
  39. package/src/{components/html → layer}/sidebar-layer.html +0 -0
  40. package/src/{components → layer}/sidebar-layer.ts +17 -47
  41. package/src/lib/checker/admin-checker.ts +7 -7
  42. package/src/lib/checker/captcha-checker.ts +5 -6
  43. package/src/lib/checker/index.ts +22 -17
  44. package/src/lib/component.ts +7 -2
  45. package/src/lib/stat.ts +63 -0
  46. package/src/lib/ui.ts +3 -10
  47. package/src/lib/user.ts +20 -3
  48. package/src/lib/utils.ts +23 -9
  49. package/src/list/index.ts +3 -0
  50. package/src/{components → list}/list-lite.ts +83 -111
  51. package/src/{components → list}/list-nest.ts +0 -0
  52. package/src/{components/html → list}/list.html +3 -6
  53. package/src/{components → list}/list.ts +44 -42
  54. package/src/style/_variables.less +1 -2
  55. package/src/style/comment.less +26 -13
  56. package/src/style/editor.less +22 -14
  57. package/src/style/list.less +6 -9
  58. package/src/style/main.less +9 -8
  59. package/src/style/pagination.less +1 -1
  60. package/test/ArtalkCount.html +16 -0
  61. package/test/ArtalkI18n.html +15 -0
  62. package/test/ArtalkLite.html +15 -0
  63. package/types/artalk-config.d.ts +50 -32
  64. package/types/context.d.ts +128 -0
  65. package/types/event.d.ts +6 -66
  66. package/types/global.d.ts +1 -0
  67. package/types/plug.d.ts +4 -0
  68. package/{vite-common.config.ts → vite-base.config.ts} +6 -4
  69. package/vite-demo.config.ts +2 -4
  70. package/vite-lite.config.ts +22 -0
  71. package/vite.config.ts +9 -18
  72. package/src/components/_component.ts.txt +0 -10
  73. package/src/components/comment.ts +0 -605
  74. package/src/components/editor-plugs/_example-plug.ts.txt +0 -29
  75. package/src/components/editor-plugs/editor-plug.ts +0 -20
  76. package/src/components/editor-plugs/preview-plug.ts +0 -48
  77. package/src/components/editor.ts +0 -604
  78. package/src/components/html/editor.html +0 -18
@@ -0,0 +1,86 @@
1
+ import Comment from './comment'
2
+ import ActionBtn from '../components/action-btn'
3
+
4
+ export default class CommentActions {
5
+ private comment: Comment
6
+
7
+ private get ctx() { return this.comment.ctx }
8
+ private get data() { return this.comment.getData() }
9
+ private get cConf() { return this.comment.getConf() }
10
+
11
+ public constructor(comment: Comment) {
12
+ this.comment = comment
13
+ }
14
+
15
+ /** 投票操作 */
16
+ public vote(type: 'up'|'down') {
17
+ const actionBtn = (type === 'up') ? this.comment.getRender().voteBtnUp : this.comment.getRender().voteBtnDown
18
+
19
+ this.ctx.getApi().vote(this.data.id, `comment_${type}`)
20
+ .then((v) => {
21
+ this.data.vote_up = v.up
22
+ this.data.vote_down = v.down
23
+ this.comment.getRender().voteBtnUp?.updateText()
24
+ this.comment.getRender().voteBtnDown?.updateText()
25
+ })
26
+ .catch((err) => {
27
+ actionBtn?.setError(this.ctx.$t('voteFail'))
28
+ console.log(err)
29
+ })
30
+ }
31
+
32
+ /** 管理员 - 评论状态修改 */
33
+ public adminEdit(type: 'collapsed'|'pending'|'pinned', btnElem: ActionBtn) {
34
+ if (btnElem.isLoading) return // 若正在修改中
35
+
36
+ btnElem.setLoading(true, `${this.ctx.$t('editing')}...`)
37
+
38
+ // 克隆并修改当前数据
39
+ const modify = { ...this.data }
40
+ if (type === 'collapsed') {
41
+ modify.is_collapsed = !modify.is_collapsed
42
+ } else if (type === 'pending') {
43
+ modify.is_pending = !modify.is_pending
44
+ } else if (type === 'pinned') {
45
+ modify.is_pinned = !modify.is_pinned
46
+ }
47
+
48
+ this.ctx.getApi().commentEdit(modify).then((data) => {
49
+ btnElem.setLoading(false)
50
+
51
+ // 刷新当前 Comment UI
52
+ this.comment.setData(data)
53
+
54
+ // 刷新 List UI
55
+ this.ctx.listRefreshUI()
56
+ }).catch((err) => {
57
+ console.error(err)
58
+ btnElem.setError(this.ctx.$t('editFail'))
59
+ })
60
+ }
61
+
62
+ /** 管理员 - 评论删除 */
63
+ public adminDelete(btnElem: ActionBtn) {
64
+ if (btnElem.isLoading) return // 若正在删除中
65
+
66
+ btnElem.setLoading(true, `${this.ctx.$t('deleting')}...`)
67
+ this.ctx.getApi().commentDel(this.data.id, this.data.site_name)
68
+ .then(() => {
69
+ btnElem.setLoading(false)
70
+ if (this.cConf.onDelete) this.cConf.onDelete(this.comment)
71
+ })
72
+ .catch((e) => {
73
+ console.error(e)
74
+ btnElem.setError(this.ctx.$t('deleteFail'))
75
+ })
76
+ }
77
+
78
+ /** 快速跳转到该评论 */
79
+ public goToReplyComment() {
80
+ const origHash = window.location.hash
81
+ const modifyHash = `#atk-comment-${this.data.rid}`
82
+
83
+ window.location.hash = modifyHash
84
+ if (modifyHash === origHash) window.dispatchEvent(new Event('hashchange')) // 强制触发事件
85
+ }
86
+ }
@@ -4,7 +4,7 @@
4
4
  <div class="atk-main">
5
5
  <div class="atk-header">
6
6
  <span class="atk-item atk-nick"></span>
7
- <span class="atk-item atk-badge"></span>
7
+ <span class="atk-badge-wrap"></span>
8
8
  <span class="atk-item atk-date"></span>
9
9
  </div>
10
10
  <div class="atk-body">
@@ -0,0 +1,191 @@
1
+ import { CommentData } from '~/types/artalk-data'
2
+ import Context from '~/types/context'
3
+ import Component from '../lib/component'
4
+ import * as Utils from '../lib/utils'
5
+ import UADetect from '../lib/detect'
6
+ import CommentRender from './render'
7
+ import CommentActions from './actions'
8
+
9
+ export interface CommentConf {
10
+ isUnread?: boolean
11
+ openURL?: string
12
+ isFlatMode: boolean
13
+ replyTo?: CommentData
14
+ afterRender?: () => void
15
+ openEvt?: () => void
16
+ onReplyBtnClick?: Function
17
+ onDelete?: Function
18
+ }
19
+
20
+ export default class Comment extends Component {
21
+ private renderInstance: CommentRender
22
+ private actionInstance: CommentActions
23
+
24
+ private data: CommentData
25
+ private cConf: CommentConf
26
+
27
+ private parent: Comment|null
28
+ private children: Comment[] = []
29
+
30
+ private nestCurt: number // 当前嵌套层数
31
+ private nestMax: number // 最大嵌套层数
32
+
33
+ constructor(ctx: Context, data: CommentData, conf: CommentConf) {
34
+ super(ctx)
35
+
36
+ // 最大嵌套数
37
+ this.nestMax = ctx.conf.nestMax || 3
38
+
39
+ this.cConf = conf
40
+ this.data = { ...data }
41
+ this.data.date = this.data.date.replace(/-/g, '/') // 解决 Safari 日期解析 NaN 问题
42
+
43
+ this.parent = null
44
+ this.nestCurt = 1 // 现在已嵌套 n 层
45
+
46
+ this.actionInstance = new CommentActions(this)
47
+ this.renderInstance = new CommentRender(this)
48
+ }
49
+
50
+ /** 渲染 UI */
51
+ public render() {
52
+ const newEl = this.renderInstance.render()
53
+
54
+ if (this.$el) this.$el.replaceWith(newEl)
55
+ this.$el = newEl
56
+
57
+ if (this.cConf.afterRender) this.cConf.afterRender()
58
+ }
59
+
60
+ /** 获取评论操作实例对象 */
61
+ public getActions() {
62
+ return this.actionInstance
63
+ }
64
+
65
+ /** 获取评论渲染器实例对象 */
66
+ public getRender() {
67
+ return this.renderInstance
68
+ }
69
+
70
+ /** 获取评论数据 */
71
+ public getData() {
72
+ return this.data
73
+ }
74
+
75
+ /** 设置数据 */
76
+ public setData(data: CommentData) {
77
+ this.data = data
78
+
79
+ this.render()
80
+ this.getRender().playFadeAnimForBody()
81
+ }
82
+
83
+ /** 获取父评论 */
84
+ public getParent() {
85
+ return this.parent
86
+ }
87
+
88
+ /** 获取所有子评论 */
89
+ public getChildren() {
90
+ return this.children
91
+ }
92
+
93
+ /** 获取当前嵌套层数 */
94
+ public getNestCurt() {
95
+ return this.nestCurt
96
+ }
97
+
98
+ /** 判断是否为根评论 */
99
+ public getIsRoot() {
100
+ return this.data.rid === 0
101
+ }
102
+
103
+ /** 获取评论 ID */
104
+ public getID() {
105
+ return this.data.id
106
+ }
107
+
108
+ /** 置入子评论 */
109
+ public putChild(childC: Comment, insertMode: 'append'|'prepend' = 'append') {
110
+ childC.parent = this
111
+ childC.nestCurt = this.nestCurt + 1 // 嵌套层数 +1
112
+
113
+ this.children.push(childC)
114
+
115
+ const $children = this.getChildrenEl()
116
+ if (insertMode === 'append') $children.append(childC.getEl())
117
+ else if (insertMode === 'prepend') $children.prepend(childC.getEl())
118
+
119
+ childC.getRender().playFadeAnim()
120
+
121
+ // 内容限高
122
+ childC.getRender().checkHeightLimitArea('content')
123
+ }
124
+
125
+ /** 获取存放子评论的元素对象 */
126
+ public getChildrenEl(): HTMLElement {
127
+ let $children = this.getRender().getChildrenWrap()
128
+
129
+ if (!$children) {
130
+ // console.log(this.nestCurt)
131
+ if (this.nestCurt < this.nestMax) {
132
+ $children = this.getRender().renderChildrenWrap()
133
+ } else {
134
+ $children = this.parent!.getChildrenEl()
135
+ }
136
+ }
137
+
138
+ return $children
139
+ }
140
+
141
+ /** 获取所有父评论 */
142
+ public getParents() {
143
+ const parents: Comment[] = []
144
+ const once = (c: Comment) => {
145
+ if (c.parent) {
146
+ parents.push(c.parent)
147
+ once(c.parent)
148
+ }
149
+ }
150
+
151
+ once(this)
152
+ return parents
153
+ }
154
+
155
+ /** 获取评论元素对象 */
156
+ public getEl() {
157
+ return this.$el
158
+ }
159
+
160
+ /** 获取 Gravatar 头像 URL */
161
+ public getGravatarURL() {
162
+ return Utils.getGravatarURL(this.ctx, this.data.email_encrypted)
163
+ }
164
+
165
+ /** 获取评论 markdown 解析后的内容 */
166
+ public getContentMarked() {
167
+ return Utils.marked(this.ctx, this.data.content)
168
+ }
169
+
170
+ /** 获取格式化后的日期 */
171
+ public getDateFormatted() {
172
+ return Utils.timeAgo(new Date(this.data.date), this.ctx)
173
+ }
174
+
175
+ /** 获取用户 UserAgent 浏览器 */
176
+ public getUserUaBrowser() {
177
+ const info = UADetect(this.data.ua)
178
+ return `${info.browser} ${info.version}`
179
+ }
180
+
181
+ /** 获取用户 UserAgent 系统 */
182
+ public getUserUaOS() {
183
+ const info = UADetect(this.data.ua)
184
+ return `${info.os} ${info.osVersion}`
185
+ }
186
+
187
+ /** 获取配置 */
188
+ public getConf() {
189
+ return this.cConf
190
+ }
191
+ }
@@ -0,0 +1,3 @@
1
+ import Comment from './comment'
2
+
3
+ export default Comment