hexo-theme-shokax 0.4.3 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- package/layout/_partials/layout.pug +1 -1
- package/package.json +1 -1
- package/scripts/plugin/index.js +3 -1
- package/source/js/_app/components/comments.ts +1 -1
- package/source/js/_app/components/sidebar.ts +23 -23
- package/source/js/_app/components/tcomments.ts +1 -2
- package/source/js/_app/globals/globalVars.ts +10 -10
- package/source/js/_app/globals/handles.ts +9 -8
- package/source/js/_app/globals/themeColor.ts +2 -3
- package/source/js/_app/globals/tools.ts +1 -1
- package/source/js/_app/library/declare.d.ts +0 -3
- package/source/js/_app/library/dom.ts +4 -2
- package/source/js/_app/library/loadFile.ts +7 -0
- package/source/js/_app/library/proto.ts +8 -12
- package/source/js/_app/library/vue.ts +3 -4
- package/source/js/_app/page/common.ts +5 -4
- package/source/js/_app/page/fancybox.ts +2 -1
- package/source/js/_app/page/post.ts +22 -22
- package/source/js/_app/page/search.ts +3 -3
- package/source/js/_app/page/tab.ts +4 -4
- package/source/js/_app/pjax/domInit.ts +10 -10
- package/source/js/_app/pjax/refresh.ts +24 -21
- package/source/js/_app/pjax/siteInit.ts +3 -3
- package/source/js/_app/player.ts +13 -14
@@ -130,7 +130,7 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f
|
|
130
130
|
|
131
131
|
!= vendor_js()
|
132
132
|
if theme.polyfill.enable
|
133
|
-
script(src=`https://
|
133
|
+
script(src=`https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?version=4.8.0&features=${theme.polyfill.features}` defer)
|
134
134
|
|
135
135
|
!= _js('siteInit.js')
|
136
136
|
|
package/package.json
CHANGED
package/scripts/plugin/index.js
CHANGED
@@ -47,7 +47,9 @@ hexo.on('generateBefore', () => {
|
|
47
47
|
});
|
48
48
|
hexo.on('generateAfter', () => {
|
49
49
|
// 检查版本更新
|
50
|
-
fetch('https://api.shokax.top/version/hexo'
|
50
|
+
fetch('https://api.shokax.top/version/hexo', { headers: {
|
51
|
+
"User-Agent": "Mozilla/5.0 ShokaX Client (hexo-theme-shokax)"
|
52
|
+
} }).then((res) => {
|
51
53
|
res.json().then((resp) => {
|
52
54
|
try {
|
53
55
|
const latest = resp['version'];
|
@@ -4,7 +4,7 @@ import { CONFIG, Container, diffY, menuToggle, showContents, sideBar } from '../
|
|
4
4
|
import { clipBoard } from '../globals/tools'
|
5
5
|
import { pageScroll, transition } from '../library/anime'
|
6
6
|
import { $dom } from '../library/dom'
|
7
|
-
import initProto, {
|
7
|
+
import initProto, { getHeight, setDisplay } from '../library/proto'
|
8
8
|
|
9
9
|
initProto()
|
10
10
|
export const sideBarToggleHandle = (event:Event, force?:number) => {
|
@@ -33,17 +33,17 @@ export const sideBarToggleHandle = (event:Event, force?:number) => {
|
|
33
33
|
}
|
34
34
|
|
35
35
|
export const sideBarTab = () => {
|
36
|
-
const sideBarInner =
|
36
|
+
const sideBarInner = sideBar.querySelector('.inner')
|
37
37
|
|
38
|
-
if (sideBar.
|
39
|
-
sideBarInner.removeChild(sideBar.
|
38
|
+
if (sideBar.querySelector('.tab')) {
|
39
|
+
sideBarInner.removeChild(sideBar.querySelector('.tab'))
|
40
40
|
}
|
41
41
|
|
42
42
|
const list = document.createElement('ul'); let active = 'active'
|
43
43
|
list.className = 'tab';
|
44
44
|
|
45
45
|
['contents', 'related', 'overview'].forEach((item) => {
|
46
|
-
const element = sideBar.
|
46
|
+
const element = sideBar.querySelector('.panel.' + item)
|
47
47
|
|
48
48
|
if (element.innerHTML.trim().length < 1) {
|
49
49
|
if (item === 'contents') {
|
@@ -81,7 +81,7 @@ export const sideBarTab = () => {
|
|
81
81
|
element.removeClass('active')
|
82
82
|
})
|
83
83
|
|
84
|
-
sideBar.
|
84
|
+
sideBar.querySelector('.panel.' + target.className.replace(' item', '')).addClass('active')
|
85
85
|
|
86
86
|
target.addClass('active')
|
87
87
|
})
|
@@ -91,10 +91,10 @@ export const sideBarTab = () => {
|
|
91
91
|
})
|
92
92
|
|
93
93
|
if (list.childNodes.length > 1) {
|
94
|
-
sideBarInner.insertBefore(list, sideBarInner.childNodes[0])
|
95
|
-
sideBar.
|
94
|
+
sideBarInner.insertBefore(list, sideBarInner.childNodes[0]);
|
95
|
+
(sideBar.querySelector('.panels') as HTMLElement).style.paddingTop = ''
|
96
96
|
} else {
|
97
|
-
sideBar.
|
97
|
+
(sideBar.querySelector('.panels') as HTMLElement).style.paddingTop = '.625rem'
|
98
98
|
}
|
99
99
|
}
|
100
100
|
|
@@ -124,7 +124,7 @@ export const sidebarTOC = () => {
|
|
124
124
|
while (!parent.matches('.contents')) {
|
125
125
|
if (parent.matches('li')) {
|
126
126
|
parent.addClass('active')
|
127
|
-
const t =
|
127
|
+
const t = document.querySelector(parent.querySelector('a.toc-link').getAttribute('href'))
|
128
128
|
if (t) {
|
129
129
|
t.addClass('active')
|
130
130
|
}
|
@@ -133,7 +133,7 @@ export const sidebarTOC = () => {
|
|
133
133
|
}
|
134
134
|
// Scrolling to center active TOC element if TOC content is taller than viewport.
|
135
135
|
if (getComputedStyle(sideBar).display !== 'none' && tocElement.hasClass('active')) {
|
136
|
-
pageScroll(tocElement, target.offsetTop - (tocElement.offsetHeight / 4))
|
136
|
+
pageScroll((tocElement as HTMLElement), target.offsetTop - ((tocElement as HTMLElement).offsetHeight / 4))
|
137
137
|
}
|
138
138
|
}
|
139
139
|
const navItems = $dom.all('.contents li')
|
@@ -142,21 +142,21 @@ export const sidebarTOC = () => {
|
|
142
142
|
return
|
143
143
|
}
|
144
144
|
|
145
|
-
let sections = [...navItems]
|
145
|
+
let sections = [...navItems] as HTMLElement[]
|
146
146
|
let activeLock = null
|
147
147
|
|
148
148
|
sections = sections.map((element, index) => {
|
149
|
-
const link = element.
|
150
|
-
const anchor =
|
149
|
+
const link = element.querySelector('a.toc-link')
|
150
|
+
const anchor = document.querySelector(decodeURI(link.getAttribute('href')))
|
151
151
|
if (!anchor) return null
|
152
|
-
const alink = anchor.
|
152
|
+
const alink = anchor.querySelector('a.anchor')
|
153
153
|
|
154
154
|
const anchorScroll = (event:MouseEvent) => {
|
155
155
|
event.preventDefault()
|
156
|
-
const target =
|
156
|
+
const target = document.querySelector(decodeURI((event.currentTarget as HTMLElement).getAttribute('href')))
|
157
157
|
|
158
158
|
activeLock = index
|
159
|
-
pageScroll(target, null, () => {
|
159
|
+
pageScroll((target as HTMLElement), null, () => {
|
160
160
|
activateNavByIndex(index)
|
161
161
|
activeLock = null
|
162
162
|
})
|
@@ -165,13 +165,13 @@ export const sidebarTOC = () => {
|
|
165
165
|
// TOC item animation navigate.
|
166
166
|
link.addEventListener('click', anchorScroll)
|
167
167
|
alink && alink.addEventListener('click', (event) => {
|
168
|
-
anchorScroll(event)
|
168
|
+
anchorScroll(<MouseEvent>event)
|
169
169
|
clipBoard(CONFIG.hostname + '/' + LOCAL.path + (event.currentTarget as HTMLElement).getAttribute('href'))
|
170
170
|
})
|
171
|
-
return anchor
|
171
|
+
return (anchor as HTMLElement)
|
172
172
|
})
|
173
173
|
|
174
|
-
const tocElement = sideBar.
|
174
|
+
const tocElement = sideBar.querySelector('.contents.panel')
|
175
175
|
|
176
176
|
const findIndex = (entries: IntersectionObserverEntry[]) => {
|
177
177
|
let index = 0
|
@@ -218,19 +218,19 @@ export const goToBottomHandle = () => {
|
|
218
218
|
}
|
219
219
|
|
220
220
|
export const goToCommentHandle = () => {
|
221
|
-
pageScroll(
|
221
|
+
pageScroll(document.getElementById('comments'))
|
222
222
|
}
|
223
223
|
|
224
224
|
export const menuActive = () => {
|
225
225
|
$dom.each('.menu .item:not(.title)', (element) => {
|
226
|
-
const target = <HTMLAnchorElement> element.
|
226
|
+
const target = <HTMLAnchorElement> element.querySelector('a[href]')
|
227
227
|
const parentItem = element.parentNode.parentNode
|
228
228
|
if (!target) return
|
229
229
|
const isSamePath = target.pathname === location.pathname || target.pathname === location.pathname.replace('index.html', '')
|
230
230
|
const isSubPath = !CONFIG.root.startsWith(target.pathname) && location.pathname.startsWith(target.pathname)
|
231
231
|
const active = !target.onclick && target.hostname === location.hostname && (isSamePath || isSubPath)
|
232
232
|
element.toggleClass('active', active)
|
233
|
-
if (element.parentNode.
|
233
|
+
if (element.parentNode.querySelector('.active') && parentItem.hasClass('dropdown')) {
|
234
234
|
parentItem.removeClass('active').addClass('expand')
|
235
235
|
} else {
|
236
236
|
parentItem.removeClass('expand')
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import * as twikoo from 'twikoo'
|
2
2
|
import { CONFIG } from '../globals/globalVars'
|
3
|
-
import { $dom } from '../library/dom'
|
4
3
|
|
5
4
|
export const twikooComment = function () {
|
6
5
|
twikoo.init({
|
@@ -51,5 +50,5 @@ export const twikooRecentComments = async function () {
|
|
51
50
|
newComments.appendChild(commentEl)
|
52
51
|
})
|
53
52
|
|
54
|
-
|
53
|
+
document.getElementById('new-comment').appendChild(newComments)
|
55
54
|
}
|
@@ -10,20 +10,20 @@ export let diffY = 0
|
|
10
10
|
export let originTitle: string, titleTime: NodeJS.Timeout
|
11
11
|
export const BODY = document.getElementsByTagName('body')[0]
|
12
12
|
export const HTML = document.documentElement
|
13
|
-
export const Container =
|
14
|
-
export const loadCat =
|
15
|
-
export const siteNav =
|
16
|
-
export const siteHeader =
|
17
|
-
export const menuToggle = siteNav.
|
18
|
-
export const quickBtn =
|
19
|
-
export const sideBar =
|
20
|
-
export const siteBrand =
|
21
|
-
export let toolBtn =
|
13
|
+
export const Container = document.getElementById('container')
|
14
|
+
export const loadCat = document.getElementById('loading')
|
15
|
+
export const siteNav = document.getElementById('nav')
|
16
|
+
export const siteHeader = document.getElementById('header')
|
17
|
+
export const menuToggle = siteNav.querySelector('.toggle')
|
18
|
+
export const quickBtn = document.getElementById('quick')
|
19
|
+
export const sideBar = document.getElementById('sidebar')
|
20
|
+
export const siteBrand = document.getElementById('brand')
|
21
|
+
export let toolBtn = document.getElementById('tool')
|
22
22
|
export let toolPlayer
|
23
23
|
export let backToTop: HTMLElement
|
24
24
|
export let goToComment
|
25
25
|
export let showContents
|
26
|
-
export let siteSearch =
|
26
|
+
export let siteSearch = document.getElementById('search')
|
27
27
|
export let siteNavHeight: number, headerHightInner: number, headerHight: number
|
28
28
|
export let oWinHeight = window.innerHeight
|
29
29
|
export let oWinWidth = window.innerWidth
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { sideBarToggleHandle } from '../components/sidebar'
|
2
|
-
import { $dom, getDocHeight } from '../library/dom'
|
3
2
|
import {
|
4
3
|
backToTop,
|
5
4
|
diffY,
|
@@ -24,13 +23,15 @@ import { changeMetaTheme } from './themeColor'
|
|
24
23
|
import { Loader } from './thirdparty'
|
25
24
|
import { getHeight, setWidth } from '../library/proto'
|
26
25
|
|
26
|
+
const wavesEle = document.getElementById('waves')
|
27
|
+
|
27
28
|
export const resizeHandle = () => {
|
28
29
|
// 获取 siteNav 的高度
|
29
30
|
setSiteNavHeight(getHeight(siteNav))
|
30
31
|
// 获取 siteHeader 的高度
|
31
32
|
setHeaderHightInner(getHeight(siteHeader))
|
32
33
|
// 获取 #waves 的高度
|
33
|
-
setHeaderHight(headerHightInner + getHeight(
|
34
|
+
setHeaderHight(headerHightInner + getHeight(wavesEle))
|
34
35
|
|
35
36
|
// 判断窗口宽度是否改变
|
36
37
|
if (oWinWidth !== window.innerWidth) {
|
@@ -46,7 +47,7 @@ export const scrollHandle = () => {
|
|
46
47
|
// 获取窗口高度
|
47
48
|
const winHeight = window.innerHeight
|
48
49
|
// 获取文档高度
|
49
|
-
const docHeight =
|
50
|
+
const docHeight = (document.querySelector('main > .inner') as HTMLElement).offsetHeight
|
50
51
|
// 计算可见内容高度
|
51
52
|
const contentVisibilityHeight = docHeight > winHeight ? docHeight - winHeight : document.body.scrollHeight - winHeight
|
52
53
|
// 判断页面是否滚动超过 headerHightInner
|
@@ -86,18 +87,18 @@ export const scrollHandle = () => {
|
|
86
87
|
// 计算滚动百分比
|
87
88
|
const scrollPercent = Math.round(Math.min(100 * window.scrollY / contentVisibilityHeight, 100)) + '%'
|
88
89
|
// 更新回到顶部按钮的文字
|
89
|
-
if (backToTop.
|
90
|
-
backToTop.
|
90
|
+
if (backToTop.querySelector('span').innerText !== scrollPercent) {
|
91
|
+
backToTop.querySelector('span').innerText = scrollPercent
|
91
92
|
}
|
92
93
|
// 更新百分比进度条的宽度
|
93
|
-
if (
|
94
|
-
setWidth(
|
94
|
+
if (document.getElementById('sidebar').hasClass('affix') || document.getElementById('sidebar').hasClass('on')) {
|
95
|
+
setWidth(document.querySelector('.percent'), scrollPercent)
|
95
96
|
}
|
96
97
|
}
|
97
98
|
|
98
99
|
// 可见度监听(离开页面和返回时更改document的title)
|
99
100
|
export const visibilityListener = () => {
|
100
|
-
const iconNode =
|
101
|
+
const iconNode = document.querySelector('[rel="icon"]')
|
101
102
|
document.addEventListener('visibilitychange', () => {
|
102
103
|
switch (document.visibilityState) {
|
103
104
|
case 'hidden':
|
@@ -1,12 +1,11 @@
|
|
1
1
|
import { $storage } from '../library/storage'
|
2
|
-
import { $dom } from '../library/dom'
|
3
2
|
import { CONFIG, HTML } from './globalVars'
|
4
3
|
|
5
4
|
/**
|
6
5
|
* 更改日夜模式
|
7
6
|
*/
|
8
7
|
export const changeTheme = (type?: string) => {
|
9
|
-
const btn =
|
8
|
+
const btn = document.querySelector('.theme .ic')
|
10
9
|
if (type === 'dark') {
|
11
10
|
HTML.setAttribute('data-theme', type)
|
12
11
|
btn.removeClass('i-sun')
|
@@ -40,7 +39,7 @@ export const changeMetaTheme = (color: string): void => {
|
|
40
39
|
color = '#222'
|
41
40
|
}
|
42
41
|
|
43
|
-
|
42
|
+
document.querySelector('meta[name="theme-color"]').setAttribute('content', color)
|
44
43
|
}
|
45
44
|
|
46
45
|
// 记忆日夜模式切换和系统亮暗模式监听
|
@@ -7,8 +7,6 @@ interface AudioItem {
|
|
7
7
|
}
|
8
8
|
|
9
9
|
declare interface EventTarget {
|
10
|
-
createChild(tag: string, obj: Object, positon?: string): HTMLElement;
|
11
|
-
wrapObject(obj: Object): void;
|
12
10
|
changeOrGetHeight(h: number | string): void;
|
13
11
|
changeOrGetHeight(): number;
|
14
12
|
changeOrGetWidth(w: number | string): void;
|
@@ -18,7 +16,6 @@ declare interface EventTarget {
|
|
18
16
|
insertAfter(element: HTMLElement): void;
|
19
17
|
display(d: string): EventTarget;
|
20
18
|
display():string
|
21
|
-
child(selector: string): HTMLElement;
|
22
19
|
find(selector: string): NodeListOf<HTMLElement>;
|
23
20
|
_class(type: string, className: string, display?: boolean): void;
|
24
21
|
addClass(className: string): EventTarget;
|
@@ -1,6 +1,6 @@
|
|
1
|
-
const getDocHeight = () => $dom('main > .inner').offsetHeight
|
2
1
|
/**
|
3
2
|
* 获取一个dom选择器对应的元素
|
3
|
+
* @deprecated Will be removed in the v0.5
|
4
4
|
*/
|
5
5
|
const $dom = (selector: string, element: Document = document): HTMLElement => {
|
6
6
|
// 在测试环境中这能优化0.01-0.02ms左右
|
@@ -12,15 +12,17 @@ const $dom = (selector: string, element: Document = document): HTMLElement => {
|
|
12
12
|
|
13
13
|
/**
|
14
14
|
* 获取具有此选择器的所有dom节点
|
15
|
+
* @deprecated Will be removed in the v0.5
|
15
16
|
*/
|
16
17
|
$dom.all = (selector: string, element: Document = document): NodeListOf<HTMLElement> => {
|
17
18
|
return element.querySelectorAll(selector)
|
18
19
|
}
|
19
20
|
/**
|
20
21
|
* 获取具有此选择器的所有dom节点,并依次执行callback函数
|
22
|
+
* @deprecated Will be removed in the v0.5
|
21
23
|
*/
|
22
24
|
$dom.each = (selector: string, callback: (value: HTMLElement, key: number, parent: NodeListOf<Element>) => void, element?: Document): void => {
|
23
25
|
$dom.all(selector, element).forEach(callback)
|
24
26
|
}
|
25
27
|
|
26
|
-
export { $dom
|
28
|
+
export { $dom }
|
@@ -4,6 +4,7 @@ import { createChild } from './proto'
|
|
4
4
|
|
5
5
|
/**
|
6
6
|
* 用途是根据不同的资源名称和类型生成相应的资源 URL。
|
7
|
+
* @deprecated Use smart bundle and import() instead. Will be removed in the v0.5
|
7
8
|
*/
|
8
9
|
const assetUrl = (asset: string, type: string): string => {
|
9
10
|
const str = CONFIG[asset][type]
|
@@ -19,6 +20,9 @@ const assetUrl = (asset: string, type: string): string => {
|
|
19
20
|
return `/${str}`
|
20
21
|
}
|
21
22
|
|
23
|
+
/**
|
24
|
+
@deprecated Use smart bundle and import() instead. Will be removed in the v0.5
|
25
|
+
*/
|
22
26
|
export const vendorJs = (type: string, callback?: Function, condition?: string) => {
|
23
27
|
if (LOCAL[type]) {
|
24
28
|
getScript(assetUrl('js', type), callback || function () {
|
@@ -27,6 +31,9 @@ export const vendorJs = (type: string, callback?: Function, condition?: string)
|
|
27
31
|
}
|
28
32
|
}
|
29
33
|
|
34
|
+
/**
|
35
|
+
@deprecated Use smart bundle and import() instead. Will be removed in the v0.5
|
36
|
+
*/
|
30
37
|
export const vendorCss = (type: string, condition?: string): void => {
|
31
38
|
if (window['css' + type]) {
|
32
39
|
return
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { $dom } from './dom'
|
2
2
|
|
3
|
-
export const insertAfter = function (el:
|
3
|
+
export const insertAfter = function (el: Element, element: HTMLElement): void {
|
4
4
|
const parent = el.parentNode
|
5
5
|
if (parent.lastChild === el) {
|
6
6
|
parent.appendChild(element)
|
@@ -12,7 +12,7 @@ export const insertAfter = function (el: HTMLElement, element: HTMLElement): voi
|
|
12
12
|
/**
|
13
13
|
* 创建一个子节点并放置
|
14
14
|
*/
|
15
|
-
export const createChild = function (parent:
|
15
|
+
export const createChild = function (parent: Element, tag: string, obj: object, positon?: string): HTMLElement {
|
16
16
|
const child = document.createElement(tag)
|
17
17
|
Object.assign(child, obj)
|
18
18
|
switch (positon) {
|
@@ -71,20 +71,11 @@ export const setDisplay = function (el: HTMLElement, d: string): HTMLElement {
|
|
71
71
|
return el
|
72
72
|
}
|
73
73
|
|
74
|
-
// TODO 未完成迁移
|
75
|
-
export const child = function (el: HTMLElement, selector: string): HTMLElement {
|
76
|
-
return $dom(selector, (el as unknown as Document))
|
77
|
-
}
|
78
74
|
export default function initProto () {
|
79
75
|
Object.assign(HTMLElement.prototype, {
|
80
76
|
/**
|
81
|
-
* 找到此节点第一个符合selector选择器的子节点
|
82
|
-
*/
|
83
|
-
child (selector: string): HTMLElement {
|
84
|
-
return $dom(selector, this)
|
85
|
-
},
|
86
|
-
/**
|
87
77
|
* 找到此节点所有符合selector选择器的子节点
|
78
|
+
* @deprecated Will be removed in the v0.5
|
88
79
|
*/
|
89
80
|
find (selector: string): NodeListOf<HTMLElement> {
|
90
81
|
return $dom.all(selector, this)
|
@@ -95,6 +86,7 @@ export default function initProto () {
|
|
95
86
|
* className 是一个或多个要操作的类名,
|
96
87
|
* display 是一个可选的布尔值,用于在执行切换操作时指定类名是否应显示或隐藏。
|
97
88
|
* 该方法会根据操作类型执行相应的类名操作。
|
89
|
+
* @deprecated Will be removed in the v0.5
|
98
90
|
*/
|
99
91
|
_class (type: string, className: string, display?: boolean): void {
|
100
92
|
const classNames = className.indexOf(' ') ? className.split(' ') : [className]
|
@@ -109,6 +101,7 @@ export default function initProto () {
|
|
109
101
|
/**
|
110
102
|
* 这个方法是对 _class 方法的封装,调用时会将操作类型设为 'add',然后执行添加类名的操作。
|
111
103
|
* 最后,它返回当前的 EventTarget,通常是 DOM 元素本身,以支持链式调用。
|
104
|
+
* @deprecated Will be removed in the v0.5
|
112
105
|
*/
|
113
106
|
addClass (className: string): EventTarget {
|
114
107
|
this._class('add', className)
|
@@ -117,6 +110,7 @@ export default function initProto () {
|
|
117
110
|
/**
|
118
111
|
* 这个方法是对 _class 方法的封装,调用时会将操作类型设为 'remove',然后执行移除类名的操作。
|
119
112
|
* 最后,它返回当前的 EventTarget,通常是 DOM 元素本身,以支持链式调用。
|
113
|
+
* @deprecated Will be removed in the v0.5
|
120
114
|
*/
|
121
115
|
removeClass (className: string): EventTarget {
|
122
116
|
this._class('remove', className)
|
@@ -126,6 +120,7 @@ export default function initProto () {
|
|
126
120
|
* 这个方法是对 _class 方法的封装,调用时会将操作类型设为 'toggle',然后执行切换类名的操作。
|
127
121
|
* 如果提供了 display 参数,它将根据布尔值决定是否显示或隐藏类名。
|
128
122
|
* 最后,它返回当前的 EventTarget,通常是 DOM 元素本身,以支持链式调用。
|
123
|
+
* @deprecated Will be removed in the v0.5
|
129
124
|
*/
|
130
125
|
toggleClass (className: string, display?: boolean): EventTarget {
|
131
126
|
this._class('toggle', className, display)
|
@@ -133,6 +128,7 @@ export default function initProto () {
|
|
133
128
|
},
|
134
129
|
/**
|
135
130
|
* 这个方法返回一个布尔值,表示元素是否包含指定的类名。
|
131
|
+
* @deprecated Will be removed in the v0.5
|
136
132
|
*/
|
137
133
|
hasClass (className: string): boolean {
|
138
134
|
return this.classList.contains(className)
|
@@ -1,13 +1,12 @@
|
|
1
1
|
import { $storage } from './storage'
|
2
2
|
import { transition } from './anime'
|
3
|
-
import { $dom } from './dom'
|
4
3
|
import { BODY } from '../globals/globalVars'
|
5
4
|
import { changeTheme } from '../globals/themeColor'
|
6
|
-
import {
|
5
|
+
import { createChild, setDisplay } from './proto'
|
7
6
|
export function initVue () {
|
8
7
|
function changeThemeByBtn () {
|
9
8
|
let c: { (): void; (): void; (): void }
|
10
|
-
const btn =
|
9
|
+
const btn = document.querySelector('.theme').querySelector('.ic')
|
11
10
|
|
12
11
|
const neko = createChild(BODY, 'div', {
|
13
12
|
id: 'neko',
|
@@ -46,5 +45,5 @@ export function initVue () {
|
|
46
45
|
setDisplay(neko, 'block')
|
47
46
|
})
|
48
47
|
}
|
49
|
-
|
48
|
+
document.getElementById('rightNav').querySelector('.theme .ic').addEventListener('click', changeThemeByBtn)
|
50
49
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { $dom } from '../library/dom'
|
2
2
|
|
3
3
|
export const cardActive = () => {
|
4
|
-
if (
|
4
|
+
if (!document.querySelector('.index.wrap')) { return }
|
5
5
|
const io = new IntersectionObserver((entries) => {
|
6
6
|
entries.forEach((article) => {
|
7
7
|
if (article.target.hasClass('show')) {
|
@@ -22,13 +22,14 @@ export const cardActive = () => {
|
|
22
22
|
io.observe(article)
|
23
23
|
})
|
24
24
|
|
25
|
-
|
25
|
+
document.querySelector('.index.wrap .item:first-child').addClass('show')
|
26
26
|
|
27
27
|
$dom.each('.cards .item', (element) => {
|
28
28
|
['mouseenter', 'touchstart'].forEach((item) => {
|
29
29
|
element.addEventListener(item, () => {
|
30
|
-
|
31
|
-
|
30
|
+
const cardEle = document.querySelector('.cards .item.active')
|
31
|
+
if (cardEle) {
|
32
|
+
cardEle.removeClass('active')
|
32
33
|
}
|
33
34
|
element.addClass('active')
|
34
35
|
}, { passive: true })
|
@@ -2,8 +2,9 @@ import { $dom } from '../library/dom'
|
|
2
2
|
import { vendorCss, vendorJs } from '../library/loadFile'
|
3
3
|
import { insertAfter } from '../library/proto'
|
4
4
|
|
5
|
+
// TODO 使用PhotoSwipe替换Fancybox
|
5
6
|
export const postFancybox = (p:string) => {
|
6
|
-
if (
|
7
|
+
if (document.querySelector(p + ' .md img')) {
|
7
8
|
vendorCss('fancybox')
|
8
9
|
vendorCss('justifiedGallery')
|
9
10
|
vendorJs('fancybox', () => {
|
@@ -7,13 +7,13 @@ import { mediaPlayer } from '../player'
|
|
7
7
|
import { getDisplay, setDisplay, wrapObject } from '../library/proto'
|
8
8
|
|
9
9
|
export const postBeauty = () => {
|
10
|
-
if (
|
10
|
+
if (!document.querySelector('.md')) { return }
|
11
11
|
|
12
12
|
if (__shokax_fancybox__) {
|
13
13
|
postFancybox('.post.block')
|
14
14
|
}
|
15
15
|
|
16
|
-
|
16
|
+
(document.querySelector('.post.block') as HTMLTextAreaElement).oncopy = (event) => {
|
17
17
|
showtip(LOCAL.copyright)
|
18
18
|
|
19
19
|
if (LOCAL.nocopy) {
|
@@ -21,12 +21,12 @@ export const postBeauty = () => {
|
|
21
21
|
return
|
22
22
|
}
|
23
23
|
|
24
|
-
const copyright =
|
24
|
+
const copyright = document.getElementById('copyright')
|
25
25
|
if (window.getSelection().toString().length > 30 && copyright) {
|
26
26
|
event.preventDefault()
|
27
|
-
const author = '# ' + copyright.
|
28
|
-
const link = '# ' + copyright.
|
29
|
-
const license = '# ' + copyright.
|
27
|
+
const author = '# ' + (copyright.querySelector('.author') as HTMLElement).innerText
|
28
|
+
const link = '# ' + (copyright.querySelector('.link') as HTMLElement).innerText
|
29
|
+
const license = '# ' + (copyright.querySelector('.license') as HTMLElement).innerText
|
30
30
|
const htmlData = author + '<br>' + link + '<br>' + license + '<br><br>' + window.getSelection().toString().replace(/\r\n/g, '<br>')
|
31
31
|
|
32
32
|
const textData = author + '\n' + link + '\n' + license + '\n\n' + window.getSelection().toString().replace(/\r\n/g, '\n')
|
@@ -68,12 +68,12 @@ export const postBeauty = () => {
|
|
68
68
|
})
|
69
69
|
|
70
70
|
$dom.each('figure.highlight', (element) => {
|
71
|
-
const code_container = element.
|
72
|
-
const caption = element.
|
71
|
+
const code_container = element.querySelector('.code-container') as HTMLElement
|
72
|
+
const caption = element.querySelector('figcaption')
|
73
73
|
|
74
74
|
element.insertAdjacentHTML('beforeend', '<div class="operation"><span class="breakline-btn"><i class="ic i-align-left"></i></span><span class="copy-btn"><i class="ic i-clipboard"></i></span><span class="fullscreen-btn"><i class="ic i-expand"></i></span></div>')
|
75
75
|
|
76
|
-
const copyBtn = element.
|
76
|
+
const copyBtn = element.querySelector('.copy-btn')
|
77
77
|
if (LOCAL.nocopy) {
|
78
78
|
copyBtn.remove()
|
79
79
|
} else {
|
@@ -86,42 +86,42 @@ export const postBeauty = () => {
|
|
86
86
|
})
|
87
87
|
|
88
88
|
clipBoard(code, (result) => {
|
89
|
-
target.
|
89
|
+
target.querySelector('.ic').className = result ? 'ic i-check' : 'ic i-times'
|
90
90
|
target.blur()
|
91
91
|
showtip(LOCAL.copyright)
|
92
92
|
})
|
93
93
|
}, { passive: true })
|
94
94
|
copyBtn.addEventListener('mouseleave', (event) => {
|
95
95
|
setTimeout(() => {
|
96
|
-
event.target.
|
96
|
+
(event.target as HTMLElement).querySelector('.ic').className = 'ic i-clipboard'
|
97
97
|
}, 1000)
|
98
98
|
})
|
99
99
|
}
|
100
100
|
|
101
|
-
const breakBtn = element.
|
101
|
+
const breakBtn = element.querySelector('.breakline-btn')
|
102
102
|
breakBtn.addEventListener('click', (event) => {
|
103
|
-
const target = event.currentTarget
|
103
|
+
const target = event.currentTarget as HTMLElement
|
104
104
|
if (element.hasClass('breakline')) {
|
105
105
|
element.removeClass('breakline')
|
106
|
-
target.
|
106
|
+
target.querySelector('.ic').className = 'ic i-align-left'
|
107
107
|
} else {
|
108
108
|
element.addClass('breakline')
|
109
|
-
target.
|
109
|
+
target.querySelector('.ic').className = 'ic i-align-justify'
|
110
110
|
}
|
111
111
|
})
|
112
112
|
|
113
|
-
const fullscreenBtn = element.
|
113
|
+
const fullscreenBtn = element.querySelector('.fullscreen-btn')
|
114
114
|
const removeFullscreen = () => {
|
115
115
|
element.removeClass('fullscreen')
|
116
116
|
element.scrollTop = 0
|
117
117
|
BODY.removeClass('fullscreen')
|
118
|
-
fullscreenBtn.
|
118
|
+
fullscreenBtn.querySelector('.ic').className = 'ic i-expand'
|
119
119
|
}
|
120
120
|
const fullscreenHandle = () => {
|
121
121
|
if (element.hasClass('fullscreen')) {
|
122
122
|
removeFullscreen()
|
123
123
|
if (code_container && code_container.find('tr').length > 15) {
|
124
|
-
const showBtn = code_container.
|
124
|
+
const showBtn = code_container.querySelector('.show-btn')
|
125
125
|
code_container.style.maxHeight = '300px'
|
126
126
|
showBtn.removeClass('open')
|
127
127
|
}
|
@@ -129,9 +129,9 @@ export const postBeauty = () => {
|
|
129
129
|
} else {
|
130
130
|
element.addClass('fullscreen')
|
131
131
|
BODY.addClass('fullscreen')
|
132
|
-
fullscreenBtn.
|
132
|
+
fullscreenBtn.querySelector('.ic').className = 'ic i-compress'
|
133
133
|
if (code_container && code_container.find('tr').length > 15) {
|
134
|
-
const showBtn = code_container.
|
134
|
+
const showBtn = code_container.querySelector('.show-btn')
|
135
135
|
code_container.style.maxHeight = ''
|
136
136
|
showBtn.addClass('open')
|
137
137
|
}
|
@@ -143,7 +143,7 @@ export const postBeauty = () => {
|
|
143
143
|
if (code_container && code_container.find('tr').length > 15) {
|
144
144
|
code_container.style.maxHeight = '300px'
|
145
145
|
code_container.insertAdjacentHTML('beforeend', '<div class="show-btn"><i class="ic i-angle-down"></i></div>')
|
146
|
-
const showBtn = code_container.
|
146
|
+
const showBtn = code_container.querySelector('.show-btn')
|
147
147
|
|
148
148
|
const hideCode = () => {
|
149
149
|
code_container.style.maxHeight = '300px'
|
@@ -174,7 +174,7 @@ export const postBeauty = () => {
|
|
174
174
|
$dom.each('.reward button', (element) => {
|
175
175
|
element.addEventListener('click', (event) => {
|
176
176
|
event.preventDefault()
|
177
|
-
const qr =
|
177
|
+
const qr = document.getElementById('qr')
|
178
178
|
if (getDisplay(qr) === 'inline-flex') {
|
179
179
|
transition(qr, 0)
|
180
180
|
} else {
|
@@ -12,7 +12,7 @@ export function algoliaSearch (pjax) {
|
|
12
12
|
searchClient: algoliasearch(CONFIG.search.appID, CONFIG.search.apiKey),
|
13
13
|
// TODO 移除弃用函数
|
14
14
|
searchFunction (helper) {
|
15
|
-
const searchInput =
|
15
|
+
const searchInput = document.querySelector('.search-input') as HTMLInputElement
|
16
16
|
if (searchInput.value) {
|
17
17
|
helper.search()
|
18
18
|
}
|
@@ -20,7 +20,7 @@ export function algoliaSearch (pjax) {
|
|
20
20
|
})
|
21
21
|
|
22
22
|
search.on('render', () => {
|
23
|
-
pjax.refresh(
|
23
|
+
pjax.refresh(document.getElementById("search-hits"))
|
24
24
|
})
|
25
25
|
|
26
26
|
// Registering Widgets
|
@@ -105,7 +105,7 @@ export function algoliaSearch (pjax) {
|
|
105
105
|
onPopupClose()
|
106
106
|
}
|
107
107
|
})
|
108
|
-
|
108
|
+
document.querySelector('.close-btn').addEventListener('click', onPopupClose)
|
109
109
|
window.addEventListener('pjax:success', onPopupClose)
|
110
110
|
window.addEventListener('keyup', (event) => {
|
111
111
|
if (event.key === 'Escape') {
|
@@ -10,14 +10,14 @@ export const tabFormat = () => {
|
|
10
10
|
|
11
11
|
const id = element.getAttribute('data-id')
|
12
12
|
const title = element.getAttribute('data-title')
|
13
|
-
let box =
|
13
|
+
let box = document.getElementById(id)
|
14
14
|
if (!box) {
|
15
15
|
box = document.createElement('div')
|
16
16
|
box.className = 'tabs'
|
17
17
|
box.id = id
|
18
18
|
box.innerHTML = '<div class="show-btn"></div>'
|
19
19
|
|
20
|
-
const showBtn = box.
|
20
|
+
const showBtn = box.querySelector('.show-btn')
|
21
21
|
showBtn.addEventListener('click', () => {
|
22
22
|
pageScroll(box)
|
23
23
|
})
|
@@ -28,12 +28,12 @@ export const tabFormat = () => {
|
|
28
28
|
first_tab = false
|
29
29
|
}
|
30
30
|
|
31
|
-
let ul = box.
|
31
|
+
let ul = box.querySelector('.nav ul')
|
32
32
|
if (!ul) {
|
33
33
|
ul = createChild(box, 'div', {
|
34
34
|
className: 'nav',
|
35
35
|
innerHTML: '<ul></ul>'
|
36
|
-
}).
|
36
|
+
}).querySelector('ul')
|
37
37
|
}
|
38
38
|
|
39
39
|
const li = createChild(ul, 'li', {
|
@@ -15,19 +15,19 @@ import {
|
|
15
15
|
import { Loader } from '../globals/thirdparty'
|
16
16
|
import { $dom } from '../library/dom'
|
17
17
|
import { mediaPlayer } from '../player'
|
18
|
-
import {
|
18
|
+
import { createChild } from '../library/proto'
|
19
19
|
|
20
20
|
export default function domInit () {
|
21
21
|
$dom.each('.overview .menu > .item', (el) => {
|
22
|
-
|
22
|
+
siteNav.querySelector('.menu').appendChild(el.cloneNode(true))
|
23
23
|
})
|
24
24
|
|
25
25
|
loadCat.addEventListener('click', Loader.vanish)
|
26
26
|
menuToggle.addEventListener('click', sideBarToggleHandle)
|
27
|
-
|
27
|
+
document.querySelector('.dimmer').addEventListener('click', sideBarToggleHandle)
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
quickBtn.querySelector('.down').addEventListener('click', goToBottomHandle)
|
30
|
+
quickBtn.querySelector('.up').addEventListener('click', backToTopHandle)
|
31
31
|
|
32
32
|
if (!toolBtn) {
|
33
33
|
setToolBtn(createChild(siteHeader, 'div', {
|
@@ -36,10 +36,10 @@ export default function domInit () {
|
|
36
36
|
}))
|
37
37
|
}
|
38
38
|
|
39
|
-
setToolPlayer(toolBtn.
|
40
|
-
setBackToTop(toolBtn.
|
41
|
-
setGoToComment(toolBtn.
|
42
|
-
setShowContents(toolBtn.
|
39
|
+
setToolPlayer(toolBtn.querySelector('.player'))
|
40
|
+
setBackToTop(toolBtn.querySelector('.back-to-top'))
|
41
|
+
setGoToComment(toolBtn.querySelector('.chat'))
|
42
|
+
setShowContents(toolBtn.querySelector('.contents'))
|
43
43
|
|
44
44
|
backToTop.addEventListener('click', backToTopHandle)
|
45
45
|
goToComment.addEventListener('click', goToCommentHandle)
|
@@ -48,7 +48,7 @@ export default function domInit () {
|
|
48
48
|
if (__shokax_player__) {
|
49
49
|
mediaPlayer(toolPlayer)
|
50
50
|
|
51
|
-
|
51
|
+
document.querySelector('main').addEventListener('click', () => {
|
52
52
|
toolPlayer.player.mini()
|
53
53
|
})
|
54
54
|
}
|
@@ -27,7 +27,7 @@ export const pjaxReload = () => {
|
|
27
27
|
menuToggle.removeClass('close')
|
28
28
|
}) // 'transition.slideRightOut'
|
29
29
|
}
|
30
|
-
const mainNode =
|
30
|
+
const mainNode = document.getElementById('main')
|
31
31
|
mainNode.innerHTML = ''
|
32
32
|
mainNode.appendChild(loadCat.lastChild.cloneNode(true))
|
33
33
|
pageScroll(0)
|
@@ -76,29 +76,32 @@ export const siteRefresh = (reload) => {
|
|
76
76
|
postBeauty()
|
77
77
|
})
|
78
78
|
|
79
|
-
const
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
79
|
+
const cpel = document.getElementById('copyright')
|
80
|
+
if (cpel) {
|
81
|
+
const comment = new IntersectionObserver((entries) => {
|
82
|
+
entries.forEach((entry) => {
|
83
|
+
if (entry.isIntersecting) {
|
84
|
+
if (__shokax_waline__) {
|
85
|
+
import('../components/comments').then(({walinePageview, walineComment}) => {
|
86
|
+
walinePageview()
|
87
|
+
walineComment()
|
88
|
+
})
|
89
|
+
}
|
90
|
+
if (__shokax_twikoo__) {
|
91
|
+
import('../components/tcomments').then(({twikooComment}) => {
|
92
|
+
twikooComment()
|
93
|
+
})
|
94
|
+
}
|
95
|
+
comment.disconnect()
|
92
96
|
}
|
93
|
-
|
94
|
-
|
97
|
+
})
|
98
|
+
}, {
|
99
|
+
root: null,
|
100
|
+
threshold: 0.2
|
95
101
|
})
|
96
|
-
}, {
|
97
|
-
root: null,
|
98
|
-
threshold: 0.2
|
99
|
-
})
|
100
102
|
|
101
|
-
|
103
|
+
comment.observe(cpel)
|
104
|
+
}
|
102
105
|
|
103
106
|
lazyLoad()
|
104
107
|
|
@@ -40,7 +40,7 @@ const siteInit = () => {
|
|
40
40
|
themeColorListener()
|
41
41
|
|
42
42
|
if (__shokax_search__) {
|
43
|
-
|
43
|
+
document.querySelector('li.item.search > i').addEventListener('click', () => {
|
44
44
|
if (CONFIG.search === null) { return }
|
45
45
|
|
46
46
|
if (!siteSearch) {
|
@@ -55,12 +55,12 @@ const siteInit = () => {
|
|
55
55
|
})
|
56
56
|
|
57
57
|
// Handle and trigger popup window
|
58
|
-
// search 只有一个,不需要 each
|
58
|
+
// TODO search 只有一个,不需要 each
|
59
59
|
$dom.each('.search', (element) => {
|
60
60
|
element.addEventListener('click', () => {
|
61
61
|
document.body.style.overflow = 'hidden'
|
62
62
|
transition(siteSearch, 'shrinkIn', () => {
|
63
|
-
|
63
|
+
(document.querySelector('.search-input') as HTMLInputElement).focus()
|
64
64
|
}) // transition.shrinkIn
|
65
65
|
})
|
66
66
|
})
|
package/source/js/_app/player.ts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import { CONFIG, originTitle } from './globals/globalVars'
|
2
2
|
import { showtip } from './globals/tools'
|
3
3
|
import { pageScroll } from './library/anime'
|
4
|
-
import { $dom } from './library/dom'
|
5
4
|
import { $storage } from './library/storage'
|
6
5
|
import { tabFormat } from './page/tab'
|
7
6
|
import { createChild, getLeft, getWidth, setDisplay, setWidth } from './library/proto'
|
@@ -68,7 +67,7 @@ export const mediaPlayer = (t, config?) => {
|
|
68
67
|
that.btns[item] = createChild(that.el, 'div', opt)
|
69
68
|
})
|
70
69
|
|
71
|
-
that.btns.volume.bar = that.btns.volume.
|
70
|
+
that.btns.volume.bar = that.btns.volume.querySelector('.bar')
|
72
71
|
},
|
73
72
|
events: {
|
74
73
|
mode (e) {
|
@@ -217,11 +216,11 @@ export const mediaPlayer = (t, config?) => {
|
|
217
216
|
|
218
217
|
preview.el.innerHTML = '<div class="cover"><div class="disc"><img src="' + (current.cover) + '" class="blur" alt="music cover"/></div></div>' +
|
219
218
|
'<div class="info"><h4 class="title">' + current.name + '</h4><span>' + current.artist + '</span>' +
|
220
|
-
'<div class="lrc"></div></div>'
|
219
|
+
'<div class="lrc"></div></div>';
|
221
220
|
|
222
|
-
preview.el.
|
221
|
+
(preview.el as HTMLElement).querySelector('.cover').addEventListener('click', t.player.options.events['play-pause'])
|
223
222
|
|
224
|
-
lyrics.create(preview.el.
|
223
|
+
lyrics.create((preview.el as HTMLElement).querySelector('.lrc'))
|
225
224
|
}
|
226
225
|
}
|
227
226
|
let source
|
@@ -257,7 +256,7 @@ export const mediaPlayer = (t, config?) => {
|
|
257
256
|
if (item.el) { return null }
|
258
257
|
|
259
258
|
const id = 'list-' + t.player._id + '-' + item.group
|
260
|
-
let tab =
|
259
|
+
let tab = document.getElementById(id)
|
261
260
|
if (!tab) {
|
262
261
|
tab = createChild(el, 'div', {
|
263
262
|
id,
|
@@ -270,7 +269,7 @@ export const mediaPlayer = (t, config?) => {
|
|
270
269
|
}
|
271
270
|
}
|
272
271
|
|
273
|
-
item.el = createChild(tab.
|
272
|
+
item.el = createChild(tab.querySelector('ol'), 'li', {
|
274
273
|
title: item.name + ' - ' + item.artist,
|
275
274
|
innerHTML: '<span class="info"><span>' + item.name + '</span><span>' + item.artist + '</span></span>',
|
276
275
|
onclick (event) {
|
@@ -299,13 +298,13 @@ export const mediaPlayer = (t, config?) => {
|
|
299
298
|
},
|
300
299
|
scroll () {
|
301
300
|
const item = this.current()
|
302
|
-
let li = this.el.
|
301
|
+
let li = this.el.querySelector('li.active')
|
303
302
|
li && li.removeClass('active')
|
304
|
-
let tab = this.el.
|
303
|
+
let tab = this.el.querySelector('.tab.active')
|
305
304
|
tab && tab.removeClass('active')
|
306
|
-
li = this.el.
|
305
|
+
li = this.el.querySelectorAll('.nav li')[item.group]
|
307
306
|
li && li.addClass('active')
|
308
|
-
tab = this.el.
|
307
|
+
tab = this.el.querySelectorAll('.tab')[item.group]
|
309
308
|
tab && tab.addClass('active')
|
310
309
|
|
311
310
|
pageScroll(item.el, item.el.offsetTop)
|
@@ -335,9 +334,9 @@ export const mediaPlayer = (t, config?) => {
|
|
335
334
|
innerHTML: (t.player.options.type === 'audio' ? '<div class="preview"></div>' : '') + '<div class="controller"></div><div class="playlist"></div>'
|
336
335
|
}, 'after')
|
337
336
|
|
338
|
-
preview.el = this.el.
|
339
|
-
playlist.el = this.el.
|
340
|
-
controller.el = this.el.
|
337
|
+
preview.el = this.el.querySelector('.preview')
|
338
|
+
playlist.el = this.el.querySelector('.playlist')
|
339
|
+
controller.el = this.el.querySelector('.controller')
|
341
340
|
},
|
342
341
|
hide () {
|
343
342
|
const el = this.el
|