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,4 +0,0 @@
1
- export * from './layer'
2
- export * from './wrap'
3
- export * from './scrollbar-helper'
4
- export * from './layer-manager'
@@ -1,32 +0,0 @@
1
- import type { ContextApi } from '~/types'
2
- import { getScrollbarHelper } from './scrollbar-helper'
3
- import { LayerWrap } from './wrap'
4
- import { Layer } from './layer'
5
-
6
- export class LayerManager {
7
- private wrap: LayerWrap
8
- private ctx: ContextApi
9
-
10
- constructor(ctx: ContextApi) {
11
- this.ctx = ctx
12
-
13
- this.wrap = new LayerWrap()
14
- document.body.appendChild(this.wrap.getWrap())
15
-
16
- ctx.on('destroy', () => {
17
- this.wrap.getWrap().remove()
18
- })
19
-
20
- // 记录页面原始 CSS 属性
21
- getScrollbarHelper().init()
22
- }
23
-
24
- getEl() {
25
- return this.wrap.getWrap()
26
- }
27
-
28
- create(name: string, el?: HTMLElement | undefined) {
29
- const layer = new Layer(this.wrap, name, el)
30
- return layer
31
- }
32
- }
@@ -1,39 +0,0 @@
1
- import type { LayerWrap } from './wrap'
2
-
3
- export class Layer {
4
- private $el: HTMLElement
5
- private wrap: LayerWrap
6
- private onAfterHide?: () => void
7
-
8
- constructor(wrap: LayerWrap, name: string, el?: HTMLElement) {
9
- this.wrap = wrap
10
- this.$el = this.wrap.createItem(name, el)
11
- }
12
-
13
- setOnAfterHide(func: () => void) {
14
- this.onAfterHide = func
15
- }
16
-
17
- getEl() {
18
- return this.$el
19
- }
20
-
21
- show() {
22
- this.$el.style.display = ''
23
- this.wrap.show()
24
- }
25
-
26
- hide() {
27
- this.wrap.hide(() => {
28
- this.$el.style.display = 'none'
29
- this.onAfterHide && this.onAfterHide()
30
- })
31
- }
32
-
33
- destroy() {
34
- this.wrap.hide(() => {
35
- this.$el.remove()
36
- this.onAfterHide && this.onAfterHide()
37
- })
38
- }
39
- }
@@ -1,24 +0,0 @@
1
- import * as Ui from '@/lib/ui'
2
-
3
- let bodyOrgOverflow: string
4
- let bodyOrgPaddingRight: string
5
-
6
- export function getScrollbarHelper() {
7
- return {
8
- init() {
9
- bodyOrgOverflow = document.body.style.overflow
10
- bodyOrgPaddingRight = document.body.style.paddingRight
11
- },
12
-
13
- unlock() {
14
- document.body.style.overflow = bodyOrgOverflow
15
- document.body.style.paddingRight = bodyOrgPaddingRight
16
- },
17
-
18
- lock() {
19
- document.body.style.overflow = 'hidden'
20
- const barPaddingRight = parseInt(window.getComputedStyle(document.body, null).getPropertyValue('padding-right'), 10)
21
- document.body.style.paddingRight = `${Ui.getScrollBarWidth() + barPaddingRight || 0}px`
22
- }
23
- }
24
- }
@@ -1,8 +0,0 @@
1
- <div class="atk-sidebar-layer">
2
- <div class="atk-sidebar-inner">
3
- <div class="atk-sidebar-header">
4
- <div class="atk-sidebar-close"><i class="atk-icon atk-icon-close"></i></div>
5
- </div>
6
- <div class="atk-sidebar-iframe-wrap"></div>
7
- </div>
8
- </div>
@@ -1,155 +0,0 @@
1
- import type { ContextApi, SidebarShowPayload } from '~/types'
2
- import Component from '@/lib/component'
3
- import * as Utils from '@/lib/utils'
4
- import * as Ui from '@/lib/ui'
5
- import SidebarHTML from './sidebar-layer.html?raw'
6
- import User from '../lib/user'
7
- import type { Layer } from './layer'
8
-
9
- export default class SidebarLayer extends Component {
10
- public layer?: Layer
11
- public $header: HTMLElement
12
- public $closeBtn: HTMLElement
13
- public $iframeWrap: HTMLElement
14
- public $iframe?: HTMLIFrameElement
15
-
16
- constructor(ctx: ContextApi) {
17
- super(ctx)
18
-
19
- this.$el = Utils.createElement(SidebarHTML)
20
- this.$header = this.$el.querySelector('.atk-sidebar-header')!
21
- this.$closeBtn = this.$header.querySelector('.atk-sidebar-close')!
22
- this.$iframeWrap = this.$el.querySelector('.atk-sidebar-iframe-wrap')!
23
-
24
- this.$closeBtn.onclick = () => {
25
- this.hide()
26
- }
27
-
28
- // event
29
- this.ctx.on('user-changed', () => { this.firstShow = true })
30
- }
31
-
32
- private firstShow = true
33
-
34
- /** 显示 */
35
- public async show(conf: SidebarShowPayload = {}) {
36
- this.$el.style.transform = '' // 动画清除,防止二次打开失效
37
-
38
- // 获取 Layer
39
- this.initLayer()
40
- this.layer!.show()
41
-
42
- // 管理员身份验证 (若身份失效,弹出验证窗口)
43
- this.authCheck({
44
- onSuccess: () => this.show(conf) // retry show after auth check
45
- })
46
-
47
- // 第一次加载
48
- if (this.firstShow) {
49
- this.$iframeWrap.innerHTML = ''
50
- this.$iframe = this.createIframe(conf.view)
51
- this.$iframeWrap.append(this.$iframe)
52
- this.firstShow = false
53
- } else {
54
- const $iframe = this.$iframe!
55
-
56
- // 夜间模式
57
- const isIframeSrcDarkMode = $iframe.src.includes('darkMode=1')
58
-
59
- if (this.conf.darkMode && !isIframeSrcDarkMode)
60
- this.iframeLoad($iframe, `${this.$iframe!.src}&darkMode=1`)
61
-
62
- if (!this.conf.darkMode && isIframeSrcDarkMode)
63
- this.iframeLoad($iframe, this.$iframe!.src.replace('&darkMode=1', ''))
64
- }
65
-
66
- // 执行滑动显示动画
67
- setTimeout(() => {
68
- this.$el.style.transform = 'translate(0, 0)'
69
- }, 100)
70
-
71
- // 清空 unread
72
- setTimeout(() => {
73
- this.ctx.getData().updateUnreads([])
74
- }, 0)
75
-
76
- this.ctx.trigger('sidebar-show')
77
- }
78
-
79
- /** 隐藏 */
80
- public hide() {
81
- // 执行动画
82
- this.$el.style.transform = ''
83
-
84
- this.layer?.hide()
85
-
86
- this.ctx.trigger('sidebar-hide')
87
- }
88
-
89
- // --------------------------------------------------
90
-
91
- private async authCheck(opts: { onSuccess: () => void }) {
92
- const resp = await this.ctx.getApi().user.loginStatus()
93
- if (resp.is_admin && !resp.is_login) {
94
- this.firstShow = true
95
-
96
- this.ctx.checkAdmin({
97
- onSuccess: () => {
98
- setTimeout(() => {
99
- opts.onSuccess()
100
- }, 500)
101
- },
102
- onCancel: () => {
103
- this.hide()
104
- }
105
- })
106
- }
107
- }
108
-
109
- private initLayer() {
110
- if (this.layer) return
111
-
112
- this.layer = this.ctx.get('layerManager').create('sidebar', this.$el)
113
- this.layer.setOnAfterHide(() => {
114
- // 防止评论框被吞
115
- this.ctx.editorResetState()
116
- })
117
- }
118
-
119
- private createIframe(view?: string) {
120
- const $iframe = Utils.createElement<HTMLIFrameElement>('<iframe></iframe>')
121
-
122
- // 准备 Iframe 参数
123
- const baseURL = (import.meta.env.DEV) ? 'http://localhost:23367/'
124
- : Utils.getURLBasedOnApi({
125
- base: this.ctx.conf.server,
126
- path: '/sidebar/',
127
- })
128
-
129
- const query: any = {
130
- pageKey: this.conf.pageKey,
131
- site: this.conf.site || '',
132
- user: JSON.stringify(User.data),
133
- time: +new Date()
134
- }
135
-
136
- if (view) query.view = view
137
- if (this.conf.darkMode) query.darkMode = '1'
138
- if (typeof this.conf.locale === 'string') query.locale = this.conf.locale
139
-
140
- const urlParams = new URLSearchParams(query);
141
- this.iframeLoad($iframe, `${baseURL}?${urlParams.toString()}`)
142
-
143
- return $iframe
144
- }
145
-
146
- private iframeLoad($iframe: HTMLIFrameElement, src: string) {
147
- $iframe.src = src
148
-
149
- // 加载动画
150
- Ui.showLoading(this.$iframeWrap)
151
- $iframe.onload = () => {
152
- Ui.hideLoading(this.$iframeWrap)
153
- }
154
- }
155
- }
package/src/layer/wrap.ts DELETED
@@ -1,77 +0,0 @@
1
- import * as Utils from '@/lib/utils'
2
- import { getScrollbarHelper } from './scrollbar-helper'
3
-
4
- export class LayerWrap {
5
- private $wrap: HTMLElement
6
- private $mask: HTMLElement
7
- private allowMaskClose: boolean = true
8
- private items: HTMLElement[] = []
9
-
10
- constructor() {
11
- this.$wrap = Utils.createElement(
12
- `<div class="atk-layer-wrap" style="display: none;"><div class="atk-layer-mask"></div></div>`
13
- )
14
- this.$mask = this.$wrap.querySelector<HTMLElement>('.atk-layer-mask')!
15
- }
16
-
17
- createItem(name: string, el?: HTMLElement) {
18
- if (!el) {
19
- el = document.createElement('div')
20
- el.classList.add('atk-layer-item')
21
- el.setAttribute('data-layer-name', name)
22
- el.style.display = 'none'
23
- }
24
- this.$wrap.appendChild(el)
25
- this.items.push(el)
26
- return el
27
- }
28
-
29
- getWrap() {
30
- return this.$wrap
31
- }
32
-
33
- getMask() {
34
- return this.$mask
35
- }
36
-
37
- setMaskClose(enabled: boolean) {
38
- this.allowMaskClose = enabled
39
- }
40
-
41
- show() {
42
- this.$wrap.style.display = 'block'
43
- this.$mask.style.display = 'block'
44
- this.$mask.classList.add('atk-fade-in')
45
- this.$mask.onclick = () => {
46
- if (this.allowMaskClose) this.hide()
47
- }
48
- getScrollbarHelper().lock()
49
- }
50
-
51
- hide(callback?: () => void) {
52
- // if wrap contains more than one item, do not hide entire wrap
53
- if (this.items.filter(e => e.isConnected && e.style.display !== 'none').length > 1) {
54
- callback && callback()
55
- return
56
- }
57
-
58
- const onAfterHide = () => {
59
- this.$wrap.style.display = 'none'
60
- this.$wrap.classList.remove('atk-fade-out')
61
-
62
- callback && callback()
63
-
64
- getScrollbarHelper().unlock()
65
-
66
- this.$wrap.onanimationend = null
67
- }
68
-
69
- // perform animation
70
- this.$wrap.classList.add('atk-fade-out')
71
- if (window.getComputedStyle(this.$wrap)['animation-name'] !== 'none') {
72
- this.$wrap.onanimationend = () => onAfterHide()
73
- } else {
74
- onAfterHide()
75
- }
76
- }
77
- }
@@ -1,12 +0,0 @@
1
- import type { ArtalkConfig, ContextApi } from '~/types'
2
-
3
- export default abstract class Component {
4
- public $el!: HTMLElement
5
- public readonly conf: ArtalkConfig
6
-
7
- public constructor(
8
- public ctx: ContextApi
9
- ) {
10
- this.conf = ctx.conf
11
- }
12
- }
package/src/lib/detect.ts DELETED
@@ -1,222 +0,0 @@
1
- const win = (window as any) || {}
2
- const nav = navigator || {}
3
-
4
- function Detect(userAgent?: string) {
5
- const u = String(userAgent || nav.userAgent)
6
- const dest = {
7
- os: '',
8
- osVersion: '',
9
- engine: '',
10
- browser: '',
11
- device: '',
12
- language: '',
13
- version: ''
14
- }
15
-
16
- // 内核
17
- const engineMatch = {
18
- Trident: u.includes('Trident') || u.includes('NET CLR'),
19
- Presto: u.includes('Presto'),
20
- WebKit: u.includes('AppleWebKit'),
21
- Gecko: u.includes('Gecko/')
22
- }
23
-
24
- // 浏览器
25
- const browserMatch = {
26
- Safari: u.includes('Safari'),
27
- Chrome: u.includes('Chrome') || u.includes('CriOS'),
28
- IE: u.includes('MSIE') || u.includes('Trident'),
29
- Edge: u.includes('Edge') || u.includes('Edg'),
30
- Firefox: u.includes('Firefox') || u.includes('FxiOS'),
31
- 'Firefox Focus': u.includes('Focus'),
32
- Chromium: u.includes('Chromium'),
33
- Opera: u.includes('Opera') || u.includes('OPR'),
34
- Vivaldi: u.includes('Vivaldi'),
35
- Yandex: u.includes('YaBrowser'),
36
- Kindle: u.includes('Kindle') || u.includes('Silk/'),
37
- 360: u.includes('360EE') || u.includes('360SE'),
38
- UC: u.includes('UC') || u.includes(' UBrowser'),
39
- QQBrowser: u.includes('QQBrowser'),
40
- QQ: u.includes('QQ/'),
41
- Baidu: u.includes('Baidu') || u.includes('BIDUBrowser'),
42
- Maxthon: u.includes('Maxthon'),
43
- Sogou: u.includes('MetaSr') || u.includes('Sogou'),
44
- LBBROWSER: u.includes('LBBROWSER'),
45
- '2345Explorer': u.includes('2345Explorer'),
46
- TheWorld: u.includes('TheWorld'),
47
- MIUI: u.includes('MiuiBrowser'),
48
- Quark: u.includes('Quark'),
49
- Qiyu: u.includes('Qiyu'),
50
- Wechat: u.includes('MicroMessenger'),
51
- Taobao: u.includes('AliApp(TB'),
52
- Alipay: u.includes('AliApp(AP'),
53
- Weibo: u.includes('Weibo'),
54
- Douban: u.includes('com.douban.frodo'),
55
- Suning: u.includes('SNEBUY-APP'),
56
- iQiYi: u.includes('IqiyiApp'),
57
- }
58
-
59
- // 系统或平台
60
- const osMatch = {
61
- Windows: u.includes('Windows'),
62
- Linux: u.includes('Linux') || u.includes('X11'),
63
- 'macOS': u.includes('Macintosh'),
64
- Android: u.includes('Android') || u.includes('Adr'),
65
- Ubuntu: u.includes('Ubuntu'),
66
- FreeBSD: u.includes('FreeBSD'),
67
- Debian: u.includes('Debian'),
68
- 'Windows Phone': u.includes('IEMobile') || u.includes('Windows Phone'),
69
- BlackBerry: u.includes('BlackBerry') || u.includes('RIM'),
70
- MeeGo: u.includes('MeeGo'),
71
- Symbian: u.includes('Symbian'),
72
- iOS: u.includes('like Mac OS X'),
73
- 'Chrome OS': u.includes('CrOS'),
74
- WebOS: u.includes('hpwOS'),
75
- }
76
-
77
- // 设备
78
- const deviceMatch = {
79
- Mobile: u.includes('Mobi') || u.includes('iPh') || u.includes('480'),
80
- Tablet: u.includes('Tablet') || u.includes('Pad') || u.includes('Nexus 7')
81
- }
82
-
83
- // 修正
84
- if (deviceMatch.Mobile) {
85
- deviceMatch.Mobile = !(u.includes('iPad'))
86
- } else if (browserMatch.Chrome && u.includes('Edg')) {
87
- // Chrome 内核的 Edge
88
- browserMatch.Chrome = false
89
- browserMatch.Edge = true
90
- } else if (win.showModalDialog && win.chrome) {
91
- browserMatch.Chrome = false
92
- browserMatch['360'] = true
93
- }
94
-
95
- // 默认设备
96
- dest.device = 'PC'
97
-
98
- // 语言
99
- dest.language = (() => {
100
- const g = ((nav as any).browserLanguage || nav.language)
101
- const arr = g.split('-')
102
- if (arr[1]) arr[1] = arr[1].toUpperCase()
103
- return arr.join('_')
104
- })()
105
-
106
- // 应用判断数据
107
- const hash = {
108
- engine: engineMatch,
109
- browser: browserMatch,
110
- os: osMatch,
111
- device: deviceMatch,
112
- }
113
- Object.entries(hash).forEach(([type, match]) => {
114
- Object.entries(match).forEach(([name, result]) => {
115
- if (result === true) dest[type] = name
116
- })
117
- })
118
-
119
- // 系统版本信息
120
- const osVersion = {
121
- Windows: () => {
122
- const v = u.replace(/^.*Windows NT ([\d.]+);.*$/, '$1')
123
- const wvHash = {
124
- '6.4': '10',
125
- '6.3': '8.1',
126
- '6.2': '8',
127
- '6.1': '7',
128
- '6.0': 'Vista',
129
- '5.2': 'XP',
130
- '5.1': 'XP',
131
- '5.0': '2000',
132
- '10.0': '10',
133
- '11.0': '11' // 自定的,不是微软官方的判断方法
134
- }
135
- return wvHash[v] || v
136
- },
137
- Android: () => u.replace(/^.*Android ([\d.]+);.*$/, '$1'),
138
- iOS: () => u.replace(/^.*OS ([\d_]+) like.*$/, '$1').replace(/_/g, '.'),
139
- Debian: () => u.replace(/^.*Debian\/([\d.]+).*$/, '$1'),
140
- 'Windows Phone': () => u.replace(/^.*Windows Phone( OS)? ([\d.]+);.*$/, '$2'),
141
- 'macOS': () => u.replace(/^.*Mac OS X ([\d_]+).*$/, '$1').replace(/_/g, '.'),
142
- WebOS: () => u.replace(/^.*hpwOS\/([\d.]+);.*$/, '$1')
143
- }
144
-
145
- dest.osVersion = ''
146
- if (osVersion[dest.os]) {
147
- dest.osVersion = osVersion[dest.os]()
148
- if (dest.osVersion === u) {
149
- dest.osVersion = ''
150
- }
151
- }
152
-
153
- // 浏览器版本信息
154
- const version = {
155
- Safari: () => u.replace(/^.*Version\/([\d.]+).*$/, '$1'),
156
- Chrome: () => u.replace(/^.*Chrome\/([\d.]+).*$/, '$1').replace(/^.*CriOS\/([\d.]+).*$/, '$1'),
157
- IE: () => u.replace(/^.*MSIE ([\d.]+).*$/, '$1').replace(/^.*rv:([\d.]+).*$/, '$1'),
158
- Edge: () => u.replace(/^.*(Edge|Edg|Edg[A-Z]{1})\/([\d.]+).*$/, '$2'),
159
- Firefox: () => u.replace(/^.*Firefox\/([\d.]+).*$/, '$1').replace(/^.*FxiOS\/([\d.]+).*$/, '$1'),
160
- 'Firefox Focus': () => u.replace(/^.*Focus\/([\d.]+).*$/, '$1'),
161
- Chromium: () => u.replace(/^.*Chromium\/([\d.]+).*$/, '$1'),
162
- Opera: () => u.replace(/^.*Opera\/([\d.]+).*$/, '$1').replace(/^.*OPR\/([\d.]+).*$/, '$1'),
163
- Vivaldi: () => u.replace(/^.*Vivaldi\/([\d.]+).*$/, '$1'),
164
- Yandex: () => u.replace(/^.*YaBrowser\/([\d.]+).*$/, '$1'),
165
- Kindle: () => u.replace(/^.*Version\/([\d.]+).*$/, '$1'),
166
- Maxthon: () => u.replace(/^.*Maxthon\/([\d.]+).*$/, '$1'),
167
- QQBrowser: () => u.replace(/^.*QQBrowser\/([\d.]+).*$/, '$1'),
168
- QQ: () => u.replace(/^.*QQ\/([\d.]+).*$/, '$1'),
169
- Baidu: () => u.replace(/^.*BIDUBrowser[\s/]([\d.]+).*$/, '$1'),
170
- UC: () => u.replace(/^.*UC?Browser\/([\d.]+).*$/, '$1'),
171
- Sogou: () => u.replace(/^.*SE ([\d.X]+).*$/, '$1').replace(/^.*SogouMobileBrowser\/([\d.]+).*$/, '$1'),
172
- '2345Explorer': () => u.replace(/^.*2345Explorer\/([\d.]+).*$/, '$1'),
173
- TheWorld: () => u.replace(/^.*TheWorld ([\d.]+).*$/, '$1'),
174
- MIUI: () => u.replace(/^.*MiuiBrowser\/([\d.]+).*$/, '$1'),
175
- Quark: () => u.replace(/^.*Quark\/([\d.]+).*$/, '$1'),
176
- Qiyu: () => u.replace(/^.*Qiyu\/([\d.]+).*$/, '$1'),
177
- Wechat: () => u.replace(/^.*MicroMessenger\/([\d.]+).*$/, '$1'),
178
- Taobao: () => u.replace(/^.*AliApp\(TB\/([\d.]+).*$/, '$1'),
179
- Alipay: () => u.replace(/^.*AliApp\(AP\/([\d.]+).*$/, '$1'),
180
- Weibo: () => u.replace(/^.*weibo__([\d.]+).*$/, '$1'),
181
- Douban: () => u.replace(/^.*com.douban.frodo\/([\d.]+).*$/, '$1'),
182
- Suning: () => u.replace(/^.*SNEBUY-APP([\d.]+).*$/, '$1'),
183
- iQiYi: () => u.replace(/^.*IqiyiVersion\/([\d.]+).*$/, '$1'),
184
- }
185
-
186
- dest.version = ''
187
- if (version[dest.browser]) {
188
- dest.version = version[dest.browser]()
189
- if (dest.version === u) {
190
- dest.version = ''
191
- }
192
- }
193
-
194
- // 简化版本号
195
- /* if (_this.osVersion.indexOf('.')) {
196
- _this.osVersion = _this.osVersion.substring(0, _this.osVersion.indexOf('.'))
197
- } */
198
- if (dest.version.indexOf('.')) {
199
- dest.version = dest.version.substring(0, dest.version.indexOf('.'))
200
- }
201
-
202
- // 修正
203
- if (dest.os === 'iOS' && u.includes('iPad')) {
204
- dest.os = 'iPadOS'
205
- } else if (dest.browser === 'Edge' && !u.includes('Edg')) {
206
- dest.engine = 'EdgeHTML'
207
- } else if (dest.browser === 'MIUI') {
208
- dest.os = 'Android'
209
- } else if (dest.browser === 'Chrome' && Number(dest.version) > 27) {
210
- dest.engine = 'Blink'
211
- } else if (dest.browser === 'Opera' && Number(dest.version) > 12) {
212
- dest.engine = 'Blink'
213
- } else if (dest.browser === 'Yandex') {
214
- dest.engine = 'Blink'
215
- } else if (dest.browser === undefined) {
216
- dest.browser = 'Unknow App'
217
- }
218
-
219
- return dest
220
- }
221
-
222
- export default Detect
@@ -1,47 +0,0 @@
1
- export type EventHandler<T> = (payload: T) => void
2
- export interface Event<PayloadMap, K extends keyof PayloadMap = keyof PayloadMap> extends EventOptions {
3
- name: K
4
- handler: EventHandler<PayloadMap[K]>
5
- }
6
- export interface EventOptions {
7
- once?: boolean
8
- }
9
-
10
- export interface EventManagerFuncs<PayloadMap> {
11
- on<K extends keyof PayloadMap>(name: K, handler: EventHandler<PayloadMap[K]>, opts?: EventOptions): void
12
- off<K extends keyof PayloadMap>(name: K, handler: EventHandler<PayloadMap[K]>): void
13
- trigger<K extends keyof PayloadMap>(name: K, payload?: PayloadMap[K]): void
14
- }
15
-
16
- export default class EventManager<PayloadMap> implements EventManagerFuncs<PayloadMap> {
17
- private events: Event<PayloadMap>[] = []
18
-
19
- /**
20
- * Add an event listener for a specific event name
21
- */
22
- public on<K extends keyof PayloadMap>(name: K, handler: EventHandler<PayloadMap[K]>, opts: EventOptions = {}) {
23
- this.events.push({ name, handler: handler as EventHandler<PayloadMap[keyof PayloadMap]>, ...opts })
24
- }
25
-
26
- /**
27
- * Remove an event listener for a specific event name and handler
28
- */
29
- public off<K extends keyof PayloadMap>(name: K, handler: EventHandler<PayloadMap[K]>) {
30
- if (!handler) return // not allow remove all events with same name
31
- this.events = this.events.filter((evt) =>
32
- !(evt.name === name && evt.handler === handler))
33
- }
34
-
35
- /**
36
- * Trigger an event with an optional payload
37
- */
38
- public trigger<K extends keyof PayloadMap>(name: K, payload?: PayloadMap[K]) {
39
- this.events
40
- .slice(0) // make a copy, in case listeners are removed while iterating
41
- .filter((evt) => evt.name === name && typeof evt.handler === 'function')
42
- .forEach((evt) => {
43
- if (evt.once) this.off(name, evt.handler)
44
- evt.handler(payload!)
45
- })
46
- }
47
- }
@@ -1,5 +0,0 @@
1
- import hanabi from 'hanabi'
2
-
3
- export function renderCode(code: string) {
4
- return hanabi(code)
5
- }
@@ -1,32 +0,0 @@
1
- import { marked as libMarked } from 'marked'
2
- import { renderCode } from './highlight'
3
-
4
- export function getRenderer() {
5
- const renderer = new libMarked.Renderer()
6
- renderer.link = markedLinkRenderer(renderer, renderer.link)
7
- renderer.code = markedCodeRenderer()
8
- return renderer
9
- }
10
-
11
- export const markedLinkRenderer = (renderer: any, orgLinkRenderer: Function) => (href: string, title: string, text: string): string => {
12
- const localLink = href?.startsWith(`${window.location.protocol}//${window.location.hostname}`);
13
- const html = orgLinkRenderer.call(renderer, href, title, text);
14
- return html.replace(/^<a /, `<a target="_blank" ${!localLink ? `rel="noreferrer noopener nofollow"` : ''} `);
15
- }
16
-
17
- export const markedCodeRenderer = () => (block: string, lang: string | undefined): string => {
18
- // Colorize the block only if the language is known to highlight.js
19
- const realLang = (!lang ? 'plaintext' : lang)
20
- let colorized = block
21
- if ((window as any).hljs) {
22
- if (realLang && (window as any).hljs.getLanguage(realLang)) {
23
- colorized = (window as any).hljs.highlight(realLang, block).value
24
- }
25
- } else {
26
- colorized = renderCode(block)
27
- }
28
-
29
- return `<pre rel="${realLang}">\n`
30
- + `<code class="hljs language-${realLang}">${colorized.replace(/&amp;/g, '&')}</code>\n`
31
- + `</pre>`
32
- }