artalk 2.1.4 → 2.1.7

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 (48) hide show
  1. package/CNAME +1 -0
  2. package/dist/Artalk.css +1 -1
  3. package/dist/Artalk.es.js +303 -1248
  4. package/dist/Artalk.iife.js +1 -1
  5. package/dist/Artalk.js +1 -1
  6. package/index.html +143 -0
  7. package/package.json +8 -29
  8. package/postcss.config.js +5 -0
  9. package/src/api/index.ts +14 -0
  10. package/src/api/request.ts +4 -2
  11. package/src/artalk.ts +28 -6
  12. package/src/components/comment.ts +20 -3
  13. package/src/components/html/list.html +4 -2
  14. package/src/components/html/sidebar-layer.html +8 -0
  15. package/src/components/list.ts +60 -0
  16. package/src/components/sidebar-layer.ts +143 -0
  17. package/src/defaults.ts +1 -0
  18. package/src/lib/detect.js +3 -1
  19. package/src/lib/utils.ts +25 -0
  20. package/src/style/_extend.less +0 -80
  21. package/src/style/comment.less +6 -0
  22. package/src/style/list.less +66 -0
  23. package/src/style/main.less +1 -1
  24. package/src/style/sidebar-layer.less +92 -0
  25. package/types/artalk-config.d.ts +4 -1
  26. package/types/artalk-data.d.ts +3 -0
  27. package/vite-common.config.ts +15 -0
  28. package/vite-demo.config.ts +14 -0
  29. package/vite.config.ts +36 -0
  30. package/LICENSE +0 -674
  31. package/README.md +0 -84
  32. package/src/components/admin/page-list.ts +0 -194
  33. package/src/components/admin/site-list-floater.ts +0 -98
  34. package/src/components/admin/site-list.ts +0 -289
  35. package/src/components/html/sidebar.html +0 -22
  36. package/src/components/item-text-editor.ts +0 -136
  37. package/src/components/sidebar-view.ts +0 -26
  38. package/src/components/sidebar-views/comments-view.ts +0 -73
  39. package/src/components/sidebar-views/pages-view.ts +0 -61
  40. package/src/components/sidebar-views/setting-view.ts +0 -21
  41. package/src/components/sidebar-views/sites-view.ts +0 -36
  42. package/src/components/sidebar-views/transfer-view.ts +0 -218
  43. package/src/components/sidebar.ts +0 -293
  44. package/src/lib/md5.js +0 -6
  45. package/src/style/item-text-editor.less +0 -35
  46. package/src/style/page-list.less +0 -50
  47. package/src/style/sidebar.less +0 -420
  48. package/src/style/site-list.less +0 -208
@@ -1,293 +0,0 @@
1
- import '../style/sidebar.less'
2
-
3
- import MD5 from '../lib/md5'
4
- import Context from '../context'
5
- import Component from '../lib/component'
6
- import * as Utils from '../lib/utils'
7
- import * as Ui from '../lib/ui'
8
- import Comment from './comment'
9
- import SidebarHTML from './html/sidebar.html?raw'
10
- import Layer from './layer'
11
-
12
- import SidebarView from './sidebar-view'
13
- import CommentsView from './sidebar-views/comments-view'
14
- import PagesView from './sidebar-views/pages-view'
15
- import SitesView from './sidebar-views/sites-view'
16
- import TransferView from './sidebar-views/transfer-view'
17
- import { SiteData } from '~/types/artalk-data'
18
- import Api from '../api'
19
- import SiteListFloater from './admin/site-list-floater'
20
- import SettingView from './sidebar-views/setting-view'
21
-
22
- const DEFAULT_VIEW = 'comments'
23
- const REGISTER_VIEWS: (typeof SidebarView)[] = [
24
- CommentsView, PagesView, SitesView, TransferView, // SettingView
25
- ]
26
-
27
- export default class Sidebar extends Component {
28
- public layer?: Layer
29
-
30
- public $header: HTMLElement
31
- public $headerMenu: HTMLElement
32
- public $title: HTMLElement
33
- public $avatar: HTMLElement
34
- public $siteLogo?: HTMLElement
35
- public $closeBtn: HTMLElement
36
- public $nav: HTMLElement
37
- public $curtViewBtn: HTMLElement
38
- public $curtViewBtnIcon: HTMLElement
39
- public $curtViewBtnText: HTMLElement
40
- public $navTabs: HTMLElement
41
- public $navViews: HTMLElement
42
- public $viewWrap: HTMLElement
43
- public siteSwitcher?: SiteListFloater
44
-
45
- private get isAdmin() { return this.ctx.user.data.isAdmin }
46
- public curtSite?: string
47
- public curtView: string = DEFAULT_VIEW
48
- public get curtViewInstance() {
49
- return this.curtView ? this.viewInstances[this.curtView] : undefined
50
- }
51
- public curtTab?: string
52
-
53
- public viewInstances: {[name: string]: SidebarView} = {}
54
-
55
- private viewSwitcherShow = false
56
-
57
- constructor(ctx: Context) {
58
- super(ctx)
59
-
60
- // initial elements
61
- this.$el = Utils.createElement(SidebarHTML)
62
- this.$header = this.$el.querySelector('.atk-sidebar-header')!
63
- this.$headerMenu = this.$header.querySelector('.atk-menu')!
64
- this.$title = this.$header.querySelector('.atk-sidebar-title')!
65
- this.$avatar = this.$header.querySelector('.atk-avatar')!
66
- this.$closeBtn = this.$header.querySelector('.atk-sidebar-close')!
67
-
68
- this.$nav = this.$el.querySelector('.atk-sidebar-nav')!
69
- this.$curtViewBtn = this.$nav.querySelector('.akt-curt-view-btn')!
70
- this.$curtViewBtnIcon = this.$curtViewBtn.querySelector('.atk-icon')!
71
- this.$curtViewBtnText = this.$curtViewBtn.querySelector('.atk-text')!
72
- this.$navTabs = this.$nav.querySelector('.atk-tabs')!
73
- this.$navViews = this.$nav.querySelector('.atk-views')!
74
-
75
- this.$viewWrap = this.$el.querySelector('.atk-sidebar-view-wrap')!
76
-
77
- // init UI
78
- this.initViewSwitcher()
79
-
80
- this.$closeBtn.onclick = () => {
81
- this.hide()
82
- }
83
-
84
- // event
85
- this.ctx.on('sidebar-show', () => (this.show()))
86
- this.ctx.on('sidebar-hide', () => (this.hide()))
87
- this.ctx.on('user-changed', () => { this.firstShow = true })
88
- }
89
-
90
- /** 初始化 view 切换器 */
91
- private initViewSwitcher() {
92
- this.$curtViewBtn.onclick = () => {
93
- this.toggleViewSwitcher()
94
- }
95
-
96
- this.$navViews.innerHTML = ''
97
- REGISTER_VIEWS.forEach(view => {
98
- const $item = Utils.createElement(`<div class="atk-tab-item"></div>`)
99
- this.$navViews.append($item)
100
- $item.setAttribute('data-name', view.viewName)
101
- $item.innerText = view.viewTitle
102
- if (view.viewName === this.curtView) {
103
- $item.classList.add('atk-active')
104
- this.$curtViewBtnText.innerText = view.viewTitle
105
- }
106
- $item.onclick = () => {
107
- // 切换 view
108
- this.switchView(view.viewName)
109
-
110
- this.toggleViewSwitcher()
111
- }
112
- })
113
- }
114
-
115
- /** 显示/隐藏 view 切换器 */
116
- private toggleViewSwitcher() {
117
- if (!this.viewSwitcherShow) {
118
- // 显示
119
- this.$navViews.style.display = ''
120
- this.$navTabs.style.display = 'none'
121
- this.$curtViewBtnIcon.classList.add('atk-arrow')
122
- // this.$curtViewBtnText.style.display = 'none'
123
- } else {
124
- // 隐藏
125
- this.$navViews.style.display = 'none'
126
- this.$navTabs.style.display = ''
127
- this.$curtViewBtnIcon.classList.remove('atk-arrow')
128
- // this.$curtViewBtnText.style.display = ''
129
- }
130
-
131
- this.viewSwitcherShow = !this.viewSwitcherShow
132
- }
133
-
134
- private firstShow = true
135
-
136
- /** 显示 */
137
- public async show() {
138
- this.$el.style.transform = '' // 动画清除,防止二次打开失效
139
-
140
- // 获取 Layer
141
- this.layer = new Layer(this.ctx, 'sidebar', this.$el)
142
- this.layer.afterHide = () => {
143
- // 防止评论框被吞
144
- if (this.ctx.conf.editorTravel === true) {
145
- this.ctx.trigger('editor-travel-back')
146
- }
147
- }
148
- this.layer.show()
149
-
150
- // viewWrap 滚动条归位
151
- this.$viewWrap.scrollTo(0, 0)
152
-
153
- // 执行动画
154
- setTimeout(() => {
155
- this.$el.style.transform = 'translate(0, 0)'
156
- }, 20)
157
-
158
- // 第一次加载
159
- if (this.firstShow) {
160
- ///////////////////
161
- //// IMPORTANT ////
162
- ///////////////////
163
-
164
- // 用户权限检测
165
- if (this.isAdmin) {
166
- // 是管理员
167
- this.$title.innerText = '控制中心'
168
- this.$curtViewBtn.style.display = ''
169
-
170
- if (!this.siteSwitcher) {
171
- // 初始化站点切换器
172
- this.siteSwitcher = new SiteListFloater(this.ctx, {
173
- onSwitchSite: (siteName) => { this.switchSite(siteName) },
174
- onClickSitesViewBtn: () => { this.switchView('sites') }
175
- })
176
- this.$viewWrap.before(this.siteSwitcher.$el)
177
- this.$avatar.onclick = (evt) => {
178
- if (!this.isAdmin) return
179
- this.siteSwitcher?.show(evt.target as any)
180
- }
181
-
182
- }
183
-
184
- this.curtSite = this.conf.site
185
-
186
- Ui.showLoading(this.$el)
187
- try {
188
- await this.siteSwitcher!.load(this.curtSite)
189
- } catch (err: any) {
190
- const $err = Utils.createElement(`<span>加载失败:${err.msg || '网络错误'}<br/></span>`)
191
- const $retryBtn = Utils.createElement('<span style="cursor:pointer;">点击重新获取</span>')
192
- $err.appendChild($retryBtn)
193
- $retryBtn.onclick = () => { Ui.setError(this.$el, null); this.show() }
194
- Ui.setError(this.$el, $err)
195
- return
196
- } finally { Ui.hideLoading(this.$el) }
197
-
198
- // 站点图像
199
- this.$avatar.innerHTML = ''
200
- this.$siteLogo = Utils.createElement('<div class="atk-site-logo"></div>')
201
- this.$siteLogo.innerText = (this.curtSite || '').substr(0, 1)
202
- this.$avatar.append(this.$siteLogo)
203
- } else {
204
- // 不是管理员
205
- this.$title.innerText = '通知中心'
206
- this.$curtViewBtn.style.display = 'none' // 隐藏 view 切换器
207
- this.curtSite = this.conf.site // 第一次 show 使用当前站点数据
208
-
209
- // 头像
210
- const $avatarImg = document.createElement('img') as HTMLImageElement
211
- $avatarImg.src = Utils.getGravatarURL(this.ctx, MD5(this.ctx.user.data.email.toLowerCase()))
212
- this.$avatar.innerHTML = ''
213
- this.$avatar.append($avatarImg)
214
- }
215
-
216
- this.switchView(DEFAULT_VIEW) // 打开默认 view
217
- this.firstShow = false
218
- }
219
- }
220
-
221
- /** 隐藏 */
222
- public hide() {
223
- // 执行动画
224
- this.$el.style.transform = ''
225
-
226
- this.layer?.hide()
227
- }
228
-
229
- /** 切换 View */
230
- public switchView(viewName: string) {
231
- let view = this.viewInstances[viewName]
232
- if (!view) {
233
- // 初始化 View
234
- const View = REGISTER_VIEWS.find(o => o.viewName === viewName)!
235
- view = new View(this.ctx, this.$viewWrap)
236
- this.viewInstances[viewName] = view
237
- }
238
-
239
- // init view
240
- view.mount(this.curtSite!)
241
-
242
- this.curtView = viewName
243
- this.curtTab = view.viewActiveTab
244
-
245
- // update view indicator
246
- this.$curtViewBtnText.innerText = (view.constructor as typeof SidebarView).viewTitle
247
- this.$navViews.querySelectorAll('.atk-tab-item').forEach((e) => {
248
- if (e.getAttribute('data-name') === viewName) {
249
- e.classList.add('atk-active')
250
- } else {
251
- e.classList.remove('atk-active')
252
- }
253
- })
254
-
255
- // update tabs
256
- this.loadViewTabs(view)
257
-
258
- // load element
259
- this.$viewWrap.innerHTML = ''
260
- this.$viewWrap.append(view.$el)
261
- this.$viewWrap.classList.forEach((c) => {
262
- if (c.startsWith('atk-view-name-'))
263
- this.$viewWrap.classList.remove(c)
264
- })
265
- this.$viewWrap.classList.add(`atk-view-name-${(view.constructor as typeof SidebarView).viewName}`)
266
- }
267
-
268
- private loadViewTabs(view: SidebarView) {
269
- this.$navTabs.innerHTML = ''
270
- Object.entries<string>(view.viewTabs).forEach(([tabName, label]) => {
271
- const $tab = Utils.createElement(`<div class="atk-tab-item"></div>`)
272
- this.$navTabs.append($tab)
273
- $tab.innerText = label
274
- if (view.viewActiveTab === tabName) $tab.classList.add('atk-active')
275
-
276
- // 切换 tab
277
- $tab.onclick = () => {
278
- if (view.switchTab(tabName, this.curtSite!) === false) { return }
279
- this.$navTabs.querySelectorAll('.atk-active').forEach(e => e.classList.remove('atk-active'))
280
- $tab.classList.add('atk-active')
281
- this.curtTab = tabName
282
- }
283
- })
284
- }
285
-
286
- /** 切换站点 */
287
- private switchSite(siteName: string) {
288
- this.curtSite = siteName
289
- const curtView = this.curtViewInstance
290
- curtView?.switchTab(this.curtTab!, siteName)
291
- if (this.$siteLogo) this.$siteLogo.innerText = this.curtSite.substr(0, 1)
292
- }
293
- }
package/src/lib/md5.js DELETED
@@ -1,6 +0,0 @@
1
- /* eslint-disable */
2
-
3
- // https://stackoverflow.com/questions/14733374/how-to-generate-an-md5-file-hash-in-javascript-node-js#answer-33486055
4
- var MD5 = function(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r<d.length;r++)_=d.charCodeAt(r),f+=m.charAt(_>>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<<m%32;return _}function V(d){for(var _="",m=0;m<32*d.length;m+=8)_+=String.fromCharCode(d[m>>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n<d.length;n+=16){var h=m,t=f,g=r,e=i;f=md5_ii(f=md5_ii(f=md5_ii(f=md5_ii(f=md5_hh(f=md5_hh(f=md5_hh(f=md5_hh(f=md5_gg(f=md5_gg(f=md5_gg(f=md5_gg(f=md5_ff(f=md5_ff(f=md5_ff(f=md5_ff(f,r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+0],7,-680876936),f,r,d[n+1],12,-389564586),m,f,d[n+2],17,606105819),i,m,d[n+3],22,-1044525330),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+4],7,-176418897),f,r,d[n+5],12,1200080426),m,f,d[n+6],17,-1473231341),i,m,d[n+7],22,-45705983),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+8],7,1770035416),f,r,d[n+9],12,-1958414417),m,f,d[n+10],17,-42063),i,m,d[n+11],22,-1990404162),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+12],7,1804603682),f,r,d[n+13],12,-40341101),m,f,d[n+14],17,-1502002290),i,m,d[n+15],22,1236535329),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+1],5,-165796510),f,r,d[n+6],9,-1069501632),m,f,d[n+11],14,643717713),i,m,d[n+0],20,-373897302),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+5],5,-701558691),f,r,d[n+10],9,38016083),m,f,d[n+15],14,-660478335),i,m,d[n+4],20,-405537848),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+9],5,568446438),f,r,d[n+14],9,-1019803690),m,f,d[n+3],14,-187363961),i,m,d[n+8],20,1163531501),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+13],5,-1444681467),f,r,d[n+2],9,-51403784),m,f,d[n+7],14,1735328473),i,m,d[n+12],20,-1926607734),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+5],4,-378558),f,r,d[n+8],11,-2022574463),m,f,d[n+11],16,1839030562),i,m,d[n+14],23,-35309556),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+1],4,-1530992060),f,r,d[n+4],11,1272893353),m,f,d[n+7],16,-155497632),i,m,d[n+10],23,-1094730640),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+13],4,681279174),f,r,d[n+0],11,-358537222),m,f,d[n+3],16,-722521979),i,m,d[n+6],23,76029189),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+9],4,-640364487),f,r,d[n+12],11,-421815835),m,f,d[n+15],16,530742520),i,m,d[n+2],23,-995338651),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+0],6,-198630844),f,r,d[n+7],10,1126891415),m,f,d[n+14],15,-1416354905),i,m,d[n+5],21,-57434055),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+12],6,1700485571),f,r,d[n+3],10,-1894986606),m,f,d[n+10],15,-1051523),i,m,d[n+1],21,-2054922799),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+8],6,1873313359),f,r,d[n+15],10,-30611744),m,f,d[n+6],15,-1560198380),i,m,d[n+13],21,1309151649),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+4],6,-145523070),f,r,d[n+11],10,-1120210379),m,f,d[n+2],15,718787259),i,m,d[n+9],21,-343485551),m=safe_add(m,h),f=safe_add(f,t),r=safe_add(r,g),i=safe_add(i,e)}return Array(m,f,r,i)}function md5_cmn(d,_,m,f,r,i){return safe_add(bit_rol(safe_add(safe_add(_,d),safe_add(f,i)),r),m)}function md5_ff(d,_,m,f,r,i,n){return md5_cmn(_&m|~_&f,d,_,r,i,n)}function md5_gg(d,_,m,f,r,i,n){return md5_cmn(_&f|m&~f,d,_,r,i,n)}function md5_hh(d,_,m,f,r,i,n){return md5_cmn(_^m^f,d,_,r,i,n)}function md5_ii(d,_,m,f,r,i,n){return md5_cmn(m^(_|~f),d,_,r,i,n)}function safe_add(d,_){var m=(65535&d)+(65535&_);return(d>>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_}
5
-
6
- export default MD5
@@ -1,35 +0,0 @@
1
- .atk-item-text-editor-layer {
2
- z-index: 999;
3
- background: var(--at-color-bg);
4
- position: absolute;
5
- left: 0;
6
- top: 0;
7
- width: 100%;
8
- height: 100%;
9
- display: flex;
10
- flex-direction: row;
11
- align-items: center;
12
-
13
- .atk-edit-form {
14
- flex: auto;
15
- padding-left: 20px;
16
-
17
- input {
18
- font-size: 17px;
19
- width: 100%;
20
- padding: 3px 5px;
21
- border: 0;
22
- border-bottom: 1px solid var(--at-color-border);
23
- outline: none;
24
- background: transparent;
25
-
26
- &.atk-invalid {}
27
- }
28
- }
29
-
30
- .atk-actions {
31
- .atk-list-btn-actions();
32
-
33
- .atk-yes-btn.atk-disabled {}
34
- }
35
- }
@@ -1,50 +0,0 @@
1
- .atk-page-list {
2
- .atk-page-item {
3
- display: flex;
4
- flex-direction: row;
5
- position: relative;
6
- min-height: 120px;
7
- align-items: center;
8
-
9
- &:not(:last-child) {
10
- border-bottom: 1px solid var(--at-color-border);
11
- }
12
- }
13
-
14
- .atk-page-main {
15
- display: flex;
16
- flex-direction: column;
17
- flex: auto;
18
- padding: 20px 30px;
19
-
20
- .atk-title {
21
- color: var(--at-color-font);
22
- font-size: 21px;
23
- margin-bottom: 10px;
24
- }
25
-
26
- .atk-sub {
27
- color: var(--at-color-sub);
28
- font-size: 14px;
29
- }
30
- }
31
-
32
- .atk-page-main-actions {
33
- .atk-list-text-actions();
34
- }
35
-
36
- .atk-page-actions {
37
- .atk-list-btn-actions();
38
- }
39
-
40
- .atk-page-edit-layer {
41
- z-index: 999;
42
- background: var(--at-color-bg);
43
- position: absolute;
44
- width: 100%;
45
- height: 100%;
46
- display: flex;
47
- flex-direction: row;
48
- align-items: center;
49
- }
50
- }