artalk 2.2.7 → 2.2.10
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 +281 -124
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/index.html +10 -8
- package/package.json +2 -2
- package/src/api/index.ts +16 -0
- package/src/artalk.ts +43 -10
- package/src/components/comment.ts +60 -25
- package/src/components/editor.ts +15 -2
- package/src/components/list-lite.ts +60 -77
- package/src/components/list-nest.ts +66 -0
- package/src/components/list.ts +36 -16
- package/src/components/pagination.ts +1 -1
- package/src/defaults.ts +3 -1
- package/src/lib/utils.ts +30 -0
- package/src/style/_color.less +2 -2
- package/src/style/comment.less +21 -0
- package/types/artalk-config.d.ts +5 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { CommentData } from '~/types/artalk-data'
|
|
2
|
+
|
|
3
|
+
export type CommentNode = {
|
|
4
|
+
id: number
|
|
5
|
+
comment: CommentData
|
|
6
|
+
children: CommentNode[]
|
|
7
|
+
parent?: CommentNode
|
|
8
|
+
level: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type SortByType = 'DATE_DESC'|'DATE_ASC'|'SRC_INDEX'|'VOTE_UP_DESC'
|
|
12
|
+
|
|
13
|
+
// 构建树状结构列表
|
|
14
|
+
export function makeNestCommentNodeList(srcData: CommentData[], sortBy: SortByType = 'DATE_DESC', nestMax = 2) {
|
|
15
|
+
const nodeList: CommentNode[] = []
|
|
16
|
+
|
|
17
|
+
const roots = srcData.filter((o) => o.rid === 0)
|
|
18
|
+
roots.forEach((root: CommentData) => {
|
|
19
|
+
const rootNode: CommentNode = {
|
|
20
|
+
id: root.id,
|
|
21
|
+
comment: root,
|
|
22
|
+
children: [],
|
|
23
|
+
level: 1,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
rootNode.parent = rootNode
|
|
27
|
+
nodeList.push(rootNode)
|
|
28
|
+
|
|
29
|
+
;(function loadChildren(parentNode: CommentNode) {
|
|
30
|
+
const children = srcData.filter((o) => o.rid === parentNode.id)
|
|
31
|
+
if (children.length === 0) return
|
|
32
|
+
if (parentNode.level >= nestMax) parentNode = parentNode.parent!
|
|
33
|
+
children.forEach((child: CommentData) => {
|
|
34
|
+
const childNode: CommentNode = {
|
|
35
|
+
id: child.id,
|
|
36
|
+
comment: child,
|
|
37
|
+
children: [],
|
|
38
|
+
parent: parentNode,
|
|
39
|
+
level: parentNode.level + 1,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
parentNode.children.push(childNode)
|
|
43
|
+
loadChildren(childNode)
|
|
44
|
+
})
|
|
45
|
+
})(rootNode)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// 排序
|
|
49
|
+
const sortFunc = (a: CommentNode, b: CommentNode): number => {
|
|
50
|
+
let v = a.id - b.id
|
|
51
|
+
if (sortBy === 'DATE_ASC') v = +new Date(a.comment.date) - +new Date(b.comment.date)
|
|
52
|
+
else if (sortBy === 'DATE_DESC') v = +new Date(b.comment.date) - +new Date(a.comment.date)
|
|
53
|
+
else if (sortBy === 'SRC_INDEX') v = srcData.indexOf(a.comment) - srcData.indexOf(b.comment)
|
|
54
|
+
else if (sortBy === 'VOTE_UP_DESC') v = b.comment.vote_up - a.comment.vote_up
|
|
55
|
+
return v
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
(function sortLevels(nodes: CommentNode[]) {
|
|
59
|
+
nodes.forEach((node) => {
|
|
60
|
+
node.children = node.children.sort(sortFunc)
|
|
61
|
+
sortLevels(node.children)
|
|
62
|
+
})
|
|
63
|
+
})(nodeList)
|
|
64
|
+
|
|
65
|
+
return nodeList
|
|
66
|
+
}
|
package/src/components/list.ts
CHANGED
|
@@ -112,11 +112,19 @@ export default class List extends ListLite {
|
|
|
112
112
|
super.onLoad(data, offset)
|
|
113
113
|
|
|
114
114
|
// 检测锚点跳转
|
|
115
|
-
this.checkGoToCommentByUrlHash()
|
|
115
|
+
if (!this.goToCommentFounded) this.checkGoToCommentByUrlHash()
|
|
116
|
+
|
|
117
|
+
// 防止评论框被吞
|
|
118
|
+
if (this.ctx.conf.editorTravel === true) {
|
|
119
|
+
this.ctx.trigger('editor-travel-back')
|
|
120
|
+
}
|
|
116
121
|
}
|
|
117
122
|
|
|
123
|
+
private goToCommentFounded = false
|
|
124
|
+
public goToCommentDelay = true
|
|
125
|
+
|
|
118
126
|
/** 跳到评论项位置 - 根据 `location.hash` */
|
|
119
|
-
public
|
|
127
|
+
public checkGoToCommentByUrlHash() {
|
|
120
128
|
let commentId = Number(Utils.getQueryParam('atk_comment')) // same as backend GetReplyLink()
|
|
121
129
|
if (!commentId) {
|
|
122
130
|
const match = window.location.hash.match(/#atk-comment-([0-9]+)/)
|
|
@@ -125,6 +133,14 @@ export default class List extends ListLite {
|
|
|
125
133
|
}
|
|
126
134
|
if (!commentId) return
|
|
127
135
|
|
|
136
|
+
const comment = this.findComment(commentId)
|
|
137
|
+
if (!comment) { // 若找不到评论
|
|
138
|
+
// 自动翻页
|
|
139
|
+
if (this.readMoreBtn) this.readMoreBtn.click()
|
|
140
|
+
else if (this.pagination) this.pagination.next()
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
128
144
|
// 已阅 API
|
|
129
145
|
const notifyKey = Utils.getQueryParam('atk_notify_key')
|
|
130
146
|
if (notifyKey) {
|
|
@@ -137,20 +153,24 @@ export default class List extends ListLite {
|
|
|
137
153
|
})
|
|
138
154
|
}
|
|
139
155
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
156
|
+
// 若父评论存在 “子评论部分” 限高,取消限高
|
|
157
|
+
comment.getParents().forEach((p) => {
|
|
158
|
+
if (p.$children) p.heightLimitRemove(p.$children)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
const goTo = () => {
|
|
162
|
+
Ui.scrollIntoView(comment.getEl(), false)
|
|
163
|
+
|
|
164
|
+
comment.getEl().classList.remove('atk-flash-once')
|
|
165
|
+
window.setTimeout(() => {
|
|
166
|
+
comment.getEl().classList.add('atk-flash-once')
|
|
167
|
+
}, 150)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (!this.goToCommentDelay) goTo()
|
|
171
|
+
else window.setTimeout(() => goTo(), 350)
|
|
172
|
+
|
|
173
|
+
this.goToCommentFounded = true
|
|
154
174
|
}
|
|
155
175
|
|
|
156
176
|
/** 管理员设置页面信息 */
|
|
@@ -38,7 +38,7 @@ export default class Pagination {
|
|
|
38
38
|
`<div class="atk-pagination-wrap">
|
|
39
39
|
<div class="atk-pagination">
|
|
40
40
|
<div class="atk-btn atk-btn-prev">Prev</div>
|
|
41
|
-
<input type="text" class="atk-input" />
|
|
41
|
+
<input type="text" class="atk-input" aria-label="Enter the number of page" />
|
|
42
42
|
<div class="atk-btn atk-btn-next">Next</div>
|
|
43
43
|
</div>
|
|
44
44
|
</div>`)
|
package/src/defaults.ts
CHANGED
|
@@ -20,7 +20,8 @@ const defaults: ArtalkConfig = {
|
|
|
20
20
|
listSort: true,
|
|
21
21
|
pvEl: '#ArtalkPV',
|
|
22
22
|
flatMode: 'auto',
|
|
23
|
-
|
|
23
|
+
nestMax: 2,
|
|
24
|
+
|
|
24
25
|
gravatar: {
|
|
25
26
|
default: 'mp',
|
|
26
27
|
mirror: 'https://sdn.geekzu.org/avatar/',
|
|
@@ -40,6 +41,7 @@ const defaults: ArtalkConfig = {
|
|
|
40
41
|
imgUpload: true,
|
|
41
42
|
reqTimeout: 15000,
|
|
42
43
|
versionCheck: true,
|
|
44
|
+
useBackendConf: false,
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
export default defaults
|
package/src/lib/utils.ts
CHANGED
|
@@ -293,3 +293,33 @@ export function getURLBasedOnApi(ctx: Context, path: string) {
|
|
|
293
293
|
export function getURLBasedOn(baseURL: string, path: string) {
|
|
294
294
|
return `${baseURL.replace(/\/$/, '')}/${path.replace(/^\//, '')}`
|
|
295
295
|
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Performs a deep merge of `source` into `target`.
|
|
299
|
+
* Mutates `target` only but not its objects and arrays.
|
|
300
|
+
*
|
|
301
|
+
* @author inspired by [jhildenbiddle](https://stackoverflow.com/a/48218209).
|
|
302
|
+
* @link https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6
|
|
303
|
+
*/
|
|
304
|
+
export function mergeDeep(target: any, source: any) {
|
|
305
|
+
const isObject = (obj: any) => obj && typeof obj === 'object'
|
|
306
|
+
|
|
307
|
+
if (!isObject(target) || !isObject(source)) {
|
|
308
|
+
return source
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
Object.keys(source).forEach(key => {
|
|
312
|
+
const targetValue = target[key]
|
|
313
|
+
const sourceValue = source[key]
|
|
314
|
+
|
|
315
|
+
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
|
|
316
|
+
target[key] = targetValue.concat(sourceValue)
|
|
317
|
+
} else if (isObject(targetValue) && isObject(sourceValue)) {
|
|
318
|
+
target[key] = mergeDeep({ ...targetValue}, sourceValue)
|
|
319
|
+
} else {
|
|
320
|
+
target[key] = sourceValue
|
|
321
|
+
}
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
return target
|
|
325
|
+
}
|
package/src/style/_color.less
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
--at-color-font: #2a2e2e;
|
|
3
3
|
--at-color-deep: #2a2e2e;
|
|
4
4
|
--at-color-sub: #757575;
|
|
5
|
-
--at-color-grey: #
|
|
6
|
-
--at-color-meta: #
|
|
5
|
+
--at-color-grey: #747474;
|
|
6
|
+
--at-color-meta: #697182;
|
|
7
7
|
--at-color-border: #eceff2;
|
|
8
8
|
--at-color-light: #4285f4;
|
|
9
9
|
--at-color-bg: #FFF;
|
package/src/style/comment.less
CHANGED
|
@@ -83,6 +83,27 @@
|
|
|
83
83
|
color: var(--at-color-main);
|
|
84
84
|
text-decoration: none;
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
&.atk-reply-at {
|
|
88
|
+
margin-left: 2px;
|
|
89
|
+
|
|
90
|
+
& > .atk-arrow:before {
|
|
91
|
+
content: '';
|
|
92
|
+
vertical-align: middle;
|
|
93
|
+
transform: rotate(90deg);
|
|
94
|
+
border-bottom: 4px solid var(--at-color-grey);
|
|
95
|
+
border-left: 3px solid transparent;
|
|
96
|
+
border-right: 3px solid transparent;
|
|
97
|
+
display: inline-block;
|
|
98
|
+
margin-top: -1px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
& > .atk-nick {
|
|
102
|
+
color: var(--at-color-main);
|
|
103
|
+
cursor: pointer;
|
|
104
|
+
margin-left: 6px;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
86
107
|
}
|
|
87
108
|
|
|
88
109
|
.badge() {
|
package/types/artalk-config.d.ts
CHANGED
|
@@ -74,8 +74,8 @@ export default interface ArtalkConfig {
|
|
|
74
74
|
/** 平铺模式 */
|
|
75
75
|
flatMode?: boolean|'auto'
|
|
76
76
|
|
|
77
|
-
/**
|
|
78
|
-
|
|
77
|
+
/** 嵌套模式 · 最大层数 */
|
|
78
|
+
nestMax?: number
|
|
79
79
|
|
|
80
80
|
/** 显示 UA 徽标 */
|
|
81
81
|
uaBadge?: boolean
|
|
@@ -88,6 +88,9 @@ export default interface ArtalkConfig {
|
|
|
88
88
|
|
|
89
89
|
/** 版本检测 */
|
|
90
90
|
versionCheck?: boolean
|
|
91
|
+
|
|
92
|
+
/** 复用后端配置 */
|
|
93
|
+
useBackendConf?: boolean
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
export interface LocalUser {
|