artalk 2.4.3 → 2.5.0
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/README.md +27 -0
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +4895 -4067
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/dist/ArtalkLite.css +1 -1
- package/dist/ArtalkLite.es.js +2496 -1779
- package/dist/ArtalkLite.iife.js +1 -1
- package/dist/ArtalkLite.js +1 -1
- package/dist/i18n/jp.js +1 -1
- package/dist/i18n/zh-TW.js +1 -1
- package/dist/src/api/index.d.ts +2 -2
- package/dist/src/api/system.d.ts +5 -2
- package/dist/src/artalk.d.ts +42 -34
- package/dist/src/comment/comment.d.ts +2 -2
- package/dist/src/comment/height-limit.d.ts +30 -0
- package/dist/src/comment/render-ctx.d.ts +23 -0
- package/dist/src/comment/render.d.ts +2 -50
- package/dist/src/comment/renders/actions.d.ts +5 -0
- package/dist/src/comment/renders/avatar.d.ts +5 -0
- package/dist/src/comment/renders/content.d.ts +5 -0
- package/dist/src/comment/renders/header.d.ts +5 -0
- package/dist/src/comment/renders/index.d.ts +2 -0
- package/dist/src/comment/renders/pending.d.ts +5 -0
- package/dist/src/comment/renders/reply-at.d.ts +5 -0
- package/dist/src/comment/renders/reply-to.d.ts +5 -0
- package/dist/src/components/dialog.d.ts +1 -1
- package/dist/src/config.d.ts +8 -0
- package/dist/src/context.d.ts +15 -29
- package/dist/src/editor/edit-mode.d.ts +9 -0
- package/dist/src/editor/editor-ui.d.ts +25 -0
- package/dist/src/editor/editor.d.ts +37 -45
- package/dist/src/editor/funcs.d.ts +2 -0
- package/dist/src/editor/mover.d.ts +8 -0
- package/dist/src/editor/plug-manager.d.ts +17 -0
- package/dist/src/editor/plugs/editor-plug.d.ts +13 -1
- package/dist/src/editor/reply.d.ts +9 -0
- package/dist/src/editor/submit.d.ts +16 -0
- package/dist/src/editor/ui.d.ts +25 -0
- package/dist/src/i18n/index.d.ts +11 -7
- package/dist/src/layer/index.d.ts +2 -2
- package/dist/src/layer/layer.d.ts +1 -1
- package/dist/src/lib/checker/captcha-renders.d.ts +5 -0
- package/dist/src/lib/checker/index.d.ts +18 -10
- package/dist/src/lib/dark-mode.d.ts +4 -0
- package/dist/src/lib/marked.d.ts +9 -0
- package/dist/src/lib/utils.d.ts +1 -5
- package/dist/src/list/list-lite.d.ts +15 -11
- package/dist/src/list/list-nest.d.ts +2 -2
- package/dist/src/list/list-ui.d.ts +7 -0
- package/dist/src/list/paginator/adaptors/index.d.ts +12 -0
- package/dist/src/list/paginator/adaptors/pagination.d.ts +9 -0
- package/dist/src/list/paginator/adaptors/read-more.d.ts +10 -0
- package/dist/src/list/paginator/holder.d.ts +16 -0
- package/dist/src/list/paginator/index.d.ts +10 -0
- package/dist/src/service.d.ts +40 -0
- package/dist/types/artalk-config.d.ts +5 -2
- package/dist/types/artalk-data.d.ts +3 -3
- package/dist/types/context.d.ts +11 -17
- package/dist/types/global.d.ts +1 -0
- package/package.json +6 -7
- package/src/api/system.ts +3 -12
- package/src/artalk.ts +101 -158
- package/src/comment/comment.ts +7 -6
- package/src/comment/height-limit.ts +100 -0
- package/src/comment/render-ctx.ts +30 -0
- package/src/comment/render.ts +31 -375
- package/src/comment/renders/actions.ts +114 -0
- package/src/comment/renders/avatar.ts +22 -0
- package/src/comment/renders/content.ts +39 -0
- package/src/comment/renders/header.ts +84 -0
- package/src/comment/renders/index.ts +19 -0
- package/src/comment/renders/pending.ts +12 -0
- package/src/comment/renders/reply-at.ts +16 -0
- package/src/comment/renders/reply-to.ts +24 -0
- package/src/config.ts +65 -0
- package/src/context.ts +31 -88
- package/src/defaults.ts +1 -0
- package/src/editor/edit-mode.ts +102 -0
- package/src/editor/editor.ts +100 -394
- package/src/editor/funcs.ts +96 -0
- package/src/editor/mover.ts +43 -0
- package/src/editor/plug-manager.ts +172 -0
- package/src/editor/plugs/editor-plug.ts +20 -2
- package/src/editor/plugs/{emoticons-plug.less → emoticons-plug.scss} +5 -4
- package/src/editor/plugs/emoticons-plug.ts +2 -1
- package/src/editor/plugs/header-input-plug.ts +5 -5
- package/src/editor/plugs/{preview-plug.less → preview-plug.scss} +1 -1
- package/src/editor/plugs/preview-plug.ts +8 -4
- package/src/editor/plugs/upload-plug.ts +10 -13
- package/src/editor/reply.ts +62 -0
- package/src/editor/submit.ts +98 -0
- package/src/editor/ui.ts +36 -0
- package/src/i18n/index.ts +21 -10
- package/src/layer/index.ts +2 -2
- package/src/layer/layer.ts +4 -4
- package/src/layer/sidebar-layer.ts +2 -1
- package/src/lib/checker/admin.ts +36 -0
- package/src/lib/checker/captcha-renders.ts +68 -0
- package/src/lib/checker/captcha.ts +26 -0
- package/src/lib/checker/index.ts +38 -20
- package/src/lib/dark-mode.ts +48 -0
- package/src/lib/marked.ts +133 -0
- package/src/lib/utils.ts +1 -123
- package/src/list/list-lite.ts +59 -162
- package/src/list/list-ui.ts +80 -0
- package/src/list/list.ts +16 -8
- package/src/list/paginator/adaptors/index.ts +21 -0
- package/src/list/paginator/adaptors/pagination.ts +42 -0
- package/src/list/paginator/adaptors/read-more.ts +56 -0
- package/src/list/paginator/holder.ts +55 -0
- package/src/list/paginator/index.ts +13 -0
- package/src/service.ts +118 -0
- package/src/style/{_color.less → _color.scss} +3 -3
- package/src/style/{_extend.less → _extend.scss} +1 -1
- package/src/style/_variables.scss +3 -0
- package/src/style/{comment.less → comment.scss} +36 -12
- package/src/style/{editor.less → editor.scss} +11 -11
- package/src/style/{list.less → list.scss} +8 -6
- package/src/style/{main.less → main.scss} +24 -23
- package/src/style/{sidebar-layer.less → sidebar-layer.scss} +8 -8
- package/types/artalk-config.d.ts +5 -2
- package/types/artalk-data.d.ts +3 -3
- package/types/context.d.ts +11 -17
- package/types/global.d.ts +1 -0
- package/CNAME +0 -1
- package/LICENSE +0 -165
- package/index.html +0 -157
- package/postcss.config.js +0 -5
- package/scripts/build-i18n.mjs +0 -46
- package/src/lib/checker/admin-checker.ts +0 -36
- package/src/lib/checker/captcha-checker.ts +0 -84
- package/src/style/_variables.less +0 -3
- package/test/ArtalkCount.html +0 -16
- package/test/ArtalkI18n.html +0 -16
- package/test/ArtalkLite.html +0 -15
- package/test/CSRF.html +0 -26
- package/tsconfig.json +0 -12
- package/vite-base.config.ts +0 -21
- package/vite-demo.config.ts +0 -12
- package/vite-lite.config.ts +0 -22
- package/vite.config.ts +0 -27
- /package/dist/src/lib/checker/{admin-checker.d.ts → admin.d.ts} +0 -0
- /package/dist/src/lib/checker/{captcha-checker.d.ts → captcha.d.ts} +0 -0
- /package/src/style/{pagination.less → pagination.scss} +0 -0
package/src/artalk.ts
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
import './style/main.
|
|
1
|
+
import './style/main.scss'
|
|
2
2
|
|
|
3
|
-
import ArtalkConfig from '~/types/artalk-config'
|
|
4
|
-
import { EventPayloadMap, Handler } from '~/types/event'
|
|
5
|
-
import ArtalkPlug from '~/types/plug'
|
|
6
|
-
import Context from '~/types/context'
|
|
3
|
+
import type ArtalkConfig from '~/types/artalk-config'
|
|
4
|
+
import type { EventPayloadMap, Handler } from '~/types/event'
|
|
5
|
+
import type ArtalkPlug from '~/types/plug'
|
|
6
|
+
import type Context from '~/types/context'
|
|
7
7
|
import ConcreteContext from './context'
|
|
8
8
|
import defaults from './defaults'
|
|
9
|
-
|
|
10
|
-
import
|
|
11
|
-
import CheckerLauncher from './lib/checker'
|
|
12
|
-
import Editor from './editor'
|
|
13
|
-
import List from './list'
|
|
14
|
-
import SidebarLayer from './layer/sidebar-layer'
|
|
15
|
-
|
|
16
|
-
import Layer from './layer'
|
|
17
|
-
import * as Utils from './lib/utils'
|
|
18
|
-
import * as Ui from './lib/ui'
|
|
9
|
+
import { handelBaseConf } from './config'
|
|
10
|
+
import Services from './service'
|
|
19
11
|
import * as Stat from './lib/stat'
|
|
12
|
+
import ListLite from './list/list-lite'
|
|
20
13
|
|
|
21
14
|
/**
|
|
22
15
|
* Artalk
|
|
23
16
|
*
|
|
24
|
-
* @
|
|
17
|
+
* @see https://artalk.js.org
|
|
25
18
|
*/
|
|
26
19
|
export default class Artalk {
|
|
20
|
+
private static instance?: Artalk
|
|
21
|
+
|
|
27
22
|
public static ListLite = ListLite
|
|
28
23
|
public static readonly defaults: ArtalkConfig = defaults
|
|
29
24
|
|
|
@@ -31,192 +26,140 @@ export default class Artalk {
|
|
|
31
26
|
public ctx!: Context
|
|
32
27
|
public $root!: HTMLElement
|
|
33
28
|
|
|
34
|
-
/** Plugins
|
|
35
|
-
protected static
|
|
36
|
-
|
|
37
|
-
/** Plugins (in a instance scope) */
|
|
38
|
-
protected instancePlugins: ArtalkPlug[] = []
|
|
39
|
-
|
|
40
|
-
/** 禁用的组件 */
|
|
29
|
+
/** Plugins */
|
|
30
|
+
protected static plugins: ArtalkPlug[] = [ Stat.PvCountWidget ]
|
|
41
31
|
public static DisabledComponents: string[] = []
|
|
42
32
|
|
|
43
|
-
constructor(
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
constructor(conf: Partial<ArtalkConfig>) {
|
|
34
|
+
if (Artalk.instance) return Artalk.instance.update(conf)
|
|
35
|
+
|
|
36
|
+
// 初始化基本配置
|
|
37
|
+
this.conf = handelBaseConf(conf)
|
|
46
38
|
if (this.conf.el instanceof HTMLElement) this.$root = this.conf.el
|
|
47
39
|
|
|
48
|
-
|
|
40
|
+
// 初始化 Context
|
|
49
41
|
this.ctx = new ConcreteContext(this.conf, this.$root)
|
|
50
42
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** 组件初始化 */
|
|
56
|
-
private initComponents() {
|
|
57
|
-
this.initLocale()
|
|
58
|
-
this.initLayer()
|
|
59
|
-
Utils.initMarked(this.ctx)
|
|
60
|
-
|
|
61
|
-
const Components: { [name: string]: () => void } = {
|
|
62
|
-
// CheckerLauncher
|
|
63
|
-
checkerLauncher: () => {
|
|
64
|
-
const checkerLauncher = new CheckerLauncher(this.ctx)
|
|
65
|
-
this.ctx.setCheckerLauncher(checkerLauncher)
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
// 编辑器
|
|
69
|
-
editor: () => {
|
|
70
|
-
const editor = new Editor(this.ctx)
|
|
71
|
-
this.ctx.setEditor(editor)
|
|
72
|
-
this.$root.appendChild(editor.$el)
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
// 评论列表
|
|
76
|
-
list: () => {
|
|
77
|
-
// 评论列表
|
|
78
|
-
const list = new List(this.ctx)
|
|
79
|
-
this.ctx.setList(list)
|
|
80
|
-
this.$root.appendChild(list.$el)
|
|
81
|
-
|
|
82
|
-
// 评论获取
|
|
83
|
-
list.fetchComments(0)
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
// 侧边栏 Layer
|
|
87
|
-
sidebarLayer: () => {
|
|
88
|
-
const sidebarLayer = new SidebarLayer(this.ctx)
|
|
89
|
-
this.ctx.setSidebarLayer(sidebarLayer)
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
// 默认事件绑定
|
|
93
|
-
eventsDefault: () => {
|
|
94
|
-
this.initEventBind()
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 组件初始化
|
|
99
|
-
Object.entries(Components).forEach(([name, initComponent]) => {
|
|
43
|
+
// 内建服务初始化
|
|
44
|
+
Object.entries(Services).forEach(([name, initService]) => {
|
|
100
45
|
if (Artalk.DisabledComponents.includes(name)) return
|
|
101
|
-
|
|
102
|
-
|
|
46
|
+
const obj = initService(this.ctx)
|
|
47
|
+
if (obj) this.ctx.inject(name as any, obj) // auto inject deps to ctx
|
|
103
48
|
})
|
|
104
49
|
|
|
105
50
|
// 插件初始化 (global scope)
|
|
106
|
-
Artalk.
|
|
51
|
+
Artalk.plugins.forEach(plugin => {
|
|
107
52
|
if (typeof plugin === 'function')
|
|
108
53
|
plugin(this.ctx)
|
|
109
54
|
})
|
|
110
55
|
}
|
|
111
56
|
|
|
112
|
-
/**
|
|
113
|
-
public static
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (typeof conf.el === 'string' && !!conf.el) {
|
|
119
|
-
try {
|
|
120
|
-
const findEl = document.querySelector<HTMLElement>(conf.el)
|
|
121
|
-
if (!findEl) throw Error(`Target element "${conf.el}" was not found.`)
|
|
122
|
-
conf.el = findEl
|
|
123
|
-
} catch (e) {
|
|
124
|
-
console.error(e)
|
|
125
|
-
throw new Error('Please check your Artalk `el` config.')
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// 服务器配置
|
|
130
|
-
conf.server = conf.server.replace(/\/$/, '').replace(/\/api\/?$/, '')
|
|
131
|
-
|
|
132
|
-
// 默认 pageKey
|
|
133
|
-
if (!conf.pageKey) {
|
|
134
|
-
// @link http://bl.ocks.org/abernier/3070589
|
|
135
|
-
conf.pageKey = `${window.location.pathname}`
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// 默认 pageTitle
|
|
139
|
-
if (!conf.pageTitle) {
|
|
140
|
-
conf.pageTitle = `${document.title}`
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return conf
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/** 事件绑定初始化 */
|
|
147
|
-
private initEventBind() {
|
|
148
|
-
// 锚点快速跳转评论
|
|
149
|
-
window.addEventListener('hashchange', () => {
|
|
150
|
-
this.ctx.listHashGotoCheck()
|
|
151
|
-
})
|
|
57
|
+
/** Init Artalk */
|
|
58
|
+
public static init(conf: Partial<ArtalkConfig>): Artalk {
|
|
59
|
+
if (this.instance) return this.instance.update(conf) // 单例模式
|
|
60
|
+
this.instance = new Artalk(conf)
|
|
61
|
+
return this.instance
|
|
62
|
+
}
|
|
152
63
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
})
|
|
64
|
+
/** Use Plugin (plugin will be called in instance `use` func) */
|
|
65
|
+
public use(plugin: ArtalkPlug) {
|
|
66
|
+
Artalk.plugins.push(plugin)
|
|
67
|
+
if (typeof plugin === 'function') plugin(this.ctx)
|
|
158
68
|
}
|
|
159
69
|
|
|
160
|
-
/**
|
|
161
|
-
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
|
|
70
|
+
/** Update config of Artalk */
|
|
71
|
+
public update(conf: Partial<ArtalkConfig>) {
|
|
72
|
+
if (!Artalk.instance) throw Error('cannot call `update` function before call `load`')
|
|
73
|
+
Artalk.instance.ctx.updateConf(conf)
|
|
74
|
+
return Artalk.instance
|
|
165
75
|
}
|
|
166
76
|
|
|
167
|
-
/**
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
Layer.BodyOrgOverflow = document.body.style.overflow
|
|
171
|
-
Layer.BodyOrgPaddingRight = document.body.style.paddingRight
|
|
77
|
+
/** Reload comment list of Artalk */
|
|
78
|
+
public reload() {
|
|
79
|
+
this.ctx.listReload()
|
|
172
80
|
}
|
|
173
81
|
|
|
174
|
-
/**
|
|
82
|
+
/** Destroy instance of Artalk */
|
|
83
|
+
public destroy() {
|
|
84
|
+
if (!Artalk.instance) throw Error('cannot call `destroy` function before call `load`')
|
|
85
|
+
Artalk.instance.$root.remove()
|
|
86
|
+
delete Artalk.instance
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Add an event listener */
|
|
175
90
|
public on<K extends keyof EventPayloadMap>(name: K, handler: Handler<EventPayloadMap[K]>) {
|
|
176
91
|
this.ctx.on(name, handler, 'external')
|
|
177
92
|
}
|
|
178
93
|
|
|
179
|
-
/**
|
|
94
|
+
/** Remove an event listener */
|
|
180
95
|
public off<K extends keyof EventPayloadMap>(name: K, handler: Handler<EventPayloadMap[K]>) {
|
|
181
96
|
this.ctx.off(name, handler, 'external')
|
|
182
97
|
}
|
|
183
98
|
|
|
184
|
-
/**
|
|
99
|
+
/** Trigger an event */
|
|
185
100
|
public trigger<K extends keyof EventPayloadMap>(name: K, payload?: EventPayloadMap[K]) {
|
|
186
101
|
this.ctx.trigger(name, payload, 'external')
|
|
187
102
|
}
|
|
188
103
|
|
|
189
|
-
/**
|
|
190
|
-
public reload() {
|
|
191
|
-
this.ctx.listReload()
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/** 设置暗黑模式 */
|
|
104
|
+
/** Set dark mode */
|
|
195
105
|
public setDarkMode(darkMode: boolean) {
|
|
196
106
|
this.ctx.setDarkMode(darkMode)
|
|
197
107
|
}
|
|
198
108
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (typeof plugin === 'function') plugin(this.ctx)
|
|
203
|
-
}
|
|
109
|
+
// ===========================
|
|
110
|
+
// Static methods
|
|
111
|
+
// ===========================
|
|
204
112
|
|
|
205
|
-
/** Use Plugin (static method
|
|
113
|
+
/** Use Plugin (static method) */
|
|
206
114
|
public static use(plugin: ArtalkPlug) {
|
|
207
|
-
this.
|
|
115
|
+
this.plugins.push(plugin)
|
|
116
|
+
if (this.instance && typeof plugin === 'function') plugin(this.instance.ctx)
|
|
208
117
|
}
|
|
209
118
|
|
|
210
|
-
/**
|
|
211
|
-
public static
|
|
212
|
-
this.
|
|
213
|
-
console.warn('`Use(...)` is deprecated, replace it with lowercase `use(...)`.')
|
|
119
|
+
/** Update config of Artalk */
|
|
120
|
+
public static update(conf: Partial<ArtalkConfig>) {
|
|
121
|
+
return this.instance?.update(conf)
|
|
214
122
|
}
|
|
215
123
|
|
|
216
|
-
/**
|
|
217
|
-
public static
|
|
218
|
-
|
|
219
|
-
|
|
124
|
+
/** Reload comment list of Artalk */
|
|
125
|
+
public static reload() {
|
|
126
|
+
this.instance?.reload()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Destroy instance of Artalk */
|
|
130
|
+
public static destroy() {
|
|
131
|
+
this.instance?.destroy()
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Add an event listener */
|
|
135
|
+
public static on<K extends keyof EventPayloadMap>(name: K, handler: Handler<EventPayloadMap[K]>) {
|
|
136
|
+
this.instance?.on(name, handler)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Remove an event listener */
|
|
140
|
+
public static off<K extends keyof EventPayloadMap>(name: K, handler: Handler<EventPayloadMap[K]>) {
|
|
141
|
+
this.instance?.off(name, handler)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Trigger an event */
|
|
145
|
+
public static trigger<K extends keyof EventPayloadMap>(name: K, payload?: EventPayloadMap[K]) {
|
|
146
|
+
this.instance?.trigger(name, payload)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Set dark mode */
|
|
150
|
+
public static setDarkMode(darkMode: boolean) {
|
|
151
|
+
this.instance?.setDarkMode(darkMode)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Load count widget */
|
|
155
|
+
public static loadCountWidget(conf: Partial<ArtalkConfig>) {
|
|
156
|
+
const ctx = new ConcreteContext(handelBaseConf(conf))
|
|
220
157
|
Stat.initCountWidget({ ctx, pvAdd: false })
|
|
221
158
|
}
|
|
159
|
+
|
|
160
|
+
/** @deprecated Please use `loadCountWidget` instead */
|
|
161
|
+
public static LoadCountWidget(conf: Partial<ArtalkConfig>) {
|
|
162
|
+
console.warn('The method `LoadCountWidget` is deprecated, please use `loadCountWidget` instead.')
|
|
163
|
+
this.loadCountWidget(conf)
|
|
164
|
+
}
|
|
222
165
|
}
|
package/src/comment/comment.ts
CHANGED
|
@@ -2,8 +2,9 @@ import { CommentData } from '~/types/artalk-data'
|
|
|
2
2
|
import Context from '~/types/context'
|
|
3
3
|
import Component from '../lib/component'
|
|
4
4
|
import * as Utils from '../lib/utils'
|
|
5
|
+
import marked from '../lib/marked'
|
|
5
6
|
import UADetect from '../lib/detect'
|
|
6
|
-
import
|
|
7
|
+
import CommentUI from './render'
|
|
7
8
|
import CommentActions from './actions'
|
|
8
9
|
|
|
9
10
|
export interface CommentConf {
|
|
@@ -18,7 +19,7 @@ export interface CommentConf {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export default class Comment extends Component {
|
|
21
|
-
private renderInstance:
|
|
22
|
+
private renderInstance: CommentUI
|
|
22
23
|
private actionInstance: CommentActions
|
|
23
24
|
|
|
24
25
|
private data: CommentData
|
|
@@ -44,7 +45,7 @@ export default class Comment extends Component {
|
|
|
44
45
|
this.nestCurt = 1 // 现在已嵌套 n 层
|
|
45
46
|
|
|
46
47
|
this.actionInstance = new CommentActions(this)
|
|
47
|
-
this.renderInstance = new
|
|
48
|
+
this.renderInstance = new CommentUI(this)
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
/** 渲染 UI */
|
|
@@ -119,7 +120,7 @@ export default class Comment extends Component {
|
|
|
119
120
|
childC.getRender().playFadeAnim()
|
|
120
121
|
|
|
121
122
|
// 内容限高
|
|
122
|
-
childC.getRender().
|
|
123
|
+
childC.getRender().checkHeightLimit()
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
/** 获取存放子评论的元素对象 */
|
|
@@ -131,7 +132,7 @@ export default class Comment extends Component {
|
|
|
131
132
|
if (this.nestCurt < this.nestMax) {
|
|
132
133
|
$children = this.getRender().renderChildrenWrap()
|
|
133
134
|
} else {
|
|
134
|
-
|
|
135
|
+
$children = this.parent!.getChildrenEl()
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
|
|
@@ -164,7 +165,7 @@ export default class Comment extends Component {
|
|
|
164
165
|
|
|
165
166
|
/** 获取评论 markdown 解析后的内容 */
|
|
166
167
|
public getContentMarked() {
|
|
167
|
-
return
|
|
168
|
+
return marked(this.ctx, this.data.content)
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
/** 获取格式化后的日期 */
|
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Comment from './comment'
|
|
2
|
+
import ActionBtn from '../components/action-btn'
|
|
3
|
+
|
|
4
|
+
export default class RenderCtx {
|
|
5
|
+
public comment: Comment
|
|
6
|
+
|
|
7
|
+
public get ctx() { return this.comment.ctx }
|
|
8
|
+
public get data() { return this.comment.getData() }
|
|
9
|
+
public get conf() { return this.comment.conf }
|
|
10
|
+
public get cConf() { return this.comment.getConf() }
|
|
11
|
+
|
|
12
|
+
public $el!: HTMLElement
|
|
13
|
+
public $main!: HTMLElement
|
|
14
|
+
public $header!: HTMLElement
|
|
15
|
+
public $headerNick!: HTMLElement
|
|
16
|
+
public $headerBadgeWrap!: HTMLElement
|
|
17
|
+
public $body!: HTMLElement
|
|
18
|
+
public $content!: HTMLElement
|
|
19
|
+
public $childrenWrap!: HTMLElement|null
|
|
20
|
+
public $actions!: HTMLElement
|
|
21
|
+
public voteBtnUp?: ActionBtn
|
|
22
|
+
public voteBtnDown?: ActionBtn
|
|
23
|
+
|
|
24
|
+
public $replyTo?: HTMLElement // 回复评论内容 (平铺下显示)
|
|
25
|
+
public $replyAt?: HTMLElement // 回复 AT(层级嵌套下显示)
|
|
26
|
+
|
|
27
|
+
public constructor(comment: Comment) {
|
|
28
|
+
this.comment = comment
|
|
29
|
+
}
|
|
30
|
+
}
|