hexo-theme-shokax 0.4.24 → 0.5.0-beta1
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 +19 -31
- package/UsageRestrictions.md +2 -2
- package/_config.yml +11 -25
- package/_images.yml +0 -7
- package/eslint.config.mjs +4 -5
- package/layout/_mixin/card.pug +1 -2
- package/layout/_mixin/comment.pug +0 -1
- package/layout/_mixin/segment.pug +1 -1
- package/layout/_partials/footer.pug +1 -4
- package/layout/_partials/head/head.pug +0 -8
- package/layout/_partials/head/pwa.pug +1 -1
- package/layout/_partials/header.pug +0 -1
- package/layout/_partials/layout.pug +4 -14
- package/layout/_partials/post/footer.pug +0 -2
- package/layout/_partials/post/post.pug +1 -2
- package/layout/_partials/post/reward.pug +1 -1
- package/layout/_partials/sidebar/overview.pug +0 -2
- package/layout/_partials/third-party/baidu-analytics.pug +1 -1
- package/layout/_partials/third-party/google-analytics.pug +1 -1
- package/layout/archive.pug +3 -0
- package/layout/category.pug +3 -0
- package/layout/index.pug +3 -0
- package/layout/page.pug +7 -0
- package/layout/post.pug +8 -0
- package/layout/tag.pug +3 -0
- package/package.json +9 -10
- package/scripts/filters/post.js +1 -1
- package/scripts/generaters/config.js +12 -7
- package/scripts/generaters/images.js +9 -8
- package/scripts/generaters/index.js +57 -44
- package/scripts/generaters/script.js +18 -33
- package/scripts/generaters/summary_ai.js +6 -7
- package/scripts/helpers/engine.js +2 -7
- package/scripts/plugin/index.js +32 -69
- package/scripts/tags/media.js +1 -1
- package/source/css/_common/outline/sidebar/sidebar.styl +1 -0
- package/source/css/app.styl +0 -13
- package/source/css/page.styl +3 -0
- package/source/css/post.styl +5 -0
- package/source/css/scaffolding.styl +5 -0
- package/source/js/_app/components/comments.ts +2 -3
- package/source/js/_app/components/sidebar.ts +35 -35
- package/source/js/_app/components/tcomments.ts +0 -1
- package/source/js/_app/globals/globalVars.ts +0 -15
- package/source/js/_app/globals/handles.ts +9 -9
- package/source/js/_app/globals/themeColor.ts +5 -6
- package/source/js/_app/globals/thirdparty.ts +2 -2
- package/source/js/_app/globals/tools.ts +4 -6
- package/source/js/_app/library/anime.ts +30 -19
- package/source/js/_app/library/declare.d.ts +0 -5
- package/source/js/_app/library/proto.ts +0 -67
- package/source/js/_app/library/vue.ts +7 -7
- package/source/js/_app/page/common.ts +8 -10
- package/source/js/_app/page/fancybox.ts +6 -8
- package/source/js/_app/page/post.ts +42 -54
- package/source/js/_app/page/search.ts +1 -6
- package/source/js/_app/page/tab.ts +8 -9
- package/source/js/_app/pjax/domInit.ts +19 -14
- package/source/js/_app/pjax/refresh.ts +8 -36
- package/source/js/_app/pjax/siteInit.ts +13 -42
- package/source/js/_app/player.ts +14 -798
- package/toolbox/compiler.mjs +20 -48
- package/toolbox/dev-version.mjs +14 -0
- package/README_en.MD +0 -71
- package/scripts/plugin/lib/injects-point.js +0 -41
- package/scripts/plugin/lib/injects.js +0 -105
- package/source/js/_app/library/dom.ts +0 -28
- package/source/js/_app/library/loadFile.ts +0 -47
- package/source/js/_app/library/scriptPjax.ts +0 -56
- package/source/js/_app/library/storage.ts +0 -12
@@ -1,9 +1,4 @@
|
|
1
|
-
import { $dom } from '../library/dom'
|
2
|
-
import Pjax from 'theme-shokax-pjax'
|
3
|
-
import initProto from '../library/proto'
|
4
|
-
|
5
1
|
export const CONFIG = shokax_CONFIG
|
6
|
-
initProto()
|
7
2
|
export const statics = CONFIG.statics.indexOf('//') > 0 ? CONFIG.statics : CONFIG.root
|
8
3
|
export const scrollAction: { x: number, y: number } = { x: 0, y: 0 }
|
9
4
|
export let diffY = 0
|
@@ -19,7 +14,6 @@ export const quickBtn = document.getElementById('quick')
|
|
19
14
|
export const sideBar = document.getElementById('sidebar')
|
20
15
|
export const siteBrand = document.getElementById('brand')
|
21
16
|
export let toolBtn = document.getElementById('tool')
|
22
|
-
export let toolPlayer
|
23
17
|
export let backToTop: HTMLElement
|
24
18
|
export let goToComment
|
25
19
|
export let showContents
|
@@ -29,7 +23,6 @@ export let oWinHeight = window.innerHeight
|
|
29
23
|
export let oWinWidth = window.innerWidth
|
30
24
|
export let LOCAL_HASH = 0
|
31
25
|
export let LOCAL_URL = window.location.href
|
32
|
-
export let pjax:Pjax
|
33
26
|
|
34
27
|
export function setSiteNavHeight (value:number):void {
|
35
28
|
siteNavHeight = value
|
@@ -66,18 +59,10 @@ export function setLocalUrl (value:string):void {
|
|
66
59
|
LOCAL_URL = value
|
67
60
|
}
|
68
61
|
|
69
|
-
export function setPjax (value:Pjax):void {
|
70
|
-
pjax = value
|
71
|
-
}
|
72
|
-
|
73
62
|
export function setOriginTitle (value:string):void {
|
74
63
|
originTitle = value
|
75
64
|
}
|
76
65
|
|
77
|
-
export function setToolPlayer (value:any):void {
|
78
|
-
toolPlayer = value
|
79
|
-
}
|
80
|
-
|
81
66
|
export function setBackToTop (value:HTMLElement):void {
|
82
67
|
backToTop = value
|
83
68
|
}
|
@@ -63,12 +63,12 @@ export const scrollHandle = () => {
|
|
63
63
|
}
|
64
64
|
|
65
65
|
// 控制导航栏的显示隐藏
|
66
|
-
siteNav.
|
66
|
+
siteNav.classList.toggle('show', SHOW)
|
67
67
|
// 控制网站 logo 的显示隐藏
|
68
|
-
toolBtn.
|
68
|
+
toolBtn.classList.toggle('affix', startScroll)
|
69
69
|
// 控制侧边栏的显示隐藏,当滚动高度大于 headerHight 且窗口宽度大于 991px 时显示
|
70
|
-
siteBrand.
|
71
|
-
sideBar.
|
70
|
+
siteBrand.classList.toggle('affix', startScroll)
|
71
|
+
sideBar.classList.toggle('affix', window.scrollY > headerHight && document.body.offsetWidth >= 991)
|
72
72
|
// 初始化滚动时导航栏的显示方向
|
73
73
|
if (typeof scrollAction.y === 'undefined') {
|
74
74
|
scrollAction.y = window.scrollY
|
@@ -77,11 +77,11 @@ export const scrollHandle = () => {
|
|
77
77
|
|
78
78
|
// 控制滑动时导航栏显示
|
79
79
|
if (diffY < 0) {
|
80
|
-
siteNav.
|
81
|
-
siteNav.
|
80
|
+
siteNav.classList.remove('up')
|
81
|
+
siteNav.classList.toggle('down', SHOW)
|
82
82
|
} else if (diffY > 0) {
|
83
|
-
siteNav.
|
84
|
-
siteNav.
|
83
|
+
siteNav.classList.remove('down')
|
84
|
+
siteNav.classList.toggle('up', SHOW)
|
85
85
|
} else { /* empty */ }
|
86
86
|
scrollAction.y = window.scrollY
|
87
87
|
// 计算滚动百分比
|
@@ -91,7 +91,7 @@ export const scrollHandle = () => {
|
|
91
91
|
backToTop.querySelector('span').innerText = scrollPercent
|
92
92
|
}
|
93
93
|
// 更新百分比进度条的宽度
|
94
|
-
if (document.getElementById('sidebar').
|
94
|
+
if (document.getElementById('sidebar').classList.contains('affix') || document.getElementById('sidebar').classList.contains('on')) {
|
95
95
|
setWidth(document.querySelector('.percent'), scrollPercent)
|
96
96
|
}
|
97
97
|
}
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import { $storage } from '../library/storage'
|
2
1
|
import { CONFIG, HTML } from './globalVars'
|
3
2
|
|
4
3
|
/**
|
@@ -8,12 +7,12 @@ export const changeTheme = (type?: string) => {
|
|
8
7
|
const btn = document.querySelector('.theme .ic')
|
9
8
|
if (type === 'dark') {
|
10
9
|
HTML.setAttribute('data-theme', type)
|
11
|
-
btn.
|
12
|
-
btn.
|
10
|
+
btn.classList.remove('i-sun')
|
11
|
+
btn.classList.add('i-moon')
|
13
12
|
} else {
|
14
13
|
HTML.removeAttribute('data-theme')
|
15
|
-
btn.
|
16
|
-
btn.
|
14
|
+
btn.classList.remove('i-moon')
|
15
|
+
btn.classList.add('i-sun')
|
17
16
|
}
|
18
17
|
}
|
19
18
|
|
@@ -52,7 +51,7 @@ export const themeColorListener = () => {
|
|
52
51
|
}
|
53
52
|
})
|
54
53
|
|
55
|
-
const t =
|
54
|
+
const t = localStorage.getItem('theme')
|
56
55
|
if (t) {
|
57
56
|
changeTheme(t)
|
58
57
|
} else {
|
@@ -9,7 +9,7 @@ export const Loader = {
|
|
9
9
|
lock: false,
|
10
10
|
show () {
|
11
11
|
clearTimeout(this.timer)
|
12
|
-
document.body.
|
12
|
+
document.body.classList.remove('loaded')
|
13
13
|
loadCat.setAttribute('style', 'display:block')
|
14
14
|
Loader.lock = false
|
15
15
|
},
|
@@ -26,7 +26,7 @@ export const Loader = {
|
|
26
26
|
if (CONFIG.loader.start) {
|
27
27
|
transition(loadCat, 0)
|
28
28
|
}
|
29
|
-
document.body.
|
29
|
+
document.body.classList.add('loaded')
|
30
30
|
Loader.lock = true
|
31
31
|
}
|
32
32
|
}
|
@@ -1,6 +1,4 @@
|
|
1
1
|
import { pageScroll } from '../library/anime'
|
2
|
-
import { $dom } from '../library/dom'
|
3
|
-
import { $storage } from '../library/storage'
|
4
2
|
import { BODY, CONFIG, LOCAL_HASH, LOCAL_URL, scrollAction, setLocalHash } from './globalVars'
|
5
3
|
import { createChild } from '../library/proto'
|
6
4
|
|
@@ -16,7 +14,7 @@ export const showtip = (msg: string): void | never => {
|
|
16
14
|
})
|
17
15
|
|
18
16
|
setTimeout(() => {
|
19
|
-
tipbox.
|
17
|
+
tipbox.classList.add('hide')
|
20
18
|
setTimeout(() => {
|
21
19
|
BODY.removeChild(tipbox)
|
22
20
|
}, 300)
|
@@ -27,7 +25,7 @@ export const pagePosition = () => {
|
|
27
25
|
// 判断配置项是否开启了自动记录滚动位置
|
28
26
|
if (CONFIG.auto_scroll) {
|
29
27
|
// 将当前页面的滚动位置存入本地缓存
|
30
|
-
|
28
|
+
localStorage.setItem(LOCAL_URL, String(scrollAction.y))
|
31
29
|
}
|
32
30
|
}
|
33
31
|
|
@@ -37,14 +35,14 @@ export const positionInit = (comment?: boolean) => {
|
|
37
35
|
|
38
36
|
let target = null
|
39
37
|
if (LOCAL_HASH) {
|
40
|
-
|
38
|
+
localStorage.removeItem(LOCAL_URL)
|
41
39
|
return
|
42
40
|
}
|
43
41
|
|
44
42
|
if (anchor) {
|
45
43
|
target = document.querySelector(decodeURI(anchor))
|
46
44
|
} else {
|
47
|
-
target = CONFIG.auto_scroll ? parseInt(
|
45
|
+
target = CONFIG.auto_scroll ? parseInt(localStorage.getItem(LOCAL_URL)) : 0
|
48
46
|
}
|
49
47
|
|
50
48
|
if (target) {
|
@@ -89,22 +89,33 @@ export const transition = (target: HTMLElement, type: number|string|Function, co
|
|
89
89
|
}, animation)).play()
|
90
90
|
}
|
91
91
|
|
92
|
-
export const pageScroll = (target: HTMLElement|number, offset?: number, complete?: Function) => {
|
93
|
-
//
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
}
|
110
|
-
|
92
|
+
export const pageScroll = (target: HTMLElement | number, offset?: number, complete?: Function) => {
|
93
|
+
// 确定滚动容器
|
94
|
+
const scrollContainer = (typeof offset === 'number' && typeof target !== 'number')
|
95
|
+
? target.parentNode as HTMLElement
|
96
|
+
: document.scrollingElement || document.documentElement;
|
97
|
+
|
98
|
+
// 计算目标滚动位置
|
99
|
+
let scrollTop: number;
|
100
|
+
if (typeof offset !== 'undefined') {
|
101
|
+
scrollTop = offset;
|
102
|
+
} else if (typeof target === 'number') {
|
103
|
+
scrollTop = target;
|
104
|
+
} else if (target) {
|
105
|
+
const rect = target.getBoundingClientRect();
|
106
|
+
scrollTop = rect.top + window.scrollY - siteNavHeight;
|
107
|
+
} else {
|
108
|
+
scrollTop = 0;
|
109
|
+
}
|
110
|
+
|
111
|
+
// 执行平滑滚动
|
112
|
+
scrollContainer.scrollTo({
|
113
|
+
top: scrollTop,
|
114
|
+
behavior: 'smooth'
|
115
|
+
});
|
116
|
+
|
117
|
+
// 处理完成回调(模拟动画持续时间)
|
118
|
+
if (complete) {
|
119
|
+
setTimeout(() => complete(), 500); // 与原动画持续时间保持一致
|
120
|
+
}
|
121
|
+
};
|
@@ -1,5 +1,3 @@
|
|
1
|
-
import { $dom } from './dom'
|
2
|
-
|
3
1
|
export const insertAfter = function (el: Element, element: HTMLElement): void {
|
4
2
|
const parent = el.parentNode
|
5
3
|
if (parent.lastChild === el) {
|
@@ -70,68 +68,3 @@ export const setDisplay = function (el: HTMLElement, d: string): HTMLElement {
|
|
70
68
|
el.style.display = d
|
71
69
|
return el
|
72
70
|
}
|
73
|
-
|
74
|
-
export default function initProto () {
|
75
|
-
Object.assign(HTMLElement.prototype, {
|
76
|
-
/**
|
77
|
-
* 找到此节点所有符合selector选择器的子节点
|
78
|
-
* @deprecated Will be removed in the v0.5
|
79
|
-
*/
|
80
|
-
find (selector: string): NodeListOf<HTMLElement> {
|
81
|
-
return $dom.all(selector, this)
|
82
|
-
},
|
83
|
-
/**
|
84
|
-
* 这个方法接受三个参数:
|
85
|
-
* type 表示操作类型('add'、'remove'、'toggle'),
|
86
|
-
* className 是一个或多个要操作的类名,
|
87
|
-
* display 是一个可选的布尔值,用于在执行切换操作时指定类名是否应显示或隐藏。
|
88
|
-
* 该方法会根据操作类型执行相应的类名操作。
|
89
|
-
* @deprecated Will be removed in the v0.5
|
90
|
-
*/
|
91
|
-
_class (type: string, className: string, display?: boolean): void {
|
92
|
-
const classNames = className.indexOf(' ') ? className.split(' ') : [className]
|
93
|
-
classNames.forEach((name) => {
|
94
|
-
if (type === 'toggle') {
|
95
|
-
this.classList.toggle(name, display)
|
96
|
-
} else {
|
97
|
-
this.classList[type](name)
|
98
|
-
}
|
99
|
-
})
|
100
|
-
},
|
101
|
-
/**
|
102
|
-
* 这个方法是对 _class 方法的封装,调用时会将操作类型设为 'add',然后执行添加类名的操作。
|
103
|
-
* 最后,它返回当前的 EventTarget,通常是 DOM 元素本身,以支持链式调用。
|
104
|
-
* @deprecated Will be removed in the v0.5
|
105
|
-
*/
|
106
|
-
addClass (className: string): EventTarget {
|
107
|
-
this._class('add', className)
|
108
|
-
return this
|
109
|
-
},
|
110
|
-
/**
|
111
|
-
* 这个方法是对 _class 方法的封装,调用时会将操作类型设为 'remove',然后执行移除类名的操作。
|
112
|
-
* 最后,它返回当前的 EventTarget,通常是 DOM 元素本身,以支持链式调用。
|
113
|
-
* @deprecated Will be removed in the v0.5
|
114
|
-
*/
|
115
|
-
removeClass (className: string): EventTarget {
|
116
|
-
this._class('remove', className)
|
117
|
-
return this
|
118
|
-
},
|
119
|
-
/**
|
120
|
-
* 这个方法是对 _class 方法的封装,调用时会将操作类型设为 'toggle',然后执行切换类名的操作。
|
121
|
-
* 如果提供了 display 参数,它将根据布尔值决定是否显示或隐藏类名。
|
122
|
-
* 最后,它返回当前的 EventTarget,通常是 DOM 元素本身,以支持链式调用。
|
123
|
-
* @deprecated Will be removed in the v0.5
|
124
|
-
*/
|
125
|
-
toggleClass (className: string, display?: boolean): EventTarget {
|
126
|
-
this._class('toggle', className, display)
|
127
|
-
return this
|
128
|
-
},
|
129
|
-
/**
|
130
|
-
* 这个方法返回一个布尔值,表示元素是否包含指定的类名。
|
131
|
-
* @deprecated Will be removed in the v0.5
|
132
|
-
*/
|
133
|
-
hasClass (className: string): boolean {
|
134
|
-
return this.classList.contains(className)
|
135
|
-
}
|
136
|
-
})
|
137
|
-
}
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import { $storage } from './storage'
|
2
1
|
import { transition } from './anime'
|
3
2
|
import { BODY } from '../globals/globalVars'
|
4
3
|
import { changeTheme } from '../globals/themeColor'
|
5
4
|
import { createChild, setDisplay } from './proto'
|
5
|
+
|
6
6
|
export function initVue () {
|
7
7
|
function changeThemeByBtn () {
|
8
8
|
let c: { (): void; (): void; (): void }
|
@@ -23,19 +23,19 @@ export function initVue () {
|
|
23
23
|
})
|
24
24
|
}
|
25
25
|
|
26
|
-
if (btn.
|
26
|
+
if (btn.classList.contains('i-sun')) {
|
27
27
|
c = () => {
|
28
|
-
neko.
|
28
|
+
neko.classList.add('dark')
|
29
29
|
changeTheme('dark')
|
30
|
-
|
30
|
+
localStorage.setItem('theme', 'dark')
|
31
31
|
hideNeko()
|
32
32
|
}
|
33
33
|
} else {
|
34
|
-
neko.
|
34
|
+
neko.classList.add('dark')
|
35
35
|
c = () => {
|
36
|
-
neko.
|
36
|
+
neko.classList.remove('dark')
|
37
37
|
changeTheme()
|
38
|
-
|
38
|
+
localStorage.setItem('theme', 'light')
|
39
39
|
hideNeko()
|
40
40
|
}
|
41
41
|
}
|
@@ -1,14 +1,12 @@
|
|
1
|
-
import { $dom } from '../library/dom'
|
2
|
-
|
3
1
|
export const cardActive = () => {
|
4
2
|
if (!document.querySelector('.index.wrap')) { return }
|
5
3
|
const io = new IntersectionObserver((entries) => {
|
6
4
|
entries.forEach((article) => {
|
7
|
-
if (article.target.
|
5
|
+
if (article.target.classList.contains('show')) {
|
8
6
|
io.unobserve(article.target)
|
9
7
|
} else {
|
10
8
|
if (article.isIntersecting || article.intersectionRatio > 0) {
|
11
|
-
article.target.
|
9
|
+
article.target.classList.add('show')
|
12
10
|
io.unobserve(article.target)
|
13
11
|
}
|
14
12
|
}
|
@@ -18,25 +16,25 @@ export const cardActive = () => {
|
|
18
16
|
threshold: [0.3]
|
19
17
|
})
|
20
18
|
|
21
|
-
|
19
|
+
document.querySelectorAll('.index.wrap article.item, .index.wrap section.item').forEach((article) => {
|
22
20
|
io.observe(article)
|
23
21
|
})
|
24
22
|
|
25
|
-
document.querySelector('.index.wrap .item:first-child').
|
23
|
+
document.querySelector('.index.wrap .item:first-child').classList.add('show')
|
26
24
|
|
27
|
-
|
25
|
+
document.querySelectorAll('.cards .item').forEach((element) => {
|
28
26
|
['mouseenter', 'touchstart'].forEach((item) => {
|
29
27
|
element.addEventListener(item, () => {
|
30
28
|
const cardEle = document.querySelector('.cards .item.active')
|
31
29
|
if (cardEle) {
|
32
|
-
cardEle.
|
30
|
+
cardEle.classList.remove('active')
|
33
31
|
}
|
34
|
-
element.
|
32
|
+
element.classList.add('active')
|
35
33
|
}, { passive: true })
|
36
34
|
});
|
37
35
|
['mouseleave'].forEach((item) => {
|
38
36
|
element.addEventListener(item, () => {
|
39
|
-
element.
|
37
|
+
element.classList.remove('active')
|
40
38
|
}, { passive: true })
|
41
39
|
})
|
42
40
|
})
|
@@ -1,14 +1,12 @@
|
|
1
|
-
import { $dom } from '../library/dom'
|
2
|
-
import { vendorCss, vendorJs } from '../library/loadFile'
|
3
1
|
import { insertAfter } from '../library/proto'
|
4
2
|
import DOMPurify from 'dompurify';
|
5
3
|
|
6
4
|
// TODO 使用PhotoSwipe替换Fancybox
|
7
5
|
export const postFancybox = (p:string) => {
|
8
6
|
if (document.querySelector(p + ' .md img')) {
|
9
|
-
vendorCss('fancybox')
|
10
|
-
vendorCss('justifiedGallery')
|
11
|
-
|
7
|
+
// vendorCss('fancybox')
|
8
|
+
// vendorCss('justifiedGallery')
|
9
|
+
document.querySelectorAll(p + ' p.gallery').forEach((element) => {
|
12
10
|
const box = document.createElement('div')
|
13
11
|
box.className = 'gallery'
|
14
12
|
box.setAttribute('data-height', String(element.getAttribute('data-height') || 220))
|
@@ -19,9 +17,9 @@ export const postFancybox = (p:string) => {
|
|
19
17
|
element.remove()
|
20
18
|
})
|
21
19
|
|
22
|
-
|
20
|
+
document.querySelectorAll(p + ' .md img:not(.emoji):not(.vemoji)').forEach((element) => {
|
23
21
|
const $image = $(element)
|
24
|
-
const imageLink = DOMPurify.sanitize($image.attr('
|
22
|
+
const imageLink = DOMPurify.sanitize($image.attr('src')) // 替换
|
25
23
|
const $imageWrapLink = $image.wrap('<a class="fancybox" href="' + imageLink + '" itemscope itemtype="https://schema.org/ImageObject" itemprop="url"></a>').parent('a')
|
26
24
|
let info; let captionClass = 'image-info'
|
27
25
|
if (!$image.is('a img')) {
|
@@ -42,7 +40,7 @@ export const postFancybox = (p:string) => {
|
|
42
40
|
}
|
43
41
|
})
|
44
42
|
|
45
|
-
|
43
|
+
document.querySelectorAll(p + ' div.gallery').forEach((el, i) => {
|
46
44
|
// @ts-ignore
|
47
45
|
$(el).justifiedGallery({
|
48
46
|
rowHeight: $(el).data('height') || 120,
|