artalk 2.7.1 → 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 (173) hide show
  1. package/README.md +1 -1
  2. package/dist/Artalk.css +1 -1
  3. package/dist/Artalk.es.js +155 -147
  4. package/dist/Artalk.es.js.map +1 -1
  5. package/dist/Artalk.iife.js +1 -1
  6. package/dist/Artalk.iife.js.map +1 -1
  7. package/dist/Artalk.js +1 -1
  8. package/dist/Artalk.js.map +1 -1
  9. package/dist/ArtalkLite.css +1 -1
  10. package/dist/ArtalkLite.es.js +155 -147
  11. package/dist/ArtalkLite.es.js.map +1 -1
  12. package/dist/ArtalkLite.iife.js +1 -1
  13. package/dist/ArtalkLite.iife.js.map +1 -1
  14. package/dist/ArtalkLite.js +1 -1
  15. package/dist/ArtalkLite.js.map +1 -1
  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/components/checker/index.d.ts +2 -0
  21. package/dist/src/i18n/en.d.ts +1 -0
  22. package/dist/src/i18n/external.d.ts +1 -0
  23. package/dist/src/i18n/index.d.ts +3 -0
  24. package/dist/src/i18n/jp.d.ts +1 -0
  25. package/dist/src/i18n/zh-TW.d.ts +1 -0
  26. package/dist/src/lib/user.d.ts +8 -6
  27. package/dist/src/plugins/editor/_kit.d.ts +7 -1
  28. package/dist/src/service.d.ts +2 -8
  29. package/dist/types/event.d.ts +1 -1
  30. package/package.json +43 -17
  31. package/dist/src/components/dark-mode.d.ts +0 -2
  32. package/src/api/_base.ts +0 -18
  33. package/src/api/_options.ts +0 -25
  34. package/src/api/_request.ts +0 -104
  35. package/src/api/admin.ts +0 -18
  36. package/src/api/captcha.ts +0 -24
  37. package/src/api/comment.ts +0 -84
  38. package/src/api/index.ts +0 -29
  39. package/src/api/page.ts +0 -83
  40. package/src/api/site.ts +0 -51
  41. package/src/api/system.ts +0 -49
  42. package/src/api/upload.ts +0 -28
  43. package/src/api/user.ts +0 -132
  44. package/src/artalk.ts +0 -115
  45. package/src/comment/actions.ts +0 -83
  46. package/src/comment/comment.html +0 -18
  47. package/src/comment/comment.ts +0 -192
  48. package/src/comment/height-limit.ts +0 -100
  49. package/src/comment/index.ts +0 -3
  50. package/src/comment/render.ts +0 -150
  51. package/src/comment/renders/actions.ts +0 -114
  52. package/src/comment/renders/avatar.ts +0 -22
  53. package/src/comment/renders/content.ts +0 -39
  54. package/src/comment/renders/header.ts +0 -84
  55. package/src/comment/renders/index.ts +0 -19
  56. package/src/comment/renders/pending.ts +0 -12
  57. package/src/comment/renders/reply-at.ts +0 -16
  58. package/src/comment/renders/reply-to.ts +0 -24
  59. package/src/components/action-btn.ts +0 -170
  60. package/src/components/checker/admin.ts +0 -37
  61. package/src/components/checker/captcha-renders.ts +0 -69
  62. package/src/components/checker/captcha.ts +0 -26
  63. package/src/components/checker/index.ts +0 -192
  64. package/src/components/dark-mode.ts +0 -30
  65. package/src/components/dialog.ts +0 -62
  66. package/src/components/error-dialog.ts +0 -35
  67. package/src/components/pagination.ts +0 -153
  68. package/src/components/read-more-btn.ts +0 -92
  69. package/src/config.ts +0 -119
  70. package/src/context.ts +0 -146
  71. package/src/data.ts +0 -110
  72. package/src/defaults.ts +0 -61
  73. package/src/editor/editor.html +0 -18
  74. package/src/editor/editor.ts +0 -114
  75. package/src/editor/state.ts +0 -52
  76. package/src/editor/ui.ts +0 -36
  77. package/src/i18n/en.ts +0 -84
  78. package/src/i18n/external.ts +0 -10
  79. package/src/i18n/index.ts +0 -67
  80. package/src/i18n/jp.ts +0 -86
  81. package/src/i18n/zh-CN.ts +0 -88
  82. package/src/i18n/zh-TW.ts +0 -86
  83. package/src/layer/index.ts +0 -4
  84. package/src/layer/layer-manager.ts +0 -32
  85. package/src/layer/layer.ts +0 -39
  86. package/src/layer/scrollbar-helper.ts +0 -24
  87. package/src/layer/sidebar-layer.html +0 -8
  88. package/src/layer/sidebar-layer.ts +0 -155
  89. package/src/layer/wrap.ts +0 -77
  90. package/src/lib/component.ts +0 -12
  91. package/src/lib/detect.ts +0 -222
  92. package/src/lib/event-manager.ts +0 -47
  93. package/src/lib/highlight.ts +0 -5
  94. package/src/lib/marked-renderer.ts +0 -32
  95. package/src/lib/marked.ts +0 -72
  96. package/src/lib/sanitizer.ts +0 -57
  97. package/src/lib/ui.ts +0 -193
  98. package/src/lib/user.ts +0 -55
  99. package/src/lib/utils.ts +0 -236
  100. package/src/list/comment.ts +0 -20
  101. package/src/list/layout.ts +0 -120
  102. package/src/list/list.html +0 -20
  103. package/src/list/list.ts +0 -79
  104. package/src/list/nest.ts +0 -66
  105. package/src/list/page.ts +0 -97
  106. package/src/list/paginator/index.ts +0 -25
  107. package/src/list/paginator/read-more.ts +0 -67
  108. package/src/list/paginator/up-down.ts +0 -51
  109. package/src/main.ts +0 -14
  110. package/src/plugins/admin-only-elem.ts +0 -40
  111. package/src/plugins/conf-remoter.ts +0 -54
  112. package/src/plugins/dark-mode.ts +0 -12
  113. package/src/plugins/editor/_kit.ts +0 -57
  114. package/src/plugins/editor/_plug.ts +0 -60
  115. package/src/plugins/editor/_sample.ts +0 -8
  116. package/src/plugins/editor/closable.ts +0 -44
  117. package/src/plugins/editor/emoticons.scss +0 -72
  118. package/src/plugins/editor/emoticons.ts +0 -293
  119. package/src/plugins/editor/header-event.ts +0 -35
  120. package/src/plugins/editor/header-link.ts +0 -31
  121. package/src/plugins/editor/header-user.ts +0 -98
  122. package/src/plugins/editor/index.ts +0 -40
  123. package/src/plugins/editor/local-storage.ts +0 -36
  124. package/src/plugins/editor/mover.ts +0 -29
  125. package/src/plugins/editor/preview.scss +0 -7
  126. package/src/plugins/editor/preview.ts +0 -41
  127. package/src/plugins/editor/state-edit.ts +0 -116
  128. package/src/plugins/editor/state-reply.ts +0 -91
  129. package/src/plugins/editor/submit-add.ts +0 -33
  130. package/src/plugins/editor/submit-btn.ts +0 -25
  131. package/src/plugins/editor/submit.ts +0 -73
  132. package/src/plugins/editor/textarea.ts +0 -55
  133. package/src/plugins/editor/upload.ts +0 -145
  134. package/src/plugins/editor-kit.ts +0 -161
  135. package/src/plugins/index.ts +0 -16
  136. package/src/plugins/list/copyright.ts +0 -16
  137. package/src/plugins/list/count.ts +0 -31
  138. package/src/plugins/list/dropdown.ts +0 -95
  139. package/src/plugins/list/error-dialog.ts +0 -22
  140. package/src/plugins/list/fetch.ts +0 -64
  141. package/src/plugins/list/goto-first.ts +0 -23
  142. package/src/plugins/list/goto.ts +0 -72
  143. package/src/plugins/list/index.ts +0 -25
  144. package/src/plugins/list/loading.ts +0 -17
  145. package/src/plugins/list/no-comment.ts +0 -25
  146. package/src/plugins/list/reach-bottom.ts +0 -46
  147. package/src/plugins/list/sidebar-btn.ts +0 -39
  148. package/src/plugins/list/time-ticking.ts +0 -22
  149. package/src/plugins/list/unread-badge.ts +0 -26
  150. package/src/plugins/list/unread.ts +0 -38
  151. package/src/plugins/list/with-editor.ts +0 -59
  152. package/src/plugins/markdown.ts +0 -10
  153. package/src/plugins/stat.ts +0 -82
  154. package/src/plugins/version-check.ts +0 -36
  155. package/src/service.ts +0 -91
  156. package/src/style/_color.scss +0 -41
  157. package/src/style/_extend.scss +0 -20
  158. package/src/style/_variables.scss +0 -3
  159. package/src/style/comment.scss +0 -360
  160. package/src/style/editor.scss +0 -194
  161. package/src/style/list.scss +0 -212
  162. package/src/style/main.scss +0 -486
  163. package/src/style/pagination.scss +0 -58
  164. package/src/style/sidebar-layer.scss +0 -92
  165. package/types/config.ts +0 -153
  166. package/types/context.ts +0 -84
  167. package/types/data.ts +0 -271
  168. package/types/editor.ts +0 -95
  169. package/types/event.ts +0 -40
  170. package/types/global.d.ts +0 -1
  171. package/types/index.ts +0 -7
  172. package/types/plugin.ts +0 -3
  173. package/types/sidebar.ts +0 -3
@@ -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
- }
package/src/lib/marked.ts DELETED
@@ -1,72 +0,0 @@
1
- import { marked as libMarked, MarkedOptions } from 'marked'
2
-
3
- import { sanitize } from './sanitizer'
4
- import { renderCode } from './highlight'
5
- import { getRenderer } from './marked-renderer'
6
-
7
- type Replacer = (raw: string) => string
8
- export type TMarked = typeof libMarked
9
-
10
- let instance: (typeof libMarked)|undefined
11
- let replacers: Replacer[] = []
12
-
13
- const markedOptions: MarkedOptions = {
14
- pedantic: false,
15
- gfm: true,
16
- breaks: true,
17
- smartLists: true,
18
- smartypants: true,
19
- xhtml: false,
20
- sanitize: false,
21
- silent: true,
22
- }
23
-
24
- /** Get Marked instance */
25
- export function getInstance() {
26
- return instance
27
- }
28
-
29
- export function setReplacers(arr: Replacer[]) {
30
- replacers = arr
31
- }
32
-
33
- /** 初始化 marked */
34
- export function initMarked() {
35
- try { if (!libMarked.name) return } catch { return }
36
-
37
- // @see https://github.com/markedjs/marked/blob/4afb228d956a415624c4e5554bb8f25d047676fe/src/Tokenizer.js#L329
38
- libMarked.setOptions({
39
- renderer: getRenderer(),
40
- ...markedOptions
41
- })
42
-
43
- instance = libMarked
44
- }
45
-
46
- /** 解析 markdown */
47
- export default function marked(src: string): string {
48
- let markedContent = getInstance()?.parse(src)
49
- if (!markedContent) { // 无 Markdown 模式简单处理
50
- markedContent = simpleMarked(src)
51
- }
52
-
53
- let dest = sanitize(markedContent)
54
-
55
- // 内容替换器
56
- replacers.forEach((replacer) => {
57
- if (typeof replacer === 'function')
58
- dest = replacer(dest)
59
- })
60
-
61
- return dest
62
- }
63
-
64
- function simpleMarked(src: string) {
65
- return src
66
- // .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
67
- .replace(/```\s*([^]+?.*?[^]+?[^]+?)```/g, (_, code) => `<pre><code>${renderCode(code)}</code></pre>`)
68
- // .replace(/`([^`]+?)`/g, '<code>$1</code>')
69
- .replace(/!\[(.*?)\]\((.*?)\)/g, (_, alt, imgSrc) => `<img src="${imgSrc}" alt="${alt}" />`)
70
- .replace(/\[(.*?)\]\((.*?)\)/g, (_, text, link) => `<a href="${link}" target="_blank">${text}</a>`)
71
- .replace(/\n/g, '<br>')
72
- }
@@ -1,57 +0,0 @@
1
- import insane from 'insane'
2
-
3
- const insaneOptions = {
4
- allowedClasses: {},
5
- // @refer CVE-2018-8495
6
- // @link https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8495
7
- // @link https://leucosite.com/Microsoft-Edge-RCE/
8
- // @link https://medium.com/@knownsec404team/analysis-of-the-security-issues-of-url-scheme-in-pc-from-cve-2018-8495-934478a36756
9
- allowedSchemes: [
10
- 'http', 'https', 'mailto',
11
- 'data' // for support base64 encoded image (安全性有待考虑)
12
- ],
13
- allowedTags: [
14
- 'a', 'abbr', 'article', 'b', 'blockquote', 'br', 'caption', 'code', 'del', 'details', 'div', 'em',
15
- 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'ins', 'kbd', 'li', 'main', 'mark',
16
- 'ol', 'p', 'pre', 'section', 'span', 'strike', 'strong', 'sub', 'summary', 'sup', 'table',
17
- 'tbody', 'td', 'th', 'thead', 'tr', 'u', 'ul'
18
- ],
19
- allowedAttributes: {
20
- '*': ['title', 'accesskey'],
21
- a: ['href', 'name', 'target', 'aria-label', 'rel'],
22
- img: ['src', 'alt', 'title', 'atk-emoticon', 'aria-label'],
23
- // for code highlight
24
- code: ['class'],
25
- span: ['class', 'style'],
26
- },
27
- filter: node => {
28
- // allow hljs style
29
- const allowed = [
30
- [ 'code', /^hljs\W+language-(.*)$/ ],
31
- [ 'span', /^(hljs-.*)$/ ]
32
- ]
33
- allowed.forEach(([ tag, reg ]) => {
34
- if (
35
- node.tag === tag
36
- && !!node.attrs.class
37
- && !(reg as RegExp).test(node.attrs.class)
38
- ) {
39
- delete node.attrs.class
40
- }
41
- })
42
-
43
- // allow <span> set color sty
44
- if (node.tag === 'span' && !!node.attrs.style
45
- && !/^color:(\W+)?#[0-9a-f]{3,6};?$/i.test(node.attrs.style)) {
46
- delete node.attrs.style
47
- }
48
-
49
- return true
50
- }
51
- }
52
-
53
- export function sanitize(content: string): string {
54
- // @link https://github.com/markedjs/marked/discussions/1232
55
- // @link https://gist.github.com/lionel-rowe/bb384465ba4e4c81a9c8dada84167225
56
- return insane(content, insaneOptions)
57
- }
package/src/lib/ui.ts DELETED
@@ -1,193 +0,0 @@
1
- import type { NotifyLevel } from '~/types'
2
- import * as Utils from './utils'
3
-
4
- /** 显示加载 */
5
- export function showLoading(parentElem: HTMLElement, conf?: { transparentBg?: boolean }) {
6
- // Use :scope https://developer.mozilla.org/en-US/docs/Web/CSS/:scope
7
- let $loading = parentElem.querySelector<HTMLElement>(':scope > .atk-loading')
8
- if (!$loading) {
9
- $loading = Utils.createElement(
10
- `<div class="atk-loading atk-fade-in" style="display: none;">
11
- <div class="atk-loading-spinner">
12
- <svg viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"></circle></svg>
13
- </div>
14
- </div>`)
15
- if (conf?.transparentBg) $loading.style.background = 'transparent'
16
- parentElem.appendChild($loading)
17
- }
18
- $loading.style.display = ''
19
-
20
- // spinner 延迟显示,若加载等待时间太短,没必要显示(闪一下即可)
21
- const $spinner = $loading.querySelector<HTMLElement>('.atk-loading-spinner')
22
- if ($spinner) {
23
- $spinner.style.display = 'none'
24
- window.setTimeout(() => {
25
- $spinner.style.display = ''
26
- }, 500)
27
- }
28
- }
29
-
30
- /** 隐藏加载 */
31
- export function hideLoading(parentElem: HTMLElement) {
32
- const $loading = parentElem.querySelector<HTMLElement>(':scope > .atk-loading')
33
- if ($loading) $loading.style.display = 'none'
34
- }
35
-
36
- /** 元素加载动画 */
37
- export function setLoading(val: boolean, parentElem: HTMLElement) {
38
- if (val) showLoading(parentElem)
39
- else hideLoading(parentElem)
40
- }
41
-
42
- /** 元素是否用户可见 */
43
- export function isVisible(el: HTMLElement, viewport: HTMLElement = document.documentElement) {
44
- const viewportHeight = viewport.clientHeight
45
-
46
- const docViewTop = viewport.scrollTop
47
- const docViewBottom = docViewTop + viewportHeight
48
-
49
- const rect = el.getBoundingClientRect()
50
- const elemTop = rect.top + docViewTop
51
- const elemBottom = elemTop + rect.height
52
-
53
- return (elemBottom <= docViewBottom) //&& (elemTop >= docViewTop) 注释因为假如 el 比 viewport 还高就会失效
54
- }
55
-
56
- /** 滚动到元素中心 */
57
- export function scrollIntoView(elem: HTMLElement, enableAnim: boolean = true, relativeTo?: HTMLElement) {
58
- let top: number
59
-
60
- if (relativeTo) {
61
- const containerRect = relativeTo.getBoundingClientRect()
62
- const elementRect = elem.getBoundingClientRect()
63
- top = elementRect.top - containerRect.top + relativeTo.scrollTop
64
- top += Utils.getHeight(relativeTo) / 2 - Utils.getHeight(elem) / 2
65
- } else {
66
- const rect = elem.getBoundingClientRect()
67
- const elemTop = rect.top + window.scrollY
68
- top = elemTop - (window.innerHeight / 2 - rect.height / 2)
69
- }
70
-
71
- const scrollOptions: ScrollToOptions = {
72
- top, left: 0,
73
- // behavior: enableAnim ? 'smooth' : 'instant',
74
- behavior: 'instant'
75
- }
76
-
77
- if (relativeTo) relativeTo.scroll(scrollOptions)
78
- else window.scroll(scrollOptions)
79
- }
80
-
81
- /** 显示消息 */
82
- export function showNotify(
83
- wrapElem: HTMLElement,
84
- msg: string,
85
- type: NotifyLevel,
86
- ) {
87
- const colors = { s: '#57d59f', e: '#ff6f6c', w: '#ffc721', i: '#2ebcfc' }
88
- const timeout = 3000 // 持续显示时间 ms
89
-
90
- const notifyElem = Utils.createElement(
91
- `<div class="atk-notify atk-fade-in" style="background-color: ${colors[type]}"><span class="atk-notify-content"></span></div>`
92
- )
93
- const notifyContentEl = notifyElem.querySelector<HTMLElement>('.atk-notify-content')!
94
- notifyContentEl.innerHTML = Utils.htmlEncode(msg).replace('\n', '<br/>')
95
-
96
- wrapElem.appendChild(notifyElem)
97
-
98
- const notifyRemove = () => {
99
- notifyElem.classList.add('atk-fade-out')
100
- setTimeout(() => {
101
- notifyElem.remove()
102
- }, 200)
103
- }
104
-
105
- let timeoutFn: number
106
- if (timeout > 0) {
107
- timeoutFn = window.setTimeout(() => {
108
- notifyRemove()
109
- }, timeout)
110
- }
111
-
112
- notifyElem.addEventListener('click', () => {
113
- notifyRemove()
114
- window.clearTimeout(timeoutFn)
115
- })
116
- }
117
-
118
- /** fade 动画 */
119
- export function playFadeAnim(
120
- elem: HTMLElement,
121
- after?: () => void,
122
- type: 'in' | 'out' = 'in'
123
- ) {
124
- elem.classList.add(`atk-fade-${type}`)
125
- // 动画结束清除 class
126
- const onAnimEnded = () => {
127
- elem.classList.remove(`atk-fade-${type}`)
128
- elem.removeEventListener('animationend', onAnimEnded)
129
- if (after) after()
130
- }
131
- elem.addEventListener('animationend', onAnimEnded)
132
- }
133
-
134
- /** 渐入动画 */
135
- export function playFadeInAnim(elem: HTMLElement, after?: () => void) {
136
- playFadeAnim(elem, after, 'in')
137
- }
138
-
139
- /** 渐出动画 */
140
- export function playFadeOutAnim(elem: HTMLElement, after?: () => void) {
141
- playFadeAnim(elem, after, 'out')
142
- }
143
-
144
- /** 设置全局错误 */
145
- export function setError(parentElem: HTMLElement, html: string | HTMLElement | null, title: string = '<span class="atk-error-title">Artalk Error</span>') {
146
- let elem = parentElem.querySelector<HTMLElement>('.atk-error-layer')
147
- if (html === null) {
148
- if (elem !== null) elem.remove()
149
- return
150
- }
151
- if (!elem) {
152
- elem = Utils.createElement(
153
- `<div class="atk-error-layer">${title}<span class="atk-error-text"></span></div>`
154
- )
155
- parentElem.appendChild(elem)
156
- }
157
-
158
- const errorTextEl = elem.querySelector<HTMLElement>('.atk-error-text')!
159
- errorTextEl.innerHTML = ''
160
- if (html === null) return
161
-
162
- if (html instanceof HTMLElement) {
163
- errorTextEl.appendChild(html)
164
- } else {
165
- errorTextEl.innerText = html
166
- }
167
- }
168
-
169
- export function getScrollBarWidth() {
170
- const inner = document.createElement('p')
171
- inner.style.width = '100%'
172
- inner.style.height = '200px'
173
-
174
- const outer = document.createElement('div')
175
- outer.style.position = 'absolute'
176
- outer.style.top = '0px'
177
- outer.style.left = '0px'
178
- outer.style.visibility = 'hidden'
179
- outer.style.width = '200px'
180
- outer.style.height = '150px'
181
- outer.style.overflow = 'hidden'
182
- outer.appendChild(inner)
183
-
184
- document.body.appendChild(outer)
185
- const w1 = inner.offsetWidth
186
- outer.style.overflow = 'scroll'
187
- let w2 = inner.offsetWidth
188
- if (w1 === w2) w2 = outer.clientWidth
189
-
190
- document.body.removeChild(outer)
191
-
192
- return (w1 - w2)
193
- }
package/src/lib/user.ts DELETED
@@ -1,55 +0,0 @@
1
- import type { LocalUser } from '~/types'
2
-
3
- const LOCAL_USER_KEY = 'ArtalkUser'
4
-
5
- class User {
6
- data: LocalUser
7
- onUserChanged: ((user: LocalUser) => void) | null = null
8
-
9
- constructor() {
10
- // 从 localStorage 导入
11
- const localUser = JSON.parse(window.localStorage.getItem(LOCAL_USER_KEY) || '{}')
12
- this.data = {
13
- nick: localUser.nick || '',
14
- email: localUser.email || '',
15
- link: localUser.link || '',
16
- token: localUser.token || '',
17
- isAdmin: localUser.isAdmin || false
18
- }
19
- }
20
-
21
- /** 保存用户到 localStorage 中 */
22
- update(obj: Partial<LocalUser> = {}) {
23
- Object.entries(obj).forEach(([key, value]) => {
24
- this.data[key] = value
25
- })
26
-
27
- window.localStorage.setItem(LOCAL_USER_KEY, JSON.stringify(this.data))
28
- this.onUserChanged && this.onUserChanged(this.data)
29
- }
30
-
31
- public setOnUserChanged(fn: ((user: LocalUser) => void) | null) {
32
- this.onUserChanged = fn
33
- }
34
-
35
- /**
36
- * Logout
37
- *
38
- * @description Logout will clear login status, but not clear user data (nick, email, link)
39
- */
40
- logout() {
41
- this.update({
42
- token: '',
43
- isAdmin: false
44
- })
45
- }
46
-
47
- /** 是否已填写基本用户信息 */
48
- checkHasBasicUserInfo() {
49
- return !!this.data.nick && !!this.data.email
50
- }
51
- }
52
-
53
- const UserInstance = new User()
54
-
55
- export default UserInstance