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.
- package/README.md +1 -1
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +209 -188
- package/dist/Artalk.es.js.map +1 -0
- package/dist/Artalk.iife.js +2 -1
- package/dist/Artalk.iife.js.map +1 -0
- package/dist/Artalk.js +2 -1
- package/dist/Artalk.js.map +1 -0
- package/dist/ArtalkLite.css +1 -1
- package/dist/ArtalkLite.es.js +209 -188
- package/dist/ArtalkLite.es.js.map +1 -0
- package/dist/ArtalkLite.iife.js +2 -1
- package/dist/ArtalkLite.iife.js.map +1 -0
- package/dist/ArtalkLite.js +2 -1
- package/dist/ArtalkLite.js.map +1 -0
- package/dist/i18n/jp.js +1 -1
- package/dist/i18n/zh-TW.js +1 -1
- package/dist/src/api/_base.d.ts +7 -0
- package/dist/src/api/_options.d.ts +5 -0
- package/dist/src/artalk.d.ts +0 -2
- package/dist/src/components/checker/index.d.ts +2 -0
- package/dist/src/i18n/en.d.ts +4 -0
- package/dist/src/i18n/external.d.ts +4 -0
- package/dist/src/i18n/index.d.ts +12 -0
- package/dist/src/i18n/jp.d.ts +4 -0
- package/dist/src/i18n/zh-TW.d.ts +4 -0
- package/dist/src/lib/user.d.ts +8 -6
- package/dist/src/main.d.ts +3 -0
- package/dist/src/plugins/editor/_kit.d.ts +7 -1
- package/dist/src/service.d.ts +2 -8
- package/dist/types/event.d.ts +1 -1
- package/package.json +43 -17
- package/dist/src/components/dark-mode.d.ts +0 -2
- package/src/api/_base.ts +0 -18
- package/src/api/_options.ts +0 -25
- package/src/api/_request.ts +0 -104
- package/src/api/admin.ts +0 -18
- package/src/api/captcha.ts +0 -24
- package/src/api/comment.ts +0 -84
- package/src/api/index.ts +0 -29
- package/src/api/page.ts +0 -83
- package/src/api/site.ts +0 -51
- package/src/api/system.ts +0 -49
- package/src/api/upload.ts +0 -28
- package/src/api/user.ts +0 -132
- package/src/artalk.ts +0 -119
- package/src/comment/actions.ts +0 -83
- package/src/comment/comment.html +0 -18
- package/src/comment/comment.ts +0 -192
- package/src/comment/height-limit.ts +0 -100
- package/src/comment/index.ts +0 -3
- package/src/comment/render.ts +0 -150
- package/src/comment/renders/actions.ts +0 -114
- package/src/comment/renders/avatar.ts +0 -22
- package/src/comment/renders/content.ts +0 -39
- package/src/comment/renders/header.ts +0 -84
- package/src/comment/renders/index.ts +0 -19
- package/src/comment/renders/pending.ts +0 -12
- package/src/comment/renders/reply-at.ts +0 -16
- package/src/comment/renders/reply-to.ts +0 -24
- package/src/components/action-btn.ts +0 -170
- package/src/components/checker/admin.ts +0 -37
- package/src/components/checker/captcha-renders.ts +0 -69
- package/src/components/checker/captcha.ts +0 -26
- package/src/components/checker/index.ts +0 -192
- package/src/components/dark-mode.ts +0 -30
- package/src/components/dialog.ts +0 -62
- package/src/components/error-dialog.ts +0 -35
- package/src/components/pagination.ts +0 -153
- package/src/components/read-more-btn.ts +0 -92
- package/src/config.ts +0 -119
- package/src/context.ts +0 -146
- package/src/data.ts +0 -110
- package/src/defaults.ts +0 -61
- package/src/editor/editor.html +0 -18
- package/src/editor/editor.ts +0 -114
- package/src/editor/state.ts +0 -52
- package/src/editor/ui.ts +0 -36
- package/src/i18n/en.ts +0 -81
- package/src/i18n/external.ts +0 -10
- package/src/i18n/index.ts +0 -67
- package/src/i18n/jp.ts +0 -83
- package/src/i18n/zh-CN.ts +0 -85
- package/src/i18n/zh-TW.ts +0 -83
- package/src/layer/index.ts +0 -4
- package/src/layer/layer-manager.ts +0 -32
- package/src/layer/layer.ts +0 -39
- package/src/layer/scrollbar-helper.ts +0 -24
- package/src/layer/sidebar-layer.html +0 -8
- package/src/layer/sidebar-layer.ts +0 -155
- package/src/layer/wrap.ts +0 -77
- package/src/lib/component.ts +0 -12
- package/src/lib/detect.ts +0 -222
- package/src/lib/event-manager.ts +0 -47
- package/src/lib/highlight.ts +0 -5
- package/src/lib/marked-renderer.ts +0 -32
- package/src/lib/marked.ts +0 -72
- package/src/lib/sanitizer.ts +0 -57
- package/src/lib/ui.ts +0 -193
- package/src/lib/user.ts +0 -55
- package/src/lib/utils.ts +0 -236
- package/src/list/comment.ts +0 -20
- package/src/list/layout.ts +0 -120
- package/src/list/list.html +0 -20
- package/src/list/list.ts +0 -79
- package/src/list/nest.ts +0 -66
- package/src/list/page.ts +0 -97
- package/src/list/paginator/index.ts +0 -25
- package/src/list/paginator/read-more.ts +0 -67
- package/src/list/paginator/up-down.ts +0 -51
- package/src/main.ts +0 -5
- package/src/plugins/admin-only-elem.ts +0 -40
- package/src/plugins/conf-remoter.ts +0 -54
- package/src/plugins/dark-mode.ts +0 -12
- package/src/plugins/editor/_kit.ts +0 -57
- package/src/plugins/editor/_plug.ts +0 -60
- package/src/plugins/editor/_sample.ts +0 -8
- package/src/plugins/editor/closable.ts +0 -44
- package/src/plugins/editor/emoticons.scss +0 -72
- package/src/plugins/editor/emoticons.ts +0 -293
- package/src/plugins/editor/header-event.ts +0 -35
- package/src/plugins/editor/header-link.ts +0 -31
- package/src/plugins/editor/header-user.ts +0 -98
- package/src/plugins/editor/index.ts +0 -40
- package/src/plugins/editor/local-storage.ts +0 -36
- package/src/plugins/editor/mover.ts +0 -29
- package/src/plugins/editor/preview.scss +0 -7
- package/src/plugins/editor/preview.ts +0 -41
- package/src/plugins/editor/state-edit.ts +0 -116
- package/src/plugins/editor/state-reply.ts +0 -91
- package/src/plugins/editor/submit-add.ts +0 -33
- package/src/plugins/editor/submit-btn.ts +0 -25
- package/src/plugins/editor/submit.ts +0 -73
- package/src/plugins/editor/textarea.ts +0 -55
- package/src/plugins/editor/upload.ts +0 -145
- package/src/plugins/editor-kit.ts +0 -161
- package/src/plugins/index.ts +0 -16
- package/src/plugins/list/copyright.ts +0 -16
- package/src/plugins/list/count.ts +0 -31
- package/src/plugins/list/dropdown.ts +0 -95
- package/src/plugins/list/error-dialog.ts +0 -22
- package/src/plugins/list/fetch.ts +0 -64
- package/src/plugins/list/goto-first.ts +0 -23
- package/src/plugins/list/goto.ts +0 -72
- package/src/plugins/list/index.ts +0 -25
- package/src/plugins/list/loading.ts +0 -17
- package/src/plugins/list/no-comment.ts +0 -25
- package/src/plugins/list/reach-bottom.ts +0 -46
- package/src/plugins/list/sidebar-btn.ts +0 -39
- package/src/plugins/list/time-ticking.ts +0 -22
- package/src/plugins/list/unread-badge.ts +0 -26
- package/src/plugins/list/unread.ts +0 -38
- package/src/plugins/list/with-editor.ts +0 -59
- package/src/plugins/markdown.ts +0 -10
- package/src/plugins/stat.ts +0 -79
- package/src/plugins/version-check.ts +0 -37
- package/src/service.ts +0 -91
- package/src/style/_color.scss +0 -41
- package/src/style/_extend.scss +0 -20
- package/src/style/_variables.scss +0 -3
- package/src/style/comment.scss +0 -360
- package/src/style/editor.scss +0 -194
- package/src/style/list.scss +0 -212
- package/src/style/main.scss +0 -486
- package/src/style/pagination.scss +0 -58
- package/src/style/sidebar-layer.scss +0 -92
- package/types/config.ts +0 -153
- package/types/context.ts +0 -84
- package/types/data.ts +0 -271
- package/types/editor.ts +0 -95
- package/types/event.ts +0 -40
- package/types/global.d.ts +0 -1
- package/types/index.ts +0 -7
- package/types/plugin.ts +0 -3
- package/types/sidebar.ts +0 -3
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
import * as Ui from '@/lib/ui'
|
|
3
|
-
|
|
4
|
-
export const Loading: ArtalkPlugin = (ctx) => {
|
|
5
|
-
ctx.on('list-fetch', (p) => {
|
|
6
|
-
const list = ctx.get('list')
|
|
7
|
-
|
|
8
|
-
if (p.offset === 0) // only show loading when fetch first page
|
|
9
|
-
Ui.setLoading(true, list.$el)
|
|
10
|
-
// else if not first page, show loading in paginator (code not there)
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
ctx.on('list-fetched', () => {
|
|
14
|
-
const list = ctx.get('list')
|
|
15
|
-
Ui.setLoading(false, list.$el)
|
|
16
|
-
})
|
|
17
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
import * as Utils from '@/lib/utils'
|
|
3
|
-
import { sanitize } from '@/lib/sanitizer'
|
|
4
|
-
|
|
5
|
-
export const NoComment: ArtalkPlugin = (ctx) => {
|
|
6
|
-
ctx.on('list-loaded', (comments) => {
|
|
7
|
-
const list = ctx.get('list')!
|
|
8
|
-
|
|
9
|
-
// 无评论
|
|
10
|
-
const isNoComment = comments.length <= 0
|
|
11
|
-
let $noComment = list.getCommentsWrapEl().querySelector<HTMLElement>('.atk-list-no-comment')
|
|
12
|
-
|
|
13
|
-
if (isNoComment) {
|
|
14
|
-
if (!$noComment) {
|
|
15
|
-
$noComment = Utils.createElement('<div class="atk-list-no-comment"></div>')
|
|
16
|
-
|
|
17
|
-
// sanitize before set innerHTML
|
|
18
|
-
$noComment.innerHTML = sanitize(list.ctx.conf.noComment || list.ctx.$t('noComment'))
|
|
19
|
-
list.getCommentsWrapEl().appendChild($noComment)
|
|
20
|
-
}
|
|
21
|
-
} else {
|
|
22
|
-
$noComment?.remove()
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
|
|
3
|
-
export const ReachBottom: ArtalkPlugin = (ctx) => {
|
|
4
|
-
const scrollEvtAt = document // TODO support ref ctx.conf
|
|
5
|
-
let observer: IntersectionObserver|null = null
|
|
6
|
-
|
|
7
|
-
const setupObserver = ($target: HTMLElement) => {
|
|
8
|
-
// eslint-disable-next-line compat/compat
|
|
9
|
-
observer = new IntersectionObserver(([entries]) => {
|
|
10
|
-
if (entries.isIntersecting) {
|
|
11
|
-
clearObserver()
|
|
12
|
-
ctx.trigger('list-reach-bottom')
|
|
13
|
-
}
|
|
14
|
-
}, {
|
|
15
|
-
root: scrollEvtAt
|
|
16
|
-
})
|
|
17
|
-
observer.observe($target)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const clearObserver = () => {
|
|
21
|
-
observer?.disconnect()
|
|
22
|
-
observer = null
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
ctx.on('list-loaded', () => {
|
|
26
|
-
clearObserver()
|
|
27
|
-
|
|
28
|
-
const list = ctx.get('list')
|
|
29
|
-
|
|
30
|
-
// use IntersectionObserver to detect reach bottom
|
|
31
|
-
const $target = list.getCommentsWrapEl().querySelector<HTMLElement>('.atk-comment-wrap:nth-last-child(3)')
|
|
32
|
-
if (!$target) return
|
|
33
|
-
|
|
34
|
-
// check IntersectionObserver support
|
|
35
|
-
if (!('IntersectionObserver' in window)) {
|
|
36
|
-
console.warn('IntersectionObserver api not supported')
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
setupObserver($target)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
ctx.on('destroy', () => {
|
|
44
|
-
clearObserver()
|
|
45
|
-
})
|
|
46
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
import $t from '@/i18n'
|
|
3
|
-
|
|
4
|
-
export const SidebarBtn: ArtalkPlugin = (ctx) => {
|
|
5
|
-
let $openSidebarBtn: HTMLElement|null = null
|
|
6
|
-
|
|
7
|
-
const syncByUser = () => {
|
|
8
|
-
if (!$openSidebarBtn) return
|
|
9
|
-
const user = ctx.get('user').data
|
|
10
|
-
|
|
11
|
-
// 已输入个人信息
|
|
12
|
-
if (!!user.nick && !!user.email) {
|
|
13
|
-
$openSidebarBtn.classList.remove('atk-hide')
|
|
14
|
-
|
|
15
|
-
// update button text (normal user or admin)
|
|
16
|
-
const $btnText = $openSidebarBtn.querySelector<HTMLElement>('.atk-text')
|
|
17
|
-
if ($btnText) $btnText.innerText = (!user.isAdmin) ? $t('msgCenter') : $t('ctrlCenter')
|
|
18
|
-
} else {
|
|
19
|
-
$openSidebarBtn.classList.add('atk-hide')
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
ctx.on('conf-loaded', () => {
|
|
24
|
-
const list = ctx.get('list')
|
|
25
|
-
|
|
26
|
-
$openSidebarBtn = list.$el.querySelector<HTMLElement>('[data-action="open-sidebar"]')
|
|
27
|
-
if (!$openSidebarBtn) return
|
|
28
|
-
|
|
29
|
-
$openSidebarBtn.onclick = () => { // use onclick rather than addEventListener to prevent duplicate event
|
|
30
|
-
ctx.showSidebar()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
syncByUser()
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
ctx.on('user-changed', (user) => {
|
|
37
|
-
syncByUser()
|
|
38
|
-
})
|
|
39
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
import * as Utils from '@/lib/utils'
|
|
3
|
-
|
|
4
|
-
/** 评论时间自动更新 */
|
|
5
|
-
export const TimeTicking: ArtalkPlugin = (ctx) => {
|
|
6
|
-
let timer: number|null = null
|
|
7
|
-
|
|
8
|
-
ctx.on('inited', () => {
|
|
9
|
-
timer = window.setInterval(() => {
|
|
10
|
-
const list = ctx.get('list')
|
|
11
|
-
|
|
12
|
-
list.$el.querySelectorAll<HTMLElement>('[data-atk-comment-date]').forEach(el => {
|
|
13
|
-
const date = el.getAttribute('data-atk-comment-date')
|
|
14
|
-
el.innerText = Utils.timeAgo(new Date(Number(date)), ctx.$t)
|
|
15
|
-
})
|
|
16
|
-
}, 30 * 1000) // 30s 更新一次
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
ctx.on('destroy', () => {
|
|
20
|
-
timer && window.clearInterval(timer)
|
|
21
|
-
})
|
|
22
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
|
|
3
|
-
export const UnreadBadge: ArtalkPlugin = (ctx) => {
|
|
4
|
-
let $unreadBadge: HTMLElement|null = null
|
|
5
|
-
|
|
6
|
-
const showUnreadBadge = (count: number) => {
|
|
7
|
-
if (!$unreadBadge) return
|
|
8
|
-
|
|
9
|
-
if (count > 0) {
|
|
10
|
-
$unreadBadge.innerText = `${Number(count || 0)}`
|
|
11
|
-
$unreadBadge.style.display = 'block'
|
|
12
|
-
} else {
|
|
13
|
-
$unreadBadge.style.display = 'none'
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
ctx.on('conf-loaded', () => {
|
|
18
|
-
const list = ctx.get('list')
|
|
19
|
-
|
|
20
|
-
$unreadBadge = list.$el.querySelector<HTMLElement>('.atk-unread-badge')
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
ctx.on('unreads-updated', (unreads) => {
|
|
24
|
-
showUnreadBadge(unreads.length || 0)
|
|
25
|
-
})
|
|
26
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
import * as Utils from '@/lib/utils'
|
|
3
|
-
|
|
4
|
-
export const Unread: ArtalkPlugin = (ctx) => {
|
|
5
|
-
ctx.on('comment-rendered', (comment) => {
|
|
6
|
-
// comment unread highlight
|
|
7
|
-
if (ctx.conf.listUnreadHighlight === true) {
|
|
8
|
-
const unreads = ctx.getData().getUnreads()
|
|
9
|
-
const notify = unreads.find(o => o.comment_id === comment.getID())
|
|
10
|
-
|
|
11
|
-
if (notify) {
|
|
12
|
-
// if comment contains in unread list
|
|
13
|
-
comment.getRender().setUnread(true)
|
|
14
|
-
comment.getRender().setOpenAction(() => {
|
|
15
|
-
window.open(notify.read_link)
|
|
16
|
-
|
|
17
|
-
// remove notify which has been read
|
|
18
|
-
ctx.getData().updateUnreads(unreads.filter(o => o.comment_id !== comment.getID()))
|
|
19
|
-
})
|
|
20
|
-
} else {
|
|
21
|
-
// comment not in unread list
|
|
22
|
-
comment.getRender().setUnread(false)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
ctx.on('list-goto', (commentID) => {
|
|
28
|
-
const notifyKey = Utils.getQueryParam('atk_notify_key')
|
|
29
|
-
if (notifyKey) {
|
|
30
|
-
// mark as read
|
|
31
|
-
ctx.getApi().user.markRead(commentID, notifyKey)
|
|
32
|
-
.then(() => {
|
|
33
|
-
// remove from unread list
|
|
34
|
-
ctx.getData().updateUnreads(ctx.getData().getUnreads().filter(o => o.comment_id !== commentID))
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { ContextApi, ArtalkPlugin, PageData } from '~/types'
|
|
2
|
-
import $t from '@/i18n'
|
|
3
|
-
|
|
4
|
-
export const WithEditor: ArtalkPlugin = (ctx) => {
|
|
5
|
-
let $closeCommentBtn: HTMLElement|undefined
|
|
6
|
-
|
|
7
|
-
// on Artalk inited
|
|
8
|
-
// (after all components had mounted)
|
|
9
|
-
ctx.on('inited', () => {
|
|
10
|
-
const list = ctx.get('list')
|
|
11
|
-
|
|
12
|
-
$closeCommentBtn = list.$el.querySelector<HTMLElement>('[data-action="admin-close-comment"]')!
|
|
13
|
-
|
|
14
|
-
// bind editor close button click event
|
|
15
|
-
$closeCommentBtn.addEventListener('click', () => {
|
|
16
|
-
const page = ctx.getData().getPage()
|
|
17
|
-
if (!page) throw new Error('Page data not found')
|
|
18
|
-
|
|
19
|
-
page.admin_only = !page.admin_only
|
|
20
|
-
adminPageEditSave(ctx, page)
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
// on comment list loaded (it will include page data update)
|
|
25
|
-
ctx.on('page-loaded', (page) => {
|
|
26
|
-
const editor = ctx.get('editor')
|
|
27
|
-
|
|
28
|
-
// if page comment is closed
|
|
29
|
-
if (page?.admin_only === true) {
|
|
30
|
-
// then close editor
|
|
31
|
-
editor.getPlugs()?.getEvents().trigger('editor-close')
|
|
32
|
-
$closeCommentBtn && ($closeCommentBtn.innerText = $t('openComment'))
|
|
33
|
-
} else {
|
|
34
|
-
// the open editor
|
|
35
|
-
editor.getPlugs()?.getEvents().trigger('editor-open')
|
|
36
|
-
$closeCommentBtn && ($closeCommentBtn.innerText = $t('closeComment'))
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
ctx.on('list-loaded', (comments) => {
|
|
41
|
-
// 防止评论框被吞
|
|
42
|
-
ctx.editorResetState()
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** 管理员设置页面信息 */
|
|
47
|
-
function adminPageEditSave(ctx: ContextApi, page: PageData) {
|
|
48
|
-
ctx.editorShowLoading()
|
|
49
|
-
ctx.getApi().page.pageEdit(page)
|
|
50
|
-
.then((respPage) => {
|
|
51
|
-
ctx.getData().updatePage(respPage)
|
|
52
|
-
})
|
|
53
|
-
.catch(err => {
|
|
54
|
-
ctx.editorShowNotify(`${$t('editFail')}: ${err.msg || String(err)}`, 'e')
|
|
55
|
-
})
|
|
56
|
-
.finally(() => {
|
|
57
|
-
ctx.editorHideLoading()
|
|
58
|
-
})
|
|
59
|
-
}
|
package/src/plugins/markdown.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
import * as marked from '@/lib/marked'
|
|
3
|
-
|
|
4
|
-
export const Markdown: ArtalkPlugin = (ctx) => {
|
|
5
|
-
marked.initMarked()
|
|
6
|
-
|
|
7
|
-
ctx.on('conf-loaded', (conf) => {
|
|
8
|
-
if (conf.markedReplacers) marked.setReplacers(conf.markedReplacers)
|
|
9
|
-
})
|
|
10
|
-
}
|
package/src/plugins/stat.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { ContextApi, ArtalkPlugin } from '~/types'
|
|
2
|
-
import Api from '../api'
|
|
3
|
-
|
|
4
|
-
export interface CountOptions {
|
|
5
|
-
getApi(): Api
|
|
6
|
-
|
|
7
|
-
pageKey: string
|
|
8
|
-
countEl: string
|
|
9
|
-
pvEl: string
|
|
10
|
-
|
|
11
|
-
/** 是否增加当前页面 PV 数 */
|
|
12
|
-
pvAdd?: boolean
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const PvCountWidget: ArtalkPlugin = (ctx: ContextApi) => {
|
|
16
|
-
ctx.on('conf-loaded', () => {
|
|
17
|
-
initCountWidget({
|
|
18
|
-
getApi: () => ctx.getApi(),
|
|
19
|
-
pageKey: ctx.conf.pageKey,
|
|
20
|
-
countEl: ctx.conf.countEl,
|
|
21
|
-
pvEl: ctx.conf.pvEl,
|
|
22
|
-
pvAdd: true,
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** 初始化评论数和 PV 数量展示元素 */
|
|
28
|
-
export async function initCountWidget(opt: CountOptions) {
|
|
29
|
-
// 评论数
|
|
30
|
-
if (opt.countEl && document.querySelector(opt.countEl)) {
|
|
31
|
-
refreshStatCount(opt, { query: 'page_comment', numEl: opt.countEl })
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// PV
|
|
35
|
-
const curtPagePvNum = opt.pvAdd ? await opt.getApi().page.pv() : NaN
|
|
36
|
-
if (opt.pvEl && document.querySelector(opt.pvEl)) {
|
|
37
|
-
refreshStatCount(opt, {
|
|
38
|
-
query: 'page_pv',
|
|
39
|
-
numEl: opt.pvEl,
|
|
40
|
-
data: { [opt.pageKey]: curtPagePvNum },
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
type CountData = { [pageKey: string]: number }
|
|
46
|
-
|
|
47
|
-
async function refreshStatCount(
|
|
48
|
-
opt: CountOptions,
|
|
49
|
-
args: {
|
|
50
|
-
query: 'page_pv' | 'page_comment'
|
|
51
|
-
numEl: string
|
|
52
|
-
data?: CountData
|
|
53
|
-
}
|
|
54
|
-
) {
|
|
55
|
-
let data: CountData = args.data || {}
|
|
56
|
-
|
|
57
|
-
// Get page keys from DOM
|
|
58
|
-
let pageKeys = Array.from(document.querySelectorAll(args.numEl))
|
|
59
|
-
.map((e) => e.getAttribute('data-page-key') || opt.pageKey)
|
|
60
|
-
.filter((e) => Number.isNaN(data[e])) // filter out keys that already have data
|
|
61
|
-
|
|
62
|
-
pageKeys = [...new Set(pageKeys)] // deduplicate
|
|
63
|
-
|
|
64
|
-
// Fetch count data from server
|
|
65
|
-
if (pageKeys.length > 0) {
|
|
66
|
-
const res = await opt.getApi().page.stat(args.query, pageKeys) as CountData
|
|
67
|
-
data = { ...data, ...res }
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
applyCountData(args.numEl, data, data[opt.pageKey])
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function applyCountData(selector: string, data: CountData, defaultCount: number) {
|
|
74
|
-
document.querySelectorAll(selector).forEach((el) => {
|
|
75
|
-
const pageKey = el.getAttribute('data-page-key')
|
|
76
|
-
const count = Number(pageKey ? (data[pageKey]) : defaultCount)
|
|
77
|
-
el.innerHTML = `${count}`
|
|
78
|
-
})
|
|
79
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { ArtalkPlugin } from '~/types'
|
|
2
|
-
import { version as ARTALK_VERSION } from '~/package.json'
|
|
3
|
-
import type List from '~/src/list/list'
|
|
4
|
-
import * as Ui from '@/lib/ui'
|
|
5
|
-
import * as Utils from '@/lib/utils'
|
|
6
|
-
import $t from '@/i18n'
|
|
7
|
-
|
|
8
|
-
let IgnoreVersionCheck = false
|
|
9
|
-
|
|
10
|
-
export const VersionCheck: ArtalkPlugin = (ctx) => {
|
|
11
|
-
ctx.on('conf-loaded', () => {
|
|
12
|
-
const list = ctx.get('list')
|
|
13
|
-
if (ctx.conf.apiVersion && ctx.conf.versionCheck && !IgnoreVersionCheck)
|
|
14
|
-
versionCheck(list, ARTALK_VERSION, ctx.conf.apiVersion)
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function versionCheck(list: List, feVer: string, beVer: string) {
|
|
19
|
-
const comp = Utils.versionCompare(feVer, beVer)
|
|
20
|
-
const sameVer = (comp === 0)
|
|
21
|
-
if (sameVer) return
|
|
22
|
-
|
|
23
|
-
const errEl = Utils.createElement(
|
|
24
|
-
`<div>请更新 Artalk ${comp < 0 ? $t('frontend') : $t('backend')}以获得完整体验 ` +
|
|
25
|
-
`(<a href="https://artalk.js.org/" target="_blank">帮助文档</a>)` +
|
|
26
|
-
`<br/><br/><span style="color: var(--at-color-meta);">` +
|
|
27
|
-
`当前版本:${$t('frontend')} ${feVer} / ${$t('backend')} ${beVer}` +
|
|
28
|
-
`</span><br/><br/></div>`)
|
|
29
|
-
const ignoreBtn = Utils.createElement('<span style="cursor:pointer">忽略</span>')
|
|
30
|
-
ignoreBtn.onclick = () => {
|
|
31
|
-
Ui.setError(list.$el.parentElement!, null)
|
|
32
|
-
IgnoreVersionCheck = true
|
|
33
|
-
list.ctx.fetch({ offset: 0 })
|
|
34
|
-
}
|
|
35
|
-
errEl.append(ignoreBtn)
|
|
36
|
-
Ui.setError(list.$el.parentElement!, errEl, '<span class="atk-warn-title">Artalk Warn</span>')
|
|
37
|
-
}
|
package/src/service.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import type { ContextApi } from '~/types'
|
|
2
|
-
import CheckerLauncher from './components/checker'
|
|
3
|
-
import Editor from './editor/editor'
|
|
4
|
-
import SidebarLayer from './layer/sidebar-layer'
|
|
5
|
-
|
|
6
|
-
import User from './lib/user'
|
|
7
|
-
import List from './list/list'
|
|
8
|
-
|
|
9
|
-
import * as I18n from './i18n'
|
|
10
|
-
import { PlugManager } from './plugins/editor-kit'
|
|
11
|
-
import { LayerManager } from './layer/layer-manager'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Services
|
|
15
|
-
*
|
|
16
|
-
* @description Call these services by `ctx.get('serviceName')` or `ctx.serviceName`
|
|
17
|
-
*/
|
|
18
|
-
const services = {
|
|
19
|
-
// I18n
|
|
20
|
-
i18n(ctx: ContextApi) {
|
|
21
|
-
I18n.setLocale(ctx.conf.locale)
|
|
22
|
-
|
|
23
|
-
ctx.on('conf-loaded', () => {
|
|
24
|
-
I18n.setLocale(ctx.conf.locale)
|
|
25
|
-
})
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
// User Store
|
|
29
|
-
user(ctx: ContextApi) {
|
|
30
|
-
User.setOnUserChanged((user) => {
|
|
31
|
-
ctx?.trigger('user-changed', user)
|
|
32
|
-
})
|
|
33
|
-
return User
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
// 弹出层
|
|
37
|
-
layerManager(ctx: ContextApi) {
|
|
38
|
-
return new LayerManager(ctx)
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
// CheckerLauncher
|
|
42
|
-
checkerLauncher(ctx: ContextApi) {
|
|
43
|
-
const checkerLauncher = new CheckerLauncher({
|
|
44
|
-
getCtx: () => ctx,
|
|
45
|
-
getApi: () => ctx.getApi(),
|
|
46
|
-
getIframeURLBase: () => ctx.conf.server,
|
|
47
|
-
onReload: () => ctx.reload()
|
|
48
|
-
})
|
|
49
|
-
return checkerLauncher
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
// 编辑器
|
|
53
|
-
editor(ctx: ContextApi) {
|
|
54
|
-
const editor = new Editor(ctx)
|
|
55
|
-
ctx.$root.appendChild(editor.$el)
|
|
56
|
-
return editor
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
// 评论列表
|
|
60
|
-
list(ctx: ContextApi): List {
|
|
61
|
-
const list = new List(ctx)
|
|
62
|
-
ctx.$root.appendChild(list.$el)
|
|
63
|
-
return list
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
// 侧边栏 Layer
|
|
67
|
-
sidebarLayer(ctx: ContextApi) {
|
|
68
|
-
const sidebarLayer = new SidebarLayer(ctx)
|
|
69
|
-
return sidebarLayer
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
// Extra Service
|
|
73
|
-
// -----------------------------------------
|
|
74
|
-
// Only for type check
|
|
75
|
-
// Not inject to ctx immediately,
|
|
76
|
-
// but can be injected by other occasions
|
|
77
|
-
|
|
78
|
-
editorPlugs(): PlugManager|undefined {
|
|
79
|
-
return undefined
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export default services
|
|
84
|
-
|
|
85
|
-
// type tricks for dependency injection
|
|
86
|
-
type TServiceImps = typeof services
|
|
87
|
-
type TObjectWithFuncs = {[k: string]: (...args: any) => any}
|
|
88
|
-
type TKeysOnlyReturn<T extends TObjectWithFuncs, V> = {[K in keyof T]: ReturnType<T[K]> extends V ? K : never}[keyof T]
|
|
89
|
-
type TOmitConditions = TKeysOnlyReturn<TServiceImps, void>
|
|
90
|
-
type TServiceInjectors = Omit<TServiceImps, TOmitConditions>
|
|
91
|
-
export type TInjectedServices = {[K in keyof TServiceInjectors]: ReturnType<TServiceInjectors[K]>}
|
package/src/style/_color.scss
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
.artalk, .atk-layer-wrap {
|
|
2
|
-
--at-color-font: #2a2e2e;
|
|
3
|
-
--at-color-deep: #2a2e2e;
|
|
4
|
-
--at-color-sub: #757575;
|
|
5
|
-
--at-color-grey: #747474;
|
|
6
|
-
--at-color-meta: #697182;
|
|
7
|
-
--at-color-border: #eceff2;
|
|
8
|
-
--at-color-light: #4285f4;
|
|
9
|
-
--at-color-bg: #FFF;
|
|
10
|
-
--at-color-bg-transl: rgba(255, 255, 255, 0.94);
|
|
11
|
-
--at-color-bg-grey: #f3f4f5;
|
|
12
|
-
--at-color-bg-grey-transl: rgba(244, 244, 244, 0.75);
|
|
13
|
-
--at-color-bg-light: rgba(29, 161, 242, 0.1);
|
|
14
|
-
--at-color-main: #0083ff;
|
|
15
|
-
--at-color-red: #ff5652;
|
|
16
|
-
--at-color-pink: #fa5a57;
|
|
17
|
-
--at-color-yellow: #ff7c37;
|
|
18
|
-
--at-color-green: #4caf50;
|
|
19
|
-
--at-color-gradient: linear-gradient(180deg, transparent, rgba(255, 255, 255));
|
|
20
|
-
|
|
21
|
-
&.atk-dark-mode {
|
|
22
|
-
--at-color-font: #fff;
|
|
23
|
-
--at-color-deep: #e7e7e7;
|
|
24
|
-
--at-color-sub: #e7e7e7;
|
|
25
|
-
--at-color-grey: #fff;
|
|
26
|
-
--at-color-meta: #fff;
|
|
27
|
-
--at-color-border: #2d3235;
|
|
28
|
-
--at-color-light: #687a86;
|
|
29
|
-
--at-color-bg: #1e2224;
|
|
30
|
-
--at-color-bg-transl: rgba(30, 34, 36, 0.95);
|
|
31
|
-
--at-color-bg-grey: #46494e;
|
|
32
|
-
--at-color-bg-grey-transl: rgba(8, 8, 8, 0.95);
|
|
33
|
-
--at-color-bg-light: rgba(29, 161, 242, 0.1);
|
|
34
|
-
--at-color-main: #0083ff;
|
|
35
|
-
--at-color-red: #ff5652;
|
|
36
|
-
--at-color-pink: #fa5a57;
|
|
37
|
-
--at-color-yellow: #ff7c37;
|
|
38
|
-
--at-color-green: #4caf50;
|
|
39
|
-
--at-color-gradient: linear-gradient(180deg, transparent, rgba(30, 34, 36, 1));
|
|
40
|
-
}
|
|
41
|
-
}
|
package/src/style/_extend.scss
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
.atk-slim-scrollbar {
|
|
2
|
-
&::-webkit-scrollbar {
|
|
3
|
-
width: 4px;
|
|
4
|
-
height: 4px;
|
|
5
|
-
background: transparent;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
&::-webkit-scrollbar-thumb,
|
|
9
|
-
&::-webkit-scrollbar-thumb:window-inactive {
|
|
10
|
-
background: rgba(86,86,86,.3);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
&::-webkit-scrollbar-thumb:vertical:hover {
|
|
14
|
-
background: rgba(65,74,82,.77);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
&::-webkit-scrollbar-thumb:vertical:active {
|
|
18
|
-
background: rgba(41,47,53,.77);
|
|
19
|
-
}
|
|
20
|
-
}
|