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.
@@ -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
+ }
@@ -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 async checkGoToCommentByUrlHash () {
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
- const comment = this.findComment(commentId)
141
- // TODO 若找不到评论的情况
142
- // if (!comment) { // 若找不到评论
143
- // if (this.hasMoreComments) { // 阅读更多,并重试
144
- // await this.fetchComments()
145
- // }
146
- // }
147
-
148
- if (!comment) return
149
-
150
- Ui.scrollIntoView(comment.getEl(), false)
151
- window.setTimeout(() => {
152
- comment.getEl().classList.add('atk-flash-once')
153
- }, 800)
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
- maxNesting: 3,
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
+ }
@@ -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: #999;
6
- --at-color-meta: #757e91;
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;
@@ -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() {
@@ -74,8 +74,8 @@ export default interface ArtalkConfig {
74
74
  /** 平铺模式 */
75
75
  flatMode?: boolean|'auto'
76
76
 
77
- /** 最大嵌套数 */
78
- maxNesting?: number
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 {