hexo-theme-solitude 1.8.3 → 1.8.4
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/.github/ISSUE_TEMPLATE/config.yml +5 -5
- package/_config.yml +1 -0
- package/layout/includes/footer.pug +3 -2
- package/layout/includes/inject/body.pug +3 -1
- package/layout/includes/inject/head.pug +2 -3
- package/layout/includes/page/says.pug +1 -1
- package/layout/includes/widgets/third-party/comments/artalk.pug +3 -3
- package/layout/includes/widgets/third-party/comments/twikoo.pug +7 -8
- package/layout/includes/widgets/third-party/comments/valine.pug +3 -3
- package/layout/includes/widgets/third-party/comments/waline.pug +2 -2
- package/layout/includes/widgets/third-party/pjax.pug +11 -0
- package/layout/index.pug +1 -1
- package/package.json +1 -1
- package/scripts/event/merge_config.js +1 -0
- package/scripts/event/welcome.js +12 -12
- package/scripts/helper/inject_head_js.js +86 -0
- package/source/css/_layout/footer.styl +15 -14
- package/source/js/main.js +2 -0
- package/source/js/utils.js +213 -330
@@ -8,10 +8,10 @@ contact_links:
|
|
8
8
|
url: https://solitude-docs.efu.me/faq
|
9
9
|
about: Solitude Q&A
|
10
10
|
|
11
|
+
- name: Discord
|
12
|
+
url: https://discord.gg/Y8VEvVgW
|
13
|
+
about: 'Official Discord Group'
|
14
|
+
|
11
15
|
- name: Telegram
|
12
|
-
url: https://t.me/
|
16
|
+
url: https://t.me/solitudePro
|
13
17
|
about: 'Official Telegram Group'
|
14
|
-
|
15
|
-
- name: QQ 群
|
16
|
-
url: https://qm.qq.com/q/VlqOewI4Cu
|
17
|
-
about: '群号 773016811'
|
package/_config.yml
CHANGED
@@ -410,6 +410,7 @@ footer:
|
|
410
410
|
# 底部上方一排图标
|
411
411
|
# Bottom row of icons
|
412
412
|
information:
|
413
|
+
author: false # 是否显示 site_icon / enable site_icon in footer
|
413
414
|
left: # 左侧显示图标
|
414
415
|
# Github: https://github.com/efuo || st-github-line # 名称:链接 || 图标 / Name: link || icon
|
415
416
|
# Mail: mailto:o@efu.me || st-mail-line
|
@@ -17,8 +17,9 @@ div#footer_deal
|
|
17
17
|
a.deal_link(href=url_for(trim(array[0])), title=label)
|
18
18
|
i.solitude(class=array[1])
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
if theme.footer.information.author
|
21
|
+
div#footer_mini_logo.nolazyload.footer_mini_logo(title=_p('nav.backtop'), onclick="sco.toTop()")
|
22
|
+
img(src=theme.site.icon, alt=_p('nav.backtop'))
|
22
23
|
|
23
24
|
each value, label in rightInfo
|
24
25
|
- var array = value.split('||')
|
@@ -11,6 +11,8 @@ mixin katex
|
|
11
11
|
})();
|
12
12
|
|
13
13
|
div
|
14
|
+
script(src=url_for(theme.cdn.utils))
|
15
|
+
script(src=url_for(theme.cdn.main))
|
14
16
|
script(src=url_for(theme.cdn.waterfall))
|
15
17
|
script(src=url_for(theme.cdn.pjax))
|
16
18
|
|
@@ -104,7 +106,7 @@ if theme.footer.randomlink
|
|
104
106
|
include ../widgets/third-party/news-comment/newest-comment.pug
|
105
107
|
|
106
108
|
// pjax
|
107
|
-
|
109
|
+
!= partial("includes/widgets/third-party/pjax", {}, { cache: true })
|
108
110
|
|
109
111
|
// theme
|
110
112
|
include ../body/mode
|
@@ -28,7 +28,7 @@ if theme.pwa.enable
|
|
28
28
|
|
29
29
|
script.
|
30
30
|
console.log(
|
31
|
-
"%c Program: Hexo %c Theme: Solitude %c Version: v1.8.
|
31
|
+
"%c Program: Hexo %c Theme: Solitude %c Version: v1.8.4",
|
32
32
|
"border-radius:5px 0 0 5px;padding: 5px 10px;color:white;background:#ff3842;",
|
33
33
|
"padding: 5px 10px;color:white;background:#3e9f50;",
|
34
34
|
"border-radius:0 5px 5px 0;padding: 5px 10px;background:#0084ff;color:white;"
|
@@ -38,5 +38,4 @@ if theme.extends.head
|
|
38
38
|
each item in theme.extends.head
|
39
39
|
!= item
|
40
40
|
|
41
|
-
|
42
|
-
script(src=url_for(theme.cdn.main))
|
41
|
+
!=fragment_cache('injectHeadJs', function(){return inject_head_js()})
|
@@ -2,7 +2,7 @@
|
|
2
2
|
- const { lazyload, count ,use} = theme.comment
|
3
3
|
|
4
4
|
script.
|
5
|
-
|
5
|
+
(() => {
|
6
6
|
let artalkItem = null
|
7
7
|
const initArtalk = () => {
|
8
8
|
artalkItem = Artalk.init({
|
@@ -31,7 +31,7 @@ script.
|
|
31
31
|
utils.addGlobalFn('pjax', destroyArtalk, 'destroyArtalk')
|
32
32
|
}
|
33
33
|
const loadArtalk = async () => {
|
34
|
-
if (typeof Artalk === 'object')
|
34
|
+
if (typeof Artalk === 'object') initArtalk()
|
35
35
|
else {
|
36
36
|
await utils.getCSS('!{theme.cdn.artalk_css}')
|
37
37
|
await utils.getScript('!{theme.cdn.artalk_js}').then(initArtalk)
|
@@ -50,7 +50,7 @@ script.
|
|
50
50
|
} else {
|
51
51
|
window.loadTwoComment = loadArtalk
|
52
52
|
}
|
53
|
-
}()
|
53
|
+
})()
|
54
54
|
|
55
55
|
if commentBarrage
|
56
56
|
script.
|
@@ -1,8 +1,8 @@
|
|
1
1
|
- const { envId, region, option ,accessToken } = theme.twikoo
|
2
2
|
- const { lazyload, count, use,commentBarrage } = theme.comment
|
3
3
|
|
4
|
-
script.
|
5
|
-
|
4
|
+
script().
|
5
|
+
(() => {
|
6
6
|
const getCount = () => {
|
7
7
|
const ele = document.querySelectorAll('.twikoo-count')
|
8
8
|
if (!ele) return
|
@@ -17,11 +17,12 @@ script.
|
|
17
17
|
console.error(err)
|
18
18
|
})
|
19
19
|
}
|
20
|
-
const init =
|
20
|
+
const init = () => {
|
21
21
|
twikoo.init(Object.assign({
|
22
22
|
el: '#twikoo-wrap',
|
23
23
|
envId: '!{envId}',
|
24
24
|
region: '!{region}',
|
25
|
+
path: window.location.pathname,
|
25
26
|
onCommentLoaded: () => {
|
26
27
|
utils.lightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
|
27
28
|
}
|
@@ -32,12 +33,10 @@ script.
|
|
32
33
|
body: '.OwO-body',
|
33
34
|
item: '.OwO-items li'
|
34
35
|
})
|
35
|
-
|
36
|
-
if (!{commentBarrage}) await barrageTwikoo()
|
37
36
|
}
|
38
37
|
|
39
38
|
const loadTwikoo = () => {
|
40
|
-
if (typeof twikoo === 'object') init
|
39
|
+
if (typeof twikoo === 'object') setTimeout(init,0)
|
41
40
|
else utils.getScript('!{url_for(theme.cdn.twikoo)}').then(init)
|
42
41
|
}
|
43
42
|
|
@@ -45,9 +44,9 @@ script.
|
|
45
44
|
if (!{lazyload}) utils.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
|
46
45
|
else loadTwikoo()
|
47
46
|
} else {
|
48
|
-
window.loadTwoComment =
|
47
|
+
window.loadTwoComment = loadTwikoo
|
49
48
|
}
|
50
|
-
}()
|
49
|
+
})()
|
51
50
|
|
52
51
|
if commentBarrage
|
53
52
|
script.
|
@@ -6,7 +6,7 @@ if site.data.valine
|
|
6
6
|
- emojiMaps = JSON.stringify(site.data.valine)
|
7
7
|
|
8
8
|
script.
|
9
|
-
|
9
|
+
(() => {
|
10
10
|
const initValine = () => {
|
11
11
|
const valine = new Valine({
|
12
12
|
el: '#vcomment',
|
@@ -23,7 +23,7 @@ script.
|
|
23
23
|
sco.owoBig({body: '.vwrap', item: '.vemojis i'})
|
24
24
|
}
|
25
25
|
const loadValine = async () => {
|
26
|
-
if (typeof Valine === 'function')
|
26
|
+
if (typeof Valine === 'function') setTimeout(initValine, 0)
|
27
27
|
else {
|
28
28
|
await utils.getScript('!{url_for(theme.cdn.valine)}').then(initValine)
|
29
29
|
}
|
@@ -35,7 +35,7 @@ script.
|
|
35
35
|
} else {
|
36
36
|
window.loadTwoComment = loadValine
|
37
37
|
}
|
38
|
-
}()
|
38
|
+
})()
|
39
39
|
|
40
40
|
if commentBarrage
|
41
41
|
script.
|
@@ -2,7 +2,7 @@
|
|
2
2
|
- const { lazyload, count, commentBarrage,use } = theme.comment
|
3
3
|
|
4
4
|
script.
|
5
|
-
|
5
|
+
(() => {
|
6
6
|
let walineInitFunction = window.walineFn || null
|
7
7
|
|
8
8
|
function initWaline(initFn) {
|
@@ -40,7 +40,7 @@ script.
|
|
40
40
|
if (!{lazyload}) utils.loadComment(document.getElementById('waline-wrap'), loadWaline)
|
41
41
|
else loadWaline()
|
42
42
|
} else window.loadTwoComment = loadWaline
|
43
|
-
}()
|
43
|
+
})()
|
44
44
|
|
45
45
|
if commentBarrage
|
46
46
|
script.
|
@@ -17,6 +17,17 @@ script.
|
|
17
17
|
|
18
18
|
document.addEventListener('pjax:complete', () => {
|
19
19
|
window.refreshFn()
|
20
|
+
|
21
|
+
document.querySelectorAll('script[data-pjax]').forEach(item => {
|
22
|
+
const newScript = document.createElement('script')
|
23
|
+
const content = item.text || item.textContent || item.innerHTML || ""
|
24
|
+
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
|
25
|
+
newScript.appendChild(document.createTextNode(content))
|
26
|
+
item.parentNode.replaceChild(newScript, item)
|
27
|
+
})
|
28
|
+
|
29
|
+
GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()
|
30
|
+
|
20
31
|
})
|
21
32
|
|
22
33
|
document.addEventListener('pjax:error', (e) => {
|
package/layout/index.pug
CHANGED
package/package.json
CHANGED
package/scripts/event/welcome.js
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
hexo.on('ready', () => {
|
2
|
-
|
3
|
-
|
4
|
-
===================================================================
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
===================================================================
|
12
|
-
GitHub: https://github.com/valor-x/hexo-theme-solitude
|
13
|
-
`)
|
2
|
+
const {version} = require('../../package.json')
|
3
|
+
hexo.log.info(`
|
4
|
+
===================================================================
|
5
|
+
##### #### # ##### ###### # # ###### ######
|
6
|
+
# # # # # # # # # # #
|
7
|
+
##### # # # # # # # # # ######
|
8
|
+
# # # # # # # # # # #
|
9
|
+
###### #### ##### ##### # ### ###### ######
|
10
|
+
${version}
|
11
|
+
===================================================================
|
12
|
+
GitHub: https://github.com/valor-x/hexo-theme-solitude
|
13
|
+
`)
|
14
14
|
})
|
@@ -0,0 +1,86 @@
|
|
1
|
+
/**
|
2
|
+
* Solitude
|
3
|
+
* inject is to head
|
4
|
+
*/
|
5
|
+
|
6
|
+
'use strict';
|
7
|
+
|
8
|
+
hexo.extend.helper.register('inject_head_js', function () {
|
9
|
+
const createJS = () => `
|
10
|
+
const saveToLocal = {
|
11
|
+
set: function setWithExpiry(key, value, ttl) {
|
12
|
+
if (ttl === 0)
|
13
|
+
return
|
14
|
+
const now = new Date()
|
15
|
+
const expiryDay = ttl * 86400000
|
16
|
+
const item = {
|
17
|
+
value: value,
|
18
|
+
expiry: now.getTime() + expiryDay
|
19
|
+
}
|
20
|
+
localStorage.setItem(key, JSON.stringify(item))
|
21
|
+
},
|
22
|
+
get: function getWithExpiry(key) {
|
23
|
+
const itemStr = localStorage.getItem(key)
|
24
|
+
|
25
|
+
if (!itemStr) {
|
26
|
+
return undefined
|
27
|
+
}
|
28
|
+
const item = JSON.parse(itemStr)
|
29
|
+
const now = new Date()
|
30
|
+
|
31
|
+
if (now.getTime() > item.expiry) {
|
32
|
+
localStorage.removeItem(key)
|
33
|
+
return undefined
|
34
|
+
}
|
35
|
+
return item.value
|
36
|
+
}
|
37
|
+
};
|
38
|
+
window.utils = {
|
39
|
+
saveToLocal: saveToLocal,
|
40
|
+
getCSS: (url, id = false) => new Promise((resolve, reject) => {
|
41
|
+
const link = document.createElement('link')
|
42
|
+
link.rel = 'stylesheet'
|
43
|
+
link.href = url
|
44
|
+
if (id) link.id = id
|
45
|
+
link.onerror = reject
|
46
|
+
link.onload = link.onreadystatechange = function() {
|
47
|
+
const loadState = this.readyState
|
48
|
+
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
|
49
|
+
link.onload = link.onreadystatechange = null
|
50
|
+
resolve()
|
51
|
+
}
|
52
|
+
document.head.appendChild(link)
|
53
|
+
}),
|
54
|
+
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
|
55
|
+
const script = document.createElement('script')
|
56
|
+
script.src = url
|
57
|
+
script.async = true
|
58
|
+
script.onerror = reject
|
59
|
+
script.onload = script.onreadystatechange = function() {
|
60
|
+
const loadState = this.readyState
|
61
|
+
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
|
62
|
+
script.onload = script.onreadystatechange = null
|
63
|
+
resolve()
|
64
|
+
}
|
65
|
+
|
66
|
+
Object.keys(attr).forEach(key => {
|
67
|
+
script.setAttribute(key, attr[key])
|
68
|
+
})
|
69
|
+
|
70
|
+
document.head.appendChild(script)
|
71
|
+
}),
|
72
|
+
addGlobalFn: (key, fn, name = false, parent = window) => {
|
73
|
+
const globalFn = parent.globalFn || {}
|
74
|
+
const keyObj = globalFn[key] || {}
|
75
|
+
|
76
|
+
if (name && keyObj[name]) return
|
77
|
+
|
78
|
+
name = name || Object.keys(keyObj).length
|
79
|
+
keyObj[name] = fn
|
80
|
+
globalFn[key] = keyObj
|
81
|
+
parent.globalFn = globalFn
|
82
|
+
},
|
83
|
+
}
|
84
|
+
`
|
85
|
+
return `<script>(()=>{${createJS()}})()</script>`
|
86
|
+
})
|
@@ -80,20 +80,21 @@
|
|
80
80
|
background var(--efu-main)
|
81
81
|
transform scale(1.1)
|
82
82
|
|
83
|
-
.
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
83
|
+
if hexo-config('footer.information.author')
|
84
|
+
.footer_mini_logo
|
85
|
+
width 50px
|
86
|
+
height 50px
|
87
|
+
margin 0 1rem
|
88
|
+
cursor pointer
|
89
|
+
transition cubic-bezier(0, 0, 0, 1.29) .5s
|
90
|
+
user-select none
|
91
|
+
border-radius 50px
|
92
|
+
overflow hidden
|
93
|
+
+maxWidth768()
|
94
|
+
display none
|
95
|
+
|
96
|
+
&:hover
|
97
|
+
transform scale(1.2)
|
97
98
|
|
98
99
|
#st-footer
|
99
100
|
display flex
|
package/source/js/main.js
CHANGED
package/source/js/utils.js
CHANGED
@@ -1,343 +1,226 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
const expiryDay = ttl * 86400000
|
8
|
-
const item = {
|
9
|
-
value: value,
|
10
|
-
expiry: now.getTime() + expiryDay
|
11
|
-
}
|
12
|
-
localStorage.setItem(key, JSON.stringify(item))
|
13
|
-
},
|
14
|
-
|
15
|
-
get: function getWithExpiry(key) {
|
16
|
-
const itemStr = localStorage.getItem(key)
|
17
|
-
|
18
|
-
if (!itemStr) {
|
19
|
-
return undefined
|
20
|
-
}
|
21
|
-
const item = JSON.parse(itemStr)
|
22
|
-
const now = new Date()
|
23
|
-
|
24
|
-
if (now.getTime() > item.expiry) {
|
25
|
-
localStorage.removeItem(key)
|
26
|
-
return undefined
|
27
|
-
}
|
28
|
-
return item.value
|
29
|
-
}
|
30
|
-
},
|
31
|
-
debounce: function (func, wait, immediate) {
|
32
|
-
let timeout
|
33
|
-
return function () {
|
34
|
-
const context = this
|
35
|
-
const args = arguments
|
1
|
+
(() => {
|
2
|
+
const utilsFn = {
|
3
|
+
throttle: (func, wait, options) => {
|
4
|
+
let timeout, context, args
|
5
|
+
let previous = 0
|
6
|
+
if (!options) options = {}
|
36
7
|
const later = function () {
|
37
|
-
|
38
|
-
|
8
|
+
previous = options.leading === false ? 0 : new Date().getTime()
|
9
|
+
func.apply(context, args)
|
10
|
+
context = args = null
|
39
11
|
}
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
}
|
57
|
-
|
58
|
-
return function () {
|
59
|
-
const now = new Date().getTime()
|
60
|
-
if (!previous && options.leading === false) previous = now
|
61
|
-
const remaining = wait - (now - previous)
|
62
|
-
context = this
|
63
|
-
args = arguments
|
64
|
-
if (remaining <= 0 || remaining > wait) {
|
65
|
-
if (timeout) {
|
66
|
-
clearTimeout(timeout)
|
67
|
-
timeout = null
|
12
|
+
return function () {
|
13
|
+
const now = new Date().getTime()
|
14
|
+
if (!previous && options.leading === false) previous = now
|
15
|
+
const remaining = wait - (now - previous)
|
16
|
+
context = this
|
17
|
+
args = arguments
|
18
|
+
if (remaining <= 0 || remaining > wait) {
|
19
|
+
if (timeout) {
|
20
|
+
clearTimeout(timeout)
|
21
|
+
timeout = null
|
22
|
+
}
|
23
|
+
previous = now
|
24
|
+
func.apply(context, args)
|
25
|
+
if (!timeout) context = args = null
|
26
|
+
} else if (!timeout && options.trailing !== false) {
|
27
|
+
timeout = setTimeout(later, remaining)
|
68
28
|
}
|
69
|
-
previous = now
|
70
|
-
func.apply(context, args)
|
71
|
-
if (!timeout) context = args = null
|
72
|
-
} else if (!timeout && options.trailing !== false) {
|
73
|
-
timeout = setTimeout(later, remaining)
|
74
29
|
}
|
75
|
-
}
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
fadeOut: (ele, time) => {
|
83
|
-
ele.addEventListener('animationend', function f() {
|
84
|
-
ele.style.cssText = "display: none; animation: '' "
|
85
|
-
ele.removeEventListener('animationend', f)
|
86
|
-
})
|
87
|
-
ele.style.animation = `to_hide ${time}s`
|
88
|
-
},
|
89
|
-
|
90
|
-
sidebarPaddingR: () => {
|
91
|
-
const innerWidth = window.innerWidth
|
92
|
-
const clientWidth = document.body.clientWidth
|
93
|
-
const paddingRight = innerWidth - clientWidth
|
94
|
-
if (innerWidth !== clientWidth) {
|
95
|
-
document.body.style.paddingRight = paddingRight + 'px'
|
96
|
-
}
|
97
|
-
},
|
98
|
-
|
99
|
-
snackbarShow: (text, showAction, duration) => {
|
100
|
-
const sa = (typeof showAction !== 'undefined') ? showAction : false
|
101
|
-
const dur = (typeof duration !== 'undefined') ? duration : 5000
|
102
|
-
document.styleSheets[0].addRule(':root', '--efu-snackbar-time:' + dur + 'ms!important')
|
103
|
-
Snackbar.show({
|
104
|
-
text: text,
|
105
|
-
showAction: sa,
|
106
|
-
duration: dur,
|
107
|
-
pos: 'top-center'
|
108
|
-
})
|
109
|
-
},
|
110
|
-
|
111
|
-
copy: async (text) => {
|
112
|
-
try {
|
113
|
-
await navigator.clipboard.writeText(text)
|
114
|
-
utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 2000)
|
115
|
-
} catch (err) {
|
116
|
-
utils.snackbarShow(GLOBAL_CONFIG.lang.copy.error, false, 2000)
|
117
|
-
}
|
118
|
-
},
|
119
|
-
|
120
|
-
getEleTop: ele => {
|
121
|
-
let actualTop = 0
|
122
|
-
while (ele) {
|
123
|
-
actualTop += ele.offsetTop
|
124
|
-
ele = ele.offsetParent
|
125
|
-
}
|
126
|
-
return actualTop
|
127
|
-
},
|
128
|
-
|
129
|
-
randomNum: (length) => {
|
130
|
-
return Math.floor(Math.random() * length)
|
131
|
-
},
|
132
|
-
|
133
|
-
timeDiff: (timeObj, today) => {
|
134
|
-
const timeDiff = today.getTime() - timeObj.getTime();
|
135
|
-
return Math.floor(timeDiff / (1000 * 3600 * 24));
|
136
|
-
},
|
137
|
-
|
138
|
-
scrollToDest: (pos, time = 500) => {
|
139
|
-
const currentPos = window.pageYOffset
|
140
|
-
const isNavFixed = document.getElementById('page-header').classList.contains('nav-fixed')
|
141
|
-
if (currentPos > pos || isNavFixed) pos = pos - 70
|
142
|
-
if ('scrollBehavior' in document.documentElement.style) {
|
143
|
-
window.scrollTo({
|
144
|
-
top: pos,
|
145
|
-
behavior: 'smooth'
|
30
|
+
},
|
31
|
+
fadeIn: (ele, time) => ele.style.cssText = `display:block;animation: to_show ${time}s`,
|
32
|
+
fadeOut: (ele, time) => {
|
33
|
+
ele.addEventListener('animationend', function f() {
|
34
|
+
ele.style.cssText = "display: none; animation: '' "
|
35
|
+
ele.removeEventListener('animationend', f)
|
146
36
|
})
|
147
|
-
|
148
|
-
}
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
window.scrollTo(0, currentPos + distance * progress / time)
|
156
|
-
window.requestAnimationFrame(step)
|
157
|
-
} else {
|
158
|
-
window.scrollTo(0, pos)
|
37
|
+
ele.style.animation = `to_hide ${time}s`
|
38
|
+
},
|
39
|
+
sidebarPaddingR: () => {
|
40
|
+
const innerWidth = window.innerWidth
|
41
|
+
const clientWidth = document.body.clientWidth
|
42
|
+
const paddingRight = innerWidth - clientWidth
|
43
|
+
if (innerWidth !== clientWidth) {
|
44
|
+
document.body.style.paddingRight = paddingRight + 'px'
|
159
45
|
}
|
160
|
-
}
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
46
|
+
},
|
47
|
+
snackbarShow: (text, showAction, duration) => {
|
48
|
+
const sa = (typeof showAction !== 'undefined') ? showAction : false
|
49
|
+
const dur = (typeof duration !== 'undefined') ? duration : 5000
|
50
|
+
document.styleSheets[0].addRule(':root', '--efu-snackbar-time:' + dur + 'ms!important')
|
51
|
+
Snackbar.show({
|
52
|
+
text: text,
|
53
|
+
showAction: sa,
|
54
|
+
duration: dur,
|
55
|
+
pos: 'top-center'
|
56
|
+
})
|
57
|
+
},
|
58
|
+
copy: async (text) => {
|
59
|
+
try {
|
60
|
+
await navigator.clipboard.writeText(text)
|
61
|
+
utils.snackbarShow(GLOBAL_CONFIG.lang.copy.success, false, 2000)
|
62
|
+
} catch (err) {
|
63
|
+
utils.snackbarShow(GLOBAL_CONFIG.lang.copy.error, false, 2000)
|
166
64
|
}
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
ele.addEventListener(event, fn, option)
|
174
|
-
utils.addGlobalFn('pjax', () => {
|
175
|
-
ele.removeEventListener(event, fn, option)
|
176
|
-
})
|
177
|
-
},
|
178
|
-
addGlobalFn: (key, fn, name = false, parent = window) => {
|
179
|
-
const globalFn = parent.globalFn || {}
|
180
|
-
const keyObj = globalFn[key] || {}
|
181
|
-
|
182
|
-
if (name && keyObj[name]) return
|
183
|
-
|
184
|
-
name = name || Object.keys(keyObj).length
|
185
|
-
keyObj[name] = fn
|
186
|
-
globalFn[key] = keyObj
|
187
|
-
parent.globalFn = globalFn
|
188
|
-
},
|
189
|
-
animateIn: (ele, text) => {
|
190
|
-
ele.style.display = 'block'
|
191
|
-
ele.style.animation = text
|
192
|
-
},
|
193
|
-
animateOut: (ele, text) => {
|
194
|
-
ele.addEventListener('animationend', function f() {
|
195
|
-
ele.style.display = ''
|
196
|
-
ele.style.animation = ''
|
197
|
-
ele.removeEventListener('animationend', f)
|
198
|
-
})
|
199
|
-
ele.style.animation = text
|
200
|
-
},
|
201
|
-
wrap: (selector, eleType, options) => {
|
202
|
-
const createEle = document.createElement(eleType)
|
203
|
-
for (const [key, value] of Object.entries(options)) {
|
204
|
-
createEle.setAttribute(key, value)
|
205
|
-
}
|
206
|
-
selector.parentNode.insertBefore(createEle, selector)
|
207
|
-
createEle.appendChild(selector)
|
208
|
-
},
|
209
|
-
lazyloadImg: function () {
|
210
|
-
window.lazyLoadInstance = new LazyLoad({
|
211
|
-
elements_selector: 'img',
|
212
|
-
threshold: 0,
|
213
|
-
data_src: 'lazy-src',
|
214
|
-
callback_error: (img) => {
|
215
|
-
img.setAttribute("src", GLOBAL_CONFIG.lazyload.error);
|
65
|
+
},
|
66
|
+
getEleTop: ele => {
|
67
|
+
let actualTop = 0
|
68
|
+
while (ele) {
|
69
|
+
actualTop += ele.offsetTop
|
70
|
+
ele = ele.offsetParent
|
216
71
|
}
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
72
|
+
return actualTop
|
73
|
+
},
|
74
|
+
randomNum: (length) => {
|
75
|
+
return Math.floor(Math.random() * length)
|
76
|
+
},
|
77
|
+
timeDiff: (timeObj, today) => {
|
78
|
+
const timeDiff = today.getTime() - timeObj.getTime();
|
79
|
+
return Math.floor(timeDiff / (1000 * 3600 * 24));
|
80
|
+
},
|
81
|
+
scrollToDest: (pos, time = 500) => {
|
82
|
+
const currentPos = window.pageYOffset
|
83
|
+
const isNavFixed = document.getElementById('page-header').classList.contains('nav-fixed')
|
84
|
+
if (currentPos > pos || isNavFixed) pos = pos - 70
|
85
|
+
if ('scrollBehavior' in document.documentElement.style) {
|
86
|
+
window.scrollTo({
|
87
|
+
top: pos,
|
88
|
+
behavior: 'smooth'
|
89
|
+
})
|
90
|
+
return
|
91
|
+
}
|
92
|
+
let start = null
|
93
|
+
const distance = pos - currentPos
|
94
|
+
window.requestAnimationFrame(function step(currentTime) {
|
95
|
+
start = !start ? currentTime : start
|
96
|
+
const progress = currentTime - start
|
97
|
+
if (progress < time) {
|
98
|
+
window.scrollTo(0, currentPos + distance * progress / time)
|
99
|
+
window.requestAnimationFrame(step)
|
100
|
+
} else {
|
101
|
+
window.scrollTo(0, pos)
|
240
102
|
}
|
241
103
|
})
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
104
|
+
},
|
105
|
+
siblings: (ele, selector) => {
|
106
|
+
return [...ele.parentNode.children].filter((child) => {
|
107
|
+
if (selector) {
|
108
|
+
return child !== ele && child.matches(selector)
|
109
|
+
}
|
110
|
+
return child !== ele
|
111
|
+
})
|
112
|
+
},
|
113
|
+
isMobile: () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
|
114
|
+
isHidden: e => 0 === e.offsetHeight && 0 === e.offsetWidth,
|
115
|
+
addEventListenerPjax: (ele, event, fn, option = false) => {
|
116
|
+
ele.addEventListener(event, fn, option)
|
117
|
+
utils.addGlobalFn('pjax', () => {
|
118
|
+
ele.removeEventListener(event, fn, option)
|
119
|
+
})
|
120
|
+
},
|
121
|
+
animateIn: (ele, text) => {
|
122
|
+
ele.style.display = 'block'
|
123
|
+
ele.style.animation = text
|
124
|
+
},
|
125
|
+
animateOut: (ele, text) => {
|
126
|
+
ele.addEventListener('animationend', function f() {
|
127
|
+
ele.style.display = ''
|
128
|
+
ele.style.animation = ''
|
129
|
+
ele.removeEventListener('animationend', f)
|
130
|
+
})
|
131
|
+
ele.style.animation = text
|
132
|
+
},
|
133
|
+
wrap: (selector, eleType, options) => {
|
134
|
+
const createEle = document.createElement(eleType)
|
135
|
+
for (const [key, value] of Object.entries(options)) {
|
136
|
+
createEle.setAttribute(key, value)
|
266
137
|
}
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
const {
|
278
|
-
time
|
279
|
-
} = GLOBAL_CONFIG.lang
|
280
|
-
|
281
|
-
if (!more) return parseInt(dateDiff / day)
|
282
|
-
|
283
|
-
const monthCount = dateDiff / month
|
284
|
-
const dayCount = dateDiff / day
|
285
|
-
const hourCount = dateDiff / hour
|
286
|
-
const minuteCount = dateDiff / minute
|
287
|
-
|
288
|
-
if (monthCount > 12) return datePost.toISOString().slice(0, 10)
|
289
|
-
if (monthCount >= 1) return `${parseInt(monthCount)} ${time.month}`
|
290
|
-
if (dayCount >= 1) return `${parseInt(dayCount)} ${time.day}`
|
291
|
-
if (hourCount >= 1) return `${parseInt(hourCount)} ${time.hour}`
|
292
|
-
if (minuteCount >= 1) return `${parseInt(minuteCount)} ${time.min}`
|
293
|
-
return time.just
|
294
|
-
},
|
295
|
-
loadComment: (dom, callback) => {
|
296
|
-
if ('IntersectionObserver' in window) {
|
297
|
-
const observerItem = new IntersectionObserver((entries) => {
|
298
|
-
if (entries[0].isIntersecting) {
|
299
|
-
callback()
|
300
|
-
observerItem.disconnect()
|
138
|
+
selector.parentNode.insertBefore(createEle, selector)
|
139
|
+
createEle.appendChild(selector)
|
140
|
+
},
|
141
|
+
lazyloadImg: function () {
|
142
|
+
window.lazyLoadInstance = new LazyLoad({
|
143
|
+
elements_selector: 'img',
|
144
|
+
threshold: 0,
|
145
|
+
data_src: 'lazy-src',
|
146
|
+
callback_error: (img) => {
|
147
|
+
img.setAttribute("src", GLOBAL_CONFIG.lazyload.error);
|
301
148
|
}
|
302
|
-
}, {
|
303
|
-
threshold: [0]
|
304
149
|
})
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
}
|
150
|
+
},
|
151
|
+
lightbox: function (selector) {
|
152
|
+
const lightboxType = GLOBAL_CONFIG.lightbox;
|
153
|
+
switch (lightboxType) {
|
154
|
+
case 'mediumZoom':
|
155
|
+
mediumZoom ? mediumZoom(selector, {background: "var(--efu-card-bg)"}) : false
|
156
|
+
break;
|
157
|
+
case 'fancybox':
|
158
|
+
selector.forEach(i => {
|
159
|
+
if (i.parentNode.tagName !== 'A') {
|
160
|
+
const dataSrc = i.dataset.lazySrc || i.src;
|
161
|
+
const dataCaption = i.title || i.alt || '';
|
162
|
+
utils.wrap(i, 'a', {
|
163
|
+
class: 'fancybox',
|
164
|
+
href: dataSrc,
|
165
|
+
'data-fancybox': 'gallery',
|
166
|
+
'data-caption': dataCaption,
|
167
|
+
'data-thumb': dataSrc
|
168
|
+
});
|
169
|
+
}
|
170
|
+
});
|
171
|
+
if (!window.fancyboxRun) {
|
172
|
+
Fancybox.bind('[data-fancybox]', {
|
173
|
+
Hash: false,
|
174
|
+
Thumbs: {showOnStart: false},
|
175
|
+
Images: {Panzoom: {maxScale: 4}},
|
176
|
+
Carousel: {transition: 'slide'},
|
177
|
+
Toolbar: {
|
178
|
+
display: {
|
179
|
+
left: ['infobar'],
|
180
|
+
middle: ['zoomIn', 'zoomOut', 'toggle1to1', 'rotateCCW', 'rotateCW', 'flipX', 'flipY'],
|
181
|
+
right: ['slideshow', 'thumbs', 'close']
|
182
|
+
}
|
183
|
+
}
|
184
|
+
});
|
185
|
+
window.fancyboxRun = true;
|
186
|
+
}
|
187
|
+
break;
|
188
|
+
}
|
189
|
+
},
|
190
|
+
diffDate: (d, more = false) => {
|
191
|
+
const dateNow = new Date();
|
192
|
+
const datePost = new Date(d);
|
193
|
+
const dateDiff = dateNow - datePost; // Simplified date difference calculation
|
194
|
+
const minute = 60000;
|
195
|
+
const hour = 3600000;
|
196
|
+
const day = 86400000;
|
197
|
+
const month = 2592000000;
|
198
|
+
const {time} = GLOBAL_CONFIG.lang;
|
199
|
+
if (!more) return Math.floor(dateDiff / day)
|
200
|
+
const minuteCount = Math.floor(dateDiff / minute)
|
201
|
+
const hourCount = Math.floor(dateDiff / hour)
|
202
|
+
const dayCount = Math.floor(dateDiff / day)
|
203
|
+
const monthCount = Math.floor(dateDiff / month)
|
204
|
+
if (monthCount > 12) return datePost.toISOString().slice(0, 10)
|
205
|
+
if (monthCount >= 1) return `${monthCount} ${time.month}`
|
206
|
+
if (dayCount >= 1) return `${dayCount} ${time.day}`
|
207
|
+
if (hourCount >= 1) return `${hourCount} ${time.hour}`
|
208
|
+
if (minuteCount >= 1) return `${minuteCount} ${time.min}`
|
209
|
+
return time.just
|
210
|
+
},
|
211
|
+
loadComment: (dom, callback) => {
|
212
|
+
if ('IntersectionObserver' in window) {
|
213
|
+
const observerItem = new IntersectionObserver((entries) => {
|
214
|
+
if (entries[0].isIntersecting) {
|
215
|
+
callback()
|
216
|
+
observerItem.disconnect()
|
217
|
+
}
|
218
|
+
}, {threshold: [0]})
|
219
|
+
observerItem.observe(dom)
|
220
|
+
} else {
|
221
|
+
callback()
|
222
|
+
}
|
223
|
+
},
|
224
|
+
}
|
225
|
+
window.utils = {...window.utils, ...utilsFn};
|
226
|
+
})()
|