artalk 2.7.0 → 2.7.2

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 (175) hide show
  1. package/README.md +1 -1
  2. package/dist/Artalk.css +1 -1
  3. package/dist/Artalk.es.js +209 -188
  4. package/dist/Artalk.es.js.map +1 -0
  5. package/dist/Artalk.iife.js +2 -1
  6. package/dist/Artalk.iife.js.map +1 -0
  7. package/dist/Artalk.js +2 -1
  8. package/dist/Artalk.js.map +1 -0
  9. package/dist/ArtalkLite.css +1 -1
  10. package/dist/ArtalkLite.es.js +209 -188
  11. package/dist/ArtalkLite.es.js.map +1 -0
  12. package/dist/ArtalkLite.iife.js +2 -1
  13. package/dist/ArtalkLite.iife.js.map +1 -0
  14. package/dist/ArtalkLite.js +2 -1
  15. package/dist/ArtalkLite.js.map +1 -0
  16. package/dist/i18n/jp.js +1 -1
  17. package/dist/i18n/zh-TW.js +1 -1
  18. package/dist/src/api/_base.d.ts +7 -0
  19. package/dist/src/api/_options.d.ts +5 -0
  20. package/dist/src/artalk.d.ts +0 -2
  21. package/dist/src/components/checker/index.d.ts +2 -0
  22. package/dist/src/i18n/en.d.ts +4 -0
  23. package/dist/src/i18n/external.d.ts +4 -0
  24. package/dist/src/i18n/index.d.ts +12 -0
  25. package/dist/src/i18n/jp.d.ts +4 -0
  26. package/dist/src/i18n/zh-TW.d.ts +4 -0
  27. package/dist/src/lib/user.d.ts +8 -6
  28. package/dist/src/main.d.ts +3 -0
  29. package/dist/src/plugins/editor/_kit.d.ts +7 -1
  30. package/dist/src/service.d.ts +2 -8
  31. package/dist/types/event.d.ts +1 -1
  32. package/package.json +43 -17
  33. package/dist/src/components/dark-mode.d.ts +0 -2
  34. package/src/api/_base.ts +0 -18
  35. package/src/api/_options.ts +0 -25
  36. package/src/api/_request.ts +0 -104
  37. package/src/api/admin.ts +0 -18
  38. package/src/api/captcha.ts +0 -24
  39. package/src/api/comment.ts +0 -84
  40. package/src/api/index.ts +0 -29
  41. package/src/api/page.ts +0 -83
  42. package/src/api/site.ts +0 -51
  43. package/src/api/system.ts +0 -49
  44. package/src/api/upload.ts +0 -28
  45. package/src/api/user.ts +0 -132
  46. package/src/artalk.ts +0 -119
  47. package/src/comment/actions.ts +0 -83
  48. package/src/comment/comment.html +0 -18
  49. package/src/comment/comment.ts +0 -192
  50. package/src/comment/height-limit.ts +0 -100
  51. package/src/comment/index.ts +0 -3
  52. package/src/comment/render.ts +0 -150
  53. package/src/comment/renders/actions.ts +0 -114
  54. package/src/comment/renders/avatar.ts +0 -22
  55. package/src/comment/renders/content.ts +0 -39
  56. package/src/comment/renders/header.ts +0 -84
  57. package/src/comment/renders/index.ts +0 -19
  58. package/src/comment/renders/pending.ts +0 -12
  59. package/src/comment/renders/reply-at.ts +0 -16
  60. package/src/comment/renders/reply-to.ts +0 -24
  61. package/src/components/action-btn.ts +0 -170
  62. package/src/components/checker/admin.ts +0 -37
  63. package/src/components/checker/captcha-renders.ts +0 -69
  64. package/src/components/checker/captcha.ts +0 -26
  65. package/src/components/checker/index.ts +0 -192
  66. package/src/components/dark-mode.ts +0 -30
  67. package/src/components/dialog.ts +0 -62
  68. package/src/components/error-dialog.ts +0 -35
  69. package/src/components/pagination.ts +0 -153
  70. package/src/components/read-more-btn.ts +0 -92
  71. package/src/config.ts +0 -119
  72. package/src/context.ts +0 -146
  73. package/src/data.ts +0 -110
  74. package/src/defaults.ts +0 -61
  75. package/src/editor/editor.html +0 -18
  76. package/src/editor/editor.ts +0 -114
  77. package/src/editor/state.ts +0 -52
  78. package/src/editor/ui.ts +0 -36
  79. package/src/i18n/en.ts +0 -81
  80. package/src/i18n/external.ts +0 -10
  81. package/src/i18n/index.ts +0 -67
  82. package/src/i18n/jp.ts +0 -83
  83. package/src/i18n/zh-CN.ts +0 -85
  84. package/src/i18n/zh-TW.ts +0 -83
  85. package/src/layer/index.ts +0 -4
  86. package/src/layer/layer-manager.ts +0 -32
  87. package/src/layer/layer.ts +0 -39
  88. package/src/layer/scrollbar-helper.ts +0 -24
  89. package/src/layer/sidebar-layer.html +0 -8
  90. package/src/layer/sidebar-layer.ts +0 -155
  91. package/src/layer/wrap.ts +0 -77
  92. package/src/lib/component.ts +0 -12
  93. package/src/lib/detect.ts +0 -222
  94. package/src/lib/event-manager.ts +0 -47
  95. package/src/lib/highlight.ts +0 -5
  96. package/src/lib/marked-renderer.ts +0 -32
  97. package/src/lib/marked.ts +0 -72
  98. package/src/lib/sanitizer.ts +0 -57
  99. package/src/lib/ui.ts +0 -193
  100. package/src/lib/user.ts +0 -55
  101. package/src/lib/utils.ts +0 -236
  102. package/src/list/comment.ts +0 -20
  103. package/src/list/layout.ts +0 -120
  104. package/src/list/list.html +0 -20
  105. package/src/list/list.ts +0 -79
  106. package/src/list/nest.ts +0 -66
  107. package/src/list/page.ts +0 -97
  108. package/src/list/paginator/index.ts +0 -25
  109. package/src/list/paginator/read-more.ts +0 -67
  110. package/src/list/paginator/up-down.ts +0 -51
  111. package/src/main.ts +0 -5
  112. package/src/plugins/admin-only-elem.ts +0 -40
  113. package/src/plugins/conf-remoter.ts +0 -54
  114. package/src/plugins/dark-mode.ts +0 -12
  115. package/src/plugins/editor/_kit.ts +0 -57
  116. package/src/plugins/editor/_plug.ts +0 -60
  117. package/src/plugins/editor/_sample.ts +0 -8
  118. package/src/plugins/editor/closable.ts +0 -44
  119. package/src/plugins/editor/emoticons.scss +0 -72
  120. package/src/plugins/editor/emoticons.ts +0 -293
  121. package/src/plugins/editor/header-event.ts +0 -35
  122. package/src/plugins/editor/header-link.ts +0 -31
  123. package/src/plugins/editor/header-user.ts +0 -98
  124. package/src/plugins/editor/index.ts +0 -40
  125. package/src/plugins/editor/local-storage.ts +0 -36
  126. package/src/plugins/editor/mover.ts +0 -29
  127. package/src/plugins/editor/preview.scss +0 -7
  128. package/src/plugins/editor/preview.ts +0 -41
  129. package/src/plugins/editor/state-edit.ts +0 -116
  130. package/src/plugins/editor/state-reply.ts +0 -91
  131. package/src/plugins/editor/submit-add.ts +0 -33
  132. package/src/plugins/editor/submit-btn.ts +0 -25
  133. package/src/plugins/editor/submit.ts +0 -73
  134. package/src/plugins/editor/textarea.ts +0 -55
  135. package/src/plugins/editor/upload.ts +0 -145
  136. package/src/plugins/editor-kit.ts +0 -161
  137. package/src/plugins/index.ts +0 -16
  138. package/src/plugins/list/copyright.ts +0 -16
  139. package/src/plugins/list/count.ts +0 -31
  140. package/src/plugins/list/dropdown.ts +0 -95
  141. package/src/plugins/list/error-dialog.ts +0 -22
  142. package/src/plugins/list/fetch.ts +0 -64
  143. package/src/plugins/list/goto-first.ts +0 -23
  144. package/src/plugins/list/goto.ts +0 -72
  145. package/src/plugins/list/index.ts +0 -25
  146. package/src/plugins/list/loading.ts +0 -17
  147. package/src/plugins/list/no-comment.ts +0 -25
  148. package/src/plugins/list/reach-bottom.ts +0 -46
  149. package/src/plugins/list/sidebar-btn.ts +0 -39
  150. package/src/plugins/list/time-ticking.ts +0 -22
  151. package/src/plugins/list/unread-badge.ts +0 -26
  152. package/src/plugins/list/unread.ts +0 -38
  153. package/src/plugins/list/with-editor.ts +0 -59
  154. package/src/plugins/markdown.ts +0 -10
  155. package/src/plugins/stat.ts +0 -79
  156. package/src/plugins/version-check.ts +0 -37
  157. package/src/service.ts +0 -91
  158. package/src/style/_color.scss +0 -41
  159. package/src/style/_extend.scss +0 -20
  160. package/src/style/_variables.scss +0 -3
  161. package/src/style/comment.scss +0 -360
  162. package/src/style/editor.scss +0 -194
  163. package/src/style/list.scss +0 -212
  164. package/src/style/main.scss +0 -486
  165. package/src/style/pagination.scss +0 -58
  166. package/src/style/sidebar-layer.scss +0 -92
  167. package/types/config.ts +0 -153
  168. package/types/context.ts +0 -84
  169. package/types/data.ts +0 -271
  170. package/types/editor.ts +0 -95
  171. package/types/event.ts +0 -40
  172. package/types/global.d.ts +0 -1
  173. package/types/index.ts +0 -7
  174. package/types/plugin.ts +0 -3
  175. package/types/sidebar.ts +0 -3
@@ -1,192 +0,0 @@
1
- import type { CommentData, ContextApi } from '~/types'
2
- import Component from '../lib/component'
3
- import * as Utils from '../lib/utils'
4
- import marked from '../lib/marked'
5
- import UADetect from '../lib/detect'
6
- import CommentUI 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: CommentUI
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: ContextApi, 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 CommentUI(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().checkHeightLimit()
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({
163
- mirror: this.ctx.conf.gravatar.mirror,
164
- params: this.ctx.conf.gravatar.params,
165
- emailMD5: this.data.email_encrypted,
166
- })
167
- }
168
-
169
- /** 获取评论 markdown 解析后的内容 */
170
- public getContentMarked() {
171
- return marked(this.data.content)
172
- }
173
-
174
- /** 获取格式化后的日期 */
175
- public getDateFormatted() {
176
- return Utils.timeAgo(new Date(this.data.date), this.ctx.$t)
177
- }
178
-
179
- /** 获取用户 UserAgent 信息 */
180
- public getUserUA() {
181
- const info = UADetect(this.data.ua)
182
- return {
183
- browser: `${info.browser} ${info.version}`,
184
- os: `${info.os} ${info.osVersion}`
185
- }
186
- }
187
-
188
- /** 获取配置 */
189
- public getConf() {
190
- return this.cConf
191
- }
192
- }
@@ -1,100 +0,0 @@
1
- import * as Utils from '../lib/utils'
2
- import $t from '../i18n'
3
-
4
- export interface IHeightLimitConf {
5
- /** Post expand btn click */
6
- postExpandBtnClick?: (e: MouseEvent) => void
7
- /** Allow Scroll */
8
- scrollable?: boolean
9
- }
10
-
11
- export interface IHeightLimitRule {
12
- /** Target element need to check */
13
- el: HTMLElement|null|undefined
14
-
15
- /** Max height (unit: px) */
16
- max: number
17
-
18
- /** Whether or not the element contains `<img />` */
19
- imgContains?: boolean
20
- }
21
-
22
- export type THeightLimitRuleSet = IHeightLimitRule[]
23
-
24
- /** Check all elements below the max height limit */
25
- export function check(conf: IHeightLimitConf, rules: THeightLimitRuleSet) {
26
- rules.forEach(({
27
- el, max: maxHeight, imgContains
28
- }) => {
29
- const _apply = () => {
30
- if (!el) return
31
- if (!conf.scrollable)
32
- applyHeightLimit({ el, maxHeight, postBtnClick: conf.postExpandBtnClick })
33
- else
34
- applyScrollableHeightLimit({ el, maxHeight })
35
- }
36
-
37
- // checking
38
- const _check = () => {
39
- if (el && Utils.getHeight(el) > maxHeight) _apply() // 是否超过高度
40
- }
41
- _check() // check now
42
- if (imgContains && el) // check again if img contains
43
- Utils.onImagesLoaded(el, () => _check())
44
- })
45
- }
46
-
47
- /** Height limit CSS class name */
48
- const HEIGHT_LIMIT_CSS = 'atk-height-limit'
49
-
50
- /** Apply height limit on an element and add expand btn */
51
- export function applyHeightLimit(obj: {
52
- el: HTMLElement,
53
- maxHeight: number,
54
- postBtnClick?: (e: MouseEvent) => void
55
- }) {
56
- if (!obj.el) return
57
- if (!obj.maxHeight) return
58
- if (obj.el.classList.contains(HEIGHT_LIMIT_CSS)) return
59
-
60
- obj.el.classList.add(HEIGHT_LIMIT_CSS)
61
- obj.el.style.height = `${obj.maxHeight}px`
62
- obj.el.style.overflow = 'hidden'
63
-
64
- /* Expand button */
65
- const $expandBtn = Utils.createElement(`<div class="atk-height-limit-btn">${$t('readMore')}</span>`)
66
- $expandBtn.onclick = (e) => {
67
- e.stopPropagation()
68
- disposeHeightLimit(obj.el)
69
-
70
- if (obj.postBtnClick) obj.postBtnClick(e)
71
- }
72
- obj.el.append($expandBtn)
73
- }
74
-
75
- /** Dispose height limit on an element and remove expand btn */
76
- export function disposeHeightLimit($el: HTMLElement) {
77
- if (!$el) return
78
- if (!$el.classList.contains(HEIGHT_LIMIT_CSS)) return
79
-
80
- $el.classList.remove(HEIGHT_LIMIT_CSS)
81
- Array.from($el.children).forEach((e) => {
82
- if (e.classList.contains('atk-height-limit-btn')) e.remove()
83
- })
84
- $el.style.height = ''
85
- $el.style.overflow = ''
86
- }
87
-
88
- /** Height limit scrollable CSS class name */
89
- const HEIGHT_LIMIT_SCROLL_CSS = 'atk-height-limit-scroll'
90
-
91
- /** Apply scrollable height limit */
92
- export function applyScrollableHeightLimit(obj: {
93
- el: HTMLElement,
94
- maxHeight: number
95
- }) {
96
- if (!obj.el) return
97
- if (obj.el.classList.contains(HEIGHT_LIMIT_SCROLL_CSS)) return
98
- obj.el.classList.add(HEIGHT_LIMIT_SCROLL_CSS)
99
- obj.el.style.height = `${obj.maxHeight}px`
100
- }
@@ -1,3 +0,0 @@
1
- import Comment from './comment'
2
-
3
- export default Comment
@@ -1,150 +0,0 @@
1
- import type Comment from './comment'
2
- import ActionBtn from '../components/action-btn'
3
- import * as Utils from '../lib/utils'
4
- import * as Ui from '../lib/ui'
5
-
6
- import * as HeightLimit from './height-limit'
7
- import CommentHTML from './comment.html?raw'
8
- import loadRenders from './renders'
9
-
10
- export default class Render {
11
- public comment: Comment
12
-
13
- public get ctx() { return this.comment.ctx }
14
- public get data() { return this.comment.getData() }
15
- public get conf() { return this.comment.conf }
16
- public get cConf() { return this.comment.getConf() }
17
-
18
- public $el!: HTMLElement
19
- public $main!: HTMLElement
20
- public $header!: HTMLElement
21
- public $headerNick!: HTMLElement
22
- public $headerBadgeWrap!: HTMLElement
23
- public $body!: HTMLElement
24
- public $content!: HTMLElement
25
- public $childrenWrap!: HTMLElement|null
26
- public $actions!: HTMLElement
27
- public voteBtnUp?: ActionBtn
28
- public voteBtnDown?: ActionBtn
29
-
30
- public $replyTo?: HTMLElement // 回复评论内容 (平铺下显示)
31
- public $replyAt?: HTMLElement // 回复 AT(层级嵌套下显示)
32
-
33
- public constructor(comment: Comment) {
34
- this.comment = comment
35
- }
36
-
37
- public render() {
38
- // init ui elements
39
- this.$el = Utils.createElement(CommentHTML)
40
-
41
- this.$main = this.$el.querySelector('.atk-main')!
42
- this.$header = this.$el.querySelector('.atk-header')!
43
- this.$body = this.$el.querySelector('.atk-body')!
44
- this.$content = this.$body.querySelector('.atk-content')!
45
- this.$actions = this.$el.querySelector('.atk-actions')!
46
-
47
- this.$el.setAttribute('id', `atk-comment-${this.data.id}`)
48
-
49
- // call all renders
50
- loadRenders(this)
51
-
52
- this.recoveryChildrenWrap()
53
-
54
- return this.$el
55
- }
56
-
57
- /** 内容限高检测 */
58
- public checkHeightLimit() {
59
- const conf = this.ctx.conf.heightLimit
60
- if (!conf || !conf.content || !conf.children) return // 关闭限高
61
-
62
- const contentMaxH = conf.content
63
- const childrenMaxH = conf.children
64
-
65
- HeightLimit.check({
66
- postExpandBtnClick: () => {
67
- // 子评论数仅有 1,直接取消限高
68
- const children = this.comment.getChildren()
69
- if (children.length === 1) HeightLimit.disposeHeightLimit(children[0].getRender().$content)
70
- },
71
- scrollable: conf.scrollable
72
- }, [
73
- // 评论内容限高
74
- { el: this.$content, max: contentMaxH, imgContains: true },
75
- { el: this.$replyTo, max: contentMaxH, imgContains: true },
76
- // 子评论区域限高(仅嵌套模式)
77
- { el: this.$childrenWrap, max: childrenMaxH, imgContains: false }
78
- ])
79
- }
80
-
81
- /** 子评论区域移除限高 */
82
- public heightLimitRemoveForChildren() {
83
- if (!this.$childrenWrap) return
84
- HeightLimit.disposeHeightLimit(this.$childrenWrap)
85
- }
86
-
87
- /** 渐出动画 */
88
- playFadeAnim() {
89
- Ui.playFadeInAnim(this.comment.getRender().$el)
90
- }
91
-
92
- /** 渐出动画 · 评论内容区域 */
93
- playFadeAnimForBody() {
94
- Ui.playFadeInAnim(this.comment.getRender().$body)
95
- }
96
-
97
- /** 获取子评论 Wrap */
98
- public getChildrenWrap() {
99
- return this.$childrenWrap
100
- }
101
-
102
- /** 初始化子评论区域 Wrap */
103
- public renderChildrenWrap() {
104
- if (!this.$childrenWrap) {
105
- this.$childrenWrap = Utils.createElement('<div class="atk-comment-children"></div>')
106
- this.$main.append(this.$childrenWrap)
107
- }
108
-
109
- return this.$childrenWrap
110
- }
111
-
112
- /** 恢复原有的子评论区域 Wrap */
113
- public recoveryChildrenWrap() {
114
- if (this.$childrenWrap) {
115
- this.$main.append(this.$childrenWrap)
116
- }
117
- }
118
-
119
- /** 设置已读 */
120
- public setUnread(val: boolean) {
121
- if (val) this.$el.classList.add('atk-unread')
122
- else this.$el.classList.remove('atk-unread')
123
- }
124
-
125
- /** 设置为可点击的评论 */
126
- public setOpenable(val: boolean) {
127
- if (val) this.$el.classList.add('atk-openable')
128
- else this.$el.classList.remove('atk-openable')
129
- }
130
-
131
- /** 设置点击评论打开置顶 URL */
132
- public setOpenURL(url: string) {
133
- this.setOpenable(true)
134
- this.$el.onclick = (evt) => {
135
- evt.preventDefault()
136
- window.open(url)
137
-
138
- if (this.cConf.openEvt) this.cConf.openEvt()
139
- }
140
- }
141
-
142
- /** 设置点击评论时的操作 */
143
- public setOpenAction(action: () => void) {
144
- this.setOpenable(true)
145
- this.$el.onclick = (evt) => {
146
- evt.preventDefault()
147
- action()
148
- }
149
- }
150
- }
@@ -1,114 +0,0 @@
1
- import * as Utils from '../../lib/utils'
2
- import ActionBtn from '../../components/action-btn'
3
- import type Render from '../render'
4
-
5
- /**
6
- * 评论操作按钮界面
7
- */
8
- export default function renderActions(r: Render) {
9
- Object.entries({
10
- renderVote, renderReply,
11
- // 管理员操作
12
- renderCollapse, renderModerator, renderPin, renderEdit, renderDel
13
- }).forEach(([name, render]) => {
14
- render(r)
15
- })
16
- }
17
-
18
-
19
- // 操作按钮 - 投票
20
- function renderVote(r: Render) {
21
- if (!r.ctx.conf.vote) return // 关闭投票功能
22
-
23
- // 赞同按钮
24
- r.voteBtnUp = new ActionBtn(() => `${r.ctx.$t('voteUp')} (${r.data.vote_up || 0})`).appendTo(r.$actions)
25
- r.voteBtnUp.setClick(() => {
26
- r.comment.getActions().vote('up')
27
- })
28
-
29
- // 反对按钮
30
- if (r.ctx.conf.voteDown) {
31
- r.voteBtnDown = new ActionBtn(() => `${r.ctx.$t('voteDown')} (${r.data.vote_down || 0})`).appendTo(r.$actions)
32
- r.voteBtnDown.setClick(() => {
33
- r.comment.getActions().vote('down')
34
- })
35
- }
36
- }
37
-
38
- // 操作按钮 - 回复
39
- function renderReply(r: Render) {
40
- if (!r.data.is_allow_reply) return // 不允许回复
41
-
42
- const replyBtn = Utils.createElement(`<span>${r.ctx.$t('reply')}</span>`)
43
- r.$actions.append(replyBtn)
44
- replyBtn.addEventListener('click', (e) => {
45
- e.stopPropagation() // 防止穿透
46
- if (!r.cConf.onReplyBtnClick) {
47
- r.ctx.replyComment(r.data, r.$el)
48
- } else {
49
- r.cConf.onReplyBtnClick()
50
- }
51
- })
52
- }
53
-
54
- // 操作按钮 - 折叠
55
- function renderCollapse(r: Render) {
56
- const collapseBtn = new ActionBtn({
57
- text: () => (r.data.is_collapsed ? r.ctx.$t('expand') : r.ctx.$t('collapse')),
58
- adminOnly: true
59
- })
60
- collapseBtn.appendTo(r.$actions)
61
- collapseBtn.setClick(() => {
62
- r.comment.getActions().adminEdit('collapsed', collapseBtn)
63
- })
64
- }
65
-
66
- // 操作按钮 - 审核
67
- function renderModerator(r: Render) {
68
- const pendingBtn = new ActionBtn({
69
- text: () => (r.data.is_pending ? r.ctx.$t('pending') : r.ctx.$t('approved')),
70
- adminOnly: true
71
- })
72
- pendingBtn.appendTo(r.$actions)
73
- pendingBtn.setClick(() => {
74
- r.comment.getActions().adminEdit('pending', pendingBtn)
75
- })
76
- }
77
-
78
- // 操作按钮 - 置顶
79
- function renderPin(r: Render) {
80
- const pinnedBtn = new ActionBtn({
81
- text: () => (r.data.is_pinned ? r.ctx.$t('unpin') : r.ctx.$t('pin')),
82
- adminOnly: true
83
- })
84
- pinnedBtn.appendTo(r.$actions)
85
- pinnedBtn.setClick(() => {
86
- r.comment.getActions().adminEdit('pinned', pinnedBtn)
87
- })
88
- }
89
-
90
- // 操作按钮 - 编辑
91
- function renderEdit(r: Render) {
92
- const editBtn = new ActionBtn({
93
- text: r.ctx.$t('edit'),
94
- adminOnly: true
95
- })
96
- editBtn.appendTo(r.$actions)
97
- editBtn.setClick(() => {
98
- r.ctx.editComment(r.data, r.$el)
99
- })
100
- }
101
-
102
- // 操作按钮 - 删除
103
- function renderDel(r: Render) {
104
- const delBtn = new ActionBtn({
105
- text: r.ctx.$t('delete'),
106
- confirm: true,
107
- confirmText: r.ctx.$t('deleteConfirm'),
108
- adminOnly: true,
109
- })
110
- delBtn.appendTo(r.$actions)
111
- delBtn.setClick(() => {
112
- r.comment.getActions().adminDelete(delBtn)
113
- })
114
- }
@@ -1,22 +0,0 @@
1
- import * as Utils from '../../lib/utils'
2
- import type Render from '../render'
3
-
4
- /**
5
- * 评论头像界面
6
- */
7
- export default function renderAvatar(r: Render) {
8
- const $avatar = r.$el.querySelector<HTMLElement>('.atk-avatar')!
9
- const $avatarImg = Utils.createElement<HTMLImageElement>('<img />')
10
-
11
- const avatarURLBuilder = r.conf.avatarURLBuilder
12
- $avatarImg.src = avatarURLBuilder ? avatarURLBuilder(r.data) : r.comment.getGravatarURL()
13
-
14
- if (r.data.link) {
15
- const $avatarA = Utils.createElement<HTMLLinkElement>('<a target="_blank" rel="noreferrer noopener nofollow"></a>')
16
- $avatarA.href = Utils.isValidURL(r.data.link) ? r.data.link : `https://${r.data.link}`
17
- $avatarA.append($avatarImg)
18
- $avatar.append($avatarA)
19
- } else {
20
- $avatar.append($avatarImg)
21
- }
22
- }
@@ -1,39 +0,0 @@
1
- import * as Utils from '../../lib/utils'
2
- import * as Ui from '../../lib/ui'
3
- import type Render from '../render'
4
-
5
- /**
6
- * 评论内容界面
7
- */
8
- export default function renderContent(r: Render) {
9
- if (!r.data.is_collapsed) {
10
- r.$content.innerHTML = r.comment.getContentMarked()
11
- r.$content.classList.remove('atk-hide', 'atk-collapsed')
12
- return
13
- }
14
-
15
- // 内容 & 折叠
16
- r.$content.classList.add('atk-hide', 'atk-type-collapsed')
17
- const collapsedInfoEl = Utils.createElement(`
18
- <div class="atk-collapsed">
19
- <span class="atk-text">${r.ctx.$t('collapsedMsg')}</span>
20
- <span class="atk-show-btn">${r.ctx.$t('expand')}</span>
21
- </div>`)
22
- r.$body.insertAdjacentElement('beforeend', collapsedInfoEl)
23
-
24
- const contentShowBtn = collapsedInfoEl.querySelector<HTMLElement>('.atk-show-btn')!
25
- contentShowBtn.addEventListener('click', (e) => {
26
- e.stopPropagation() // 防止穿透
27
-
28
- if (r.$content.classList.contains('atk-hide')) {
29
- r.$content.innerHTML = r.comment.getContentMarked()
30
- r.$content.classList.remove('atk-hide')
31
- Ui.playFadeInAnim(r.$content)
32
- contentShowBtn.innerText = r.ctx.$t('collapse')
33
- } else {
34
- r.$content.innerHTML = ''
35
- r.$content.classList.add('atk-hide')
36
- contentShowBtn.innerText = r.ctx.$t('expand')
37
- }
38
- })
39
- }
@@ -1,84 +0,0 @@
1
- import * as Utils from '../../lib/utils'
2
- import type Render from '../render'
3
-
4
- /**
5
- * 评论头部界面
6
- */
7
- export default function renderHeader(r: Render) {
8
- Object.entries({
9
- renderNick, renderVerifyBadge, renderDate, renderUABadge
10
- }).forEach(([name, render]) => {
11
- render(r)
12
- })
13
- }
14
-
15
- function renderNick(r: Render) {
16
- r.$headerNick = r.$el.querySelector<HTMLElement>('.atk-nick')!
17
-
18
- if (r.data.link) {
19
- const $nickA = Utils.createElement<HTMLLinkElement>('<a target="_blank" rel="noreferrer noopener nofollow"></a>')
20
- $nickA.innerText = r.data.nick
21
- $nickA.href = Utils.isValidURL(r.data.link) ? r.data.link : `https://${r.data.link}`
22
- r.$headerNick.append($nickA)
23
- } else {
24
- r.$headerNick.innerText = r.data.nick
25
- }
26
- }
27
-
28
- function renderVerifyBadge(ctx: Render) {
29
- ctx.$headerBadgeWrap = ctx.$el.querySelector<HTMLElement>('.atk-badge-wrap')!
30
- ctx.$headerBadgeWrap.innerHTML = ''
31
-
32
- const badgeText = ctx.data.badge_name
33
- const badgeColor = ctx.data.badge_color
34
- if (badgeText) {
35
- const $badge = Utils.createElement(`<span class="atk-badge"></span>`)
36
- $badge.innerText = badgeText.replace('管理员', ctx.ctx.$t('admin')) // i18n patch
37
- $badge.style.backgroundColor = badgeColor || ''
38
- ctx.$headerBadgeWrap.append($badge)
39
- }
40
-
41
- if (ctx.data.is_pinned) {
42
- const $pinnedBadge = Utils.createElement(`<span class="atk-pinned-badge">${ctx.ctx.$t('pin')}</span>`) // 置顶徽章
43
- ctx.$headerBadgeWrap.append($pinnedBadge)
44
- }
45
- }
46
-
47
- function renderDate(ctx: Render) {
48
- const $date = ctx.$el.querySelector<HTMLElement>('.atk-date')!
49
- $date.innerText = ctx.comment.getDateFormatted()
50
- $date.setAttribute('data-atk-comment-date', String(+new Date(ctx.data.date)))
51
- }
52
-
53
- function renderUABadge(ctx: Render) {
54
- if (!ctx.ctx.conf.uaBadge && !ctx.data.ip_region) return
55
-
56
- let $uaWrap = ctx.$header.querySelector('atk-ua-wrap')
57
- if (!$uaWrap) {
58
- $uaWrap = Utils.createElement(`<span class="atk-ua-wrap"></span>`)
59
- ctx.$header.append($uaWrap)
60
- }
61
-
62
- $uaWrap.innerHTML = ''
63
-
64
- if (ctx.data.ip_region) {
65
- const $regionBadge = Utils.createElement(`<span class="atk-region-badge"></span>`)
66
- $regionBadge.innerText = ctx.data.ip_region
67
- $uaWrap.append($regionBadge)
68
- }
69
-
70
- if (ctx.ctx.conf.uaBadge) {
71
- const { browser, os } = ctx.comment.getUserUA()
72
- if (String(browser).trim()) {
73
- const $uaBrowser = Utils.createElement(`<span class="atk-ua ua-browser"></span>`)
74
- $uaBrowser.innerText = browser
75
- $uaWrap.append($uaBrowser)
76
- }
77
-
78
- if (String(os).trim()) {
79
- const $usOS = Utils.createElement(`<span class="atk-ua ua-os"></span>`)
80
- $usOS.innerText = os
81
- $uaWrap.append($usOS)
82
- }
83
- }
84
- }