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.
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +1872 -1143
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/dist/ArtalkLite.css +1 -0
- package/dist/ArtalkLite.es.js +5123 -0
- package/dist/ArtalkLite.iife.js +1 -0
- package/dist/ArtalkLite.js +1 -0
- package/index.html +5 -3
- package/package.json +7 -5
- package/src/api/index.ts +24 -4
- package/src/api/request.ts +50 -81
- package/src/artalk.ts +131 -127
- package/src/comment/actions.ts +86 -0
- package/src/{components/html → comment}/comment.html +1 -1
- package/src/comment/comment.ts +191 -0
- package/src/comment/index.ts +3 -0
- package/src/comment/render.ts +425 -0
- package/src/components/action-btn.ts +6 -3
- package/src/components/dialog.ts +7 -3
- package/src/components/read-more-btn.ts +6 -2
- package/src/context.ts +204 -13
- package/src/defaults.ts +15 -4
- package/src/editor/editor.html +18 -0
- package/src/editor/editor.ts +419 -0
- package/src/editor/index.ts +3 -0
- package/src/editor/plugs/editor-plug.ts +51 -0
- package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.less +2 -1
- package/src/{components/editor-plugs → editor/plugs}/emoticons-plug.ts +65 -63
- package/src/editor/plugs/header-input-plug.ts +78 -0
- package/src/{components/editor-plugs → editor/plugs}/preview-plug.less +0 -0
- package/src/editor/plugs/preview-plug.ts +40 -0
- package/src/editor/plugs/upload-plug.ts +124 -0
- package/src/i18n/en.ts +78 -0
- package/src/i18n/index.ts +21 -0
- package/src/i18n/zh-CN.ts +82 -0
- package/src/layer/index.ts +4 -0
- package/src/{components → layer}/layer.ts +9 -9
- package/src/{components/html → layer}/sidebar-layer.html +0 -0
- package/src/{components → layer}/sidebar-layer.ts +17 -47
- package/src/lib/checker/admin-checker.ts +7 -7
- package/src/lib/checker/captcha-checker.ts +5 -6
- package/src/lib/checker/index.ts +22 -17
- package/src/lib/component.ts +7 -2
- package/src/lib/stat.ts +63 -0
- package/src/lib/ui.ts +3 -10
- package/src/lib/user.ts +20 -3
- package/src/lib/utils.ts +23 -9
- package/src/list/index.ts +3 -0
- package/src/{components → list}/list-lite.ts +83 -111
- package/src/{components → list}/list-nest.ts +0 -0
- package/src/{components/html → list}/list.html +3 -6
- package/src/{components → list}/list.ts +44 -42
- package/src/style/_variables.less +1 -2
- package/src/style/comment.less +26 -13
- package/src/style/editor.less +22 -14
- package/src/style/list.less +6 -9
- package/src/style/main.less +9 -8
- package/src/style/pagination.less +1 -1
- package/test/ArtalkCount.html +16 -0
- package/test/ArtalkI18n.html +15 -0
- package/test/ArtalkLite.html +15 -0
- package/types/artalk-config.d.ts +50 -32
- package/types/context.d.ts +128 -0
- package/types/event.d.ts +6 -66
- package/types/global.d.ts +1 -0
- package/types/plug.d.ts +4 -0
- package/{vite-common.config.ts → vite-base.config.ts} +6 -4
- package/vite-demo.config.ts +2 -4
- package/vite-lite.config.ts +22 -0
- package/vite.config.ts +9 -18
- package/src/components/_component.ts.txt +0 -10
- package/src/components/comment.ts +0 -605
- package/src/components/editor-plugs/_example-plug.ts.txt +0 -29
- package/src/components/editor-plugs/editor-plug.ts +0 -20
- package/src/components/editor-plugs/preview-plug.ts +0 -48
- package/src/components/editor.ts +0 -604
- 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
|
+
}
|
|
@@ -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
|
+
}
|