tona-plugins 1.0.1
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 +48 -0
- package/index.d.ts +32 -0
- package/package.json +51 -0
- package/src/constants/cdn.js +12 -0
- package/src/index.js +30 -0
- package/src/plugins/background/index.js +50 -0
- package/src/plugins/background/index.scss +0 -0
- package/src/plugins/barrage/index.js +104 -0
- package/src/plugins/barrage/index.scss +16 -0
- package/src/plugins/catalog/index.js +212 -0
- package/src/plugins/catalog/index.scss +0 -0
- package/src/plugins/charts/index.js +60 -0
- package/src/plugins/charts/index.scss +16 -0
- package/src/plugins/clickEffects/index.js +137 -0
- package/src/plugins/clickEffects/index.scss +0 -0
- package/src/plugins/codeCopy/index.js +94 -0
- package/src/plugins/codeCopy/index.scss +65 -0
- package/src/plugins/codeHighlight/index.js +35 -0
- package/src/plugins/codeHighlight/index.scss +216 -0
- package/src/plugins/codeHighlight/themes.js +60 -0
- package/src/plugins/codeLang/index.js +51 -0
- package/src/plugins/codeLang/index.scss +28 -0
- package/src/plugins/codeLinenumbers/index.js +33 -0
- package/src/plugins/codeLinenumbers/index.scss +61 -0
- package/src/plugins/codeTrafficLight/index.js +18 -0
- package/src/plugins/codeTrafficLight/index.scss +0 -0
- package/src/plugins/colorMode/index.js +81 -0
- package/src/plugins/colorMode/index.scss +0 -0
- package/src/plugins/commentsAvatars/index.js +85 -0
- package/src/plugins/commentsAvatars/index.scss +3 -0
- package/src/plugins/darkMode/index.js +115 -0
- package/src/plugins/darkMode/index.scss +67 -0
- package/src/plugins/donation/index.js +45 -0
- package/src/plugins/donation/index.scss +63 -0
- package/src/plugins/emoji/index.js +167 -0
- package/src/plugins/emoji/index.scss +155 -0
- package/src/plugins/footer/index.js +35 -0
- package/src/plugins/footer/index.scss +54 -0
- package/src/plugins/imagePreview/index.js +98 -0
- package/src/plugins/imagePreview/index.scss +51 -0
- package/src/plugins/license/index.js +62 -0
- package/src/plugins/license/index.scss +51 -0
- package/src/plugins/live2d/index.js +67 -0
- package/src/plugins/live2d/index.scss +0 -0
- package/src/plugins/live2d/live2d-models.js +21 -0
- package/src/plugins/lock/index.js +77 -0
- package/src/plugins/lock/index.scss +56 -0
- package/src/plugins/musicPlayer/index.js +81 -0
- package/src/plugins/musicPlayer/index.scss +68 -0
- package/src/plugins/notation/index.js +73 -0
- package/src/plugins/notation/index.scss +12 -0
- package/src/plugins/notice/index.js +17 -0
- package/src/plugins/notice/index.scss +46 -0
- package/src/plugins/postBottomImage/index.js +27 -0
- package/src/plugins/postBottomImage/index.scss +26 -0
- package/src/plugins/postMessage/index.js +89 -0
- package/src/plugins/postMessage/index.scss +81 -0
- package/src/plugins/postTopImage/index.js +28 -0
- package/src/plugins/postTopImage/index.scss +29 -0
- package/src/plugins/qrcode/index.js +42 -0
- package/src/plugins/qrcode/index.scss +10 -0
- package/src/plugins/signature/index.js +47 -0
- package/src/plugins/signature/index.scss +18 -0
- package/src/plugins/toast/index.js +49 -0
- package/src/plugins/tools/index.js +251 -0
- package/src/plugins/tools/index.scss +114 -0
- package/src/plugins/webTag/index.js +40 -0
- package/src/plugins/webTag/index.scss +0 -0
- package/src/utils/cnblog.js +282 -0
- package/src/utils/helpers.js +418 -0
- package/src/utils/shared.js +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# plugins
|
|
2
|
+
|
|
3
|
+
Plugins for Tona theme.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i tona
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i tona-plugins
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import { createTheme } from 'tona'
|
|
17
|
+
import { background } from 'tona-plugins'
|
|
18
|
+
|
|
19
|
+
createTheme().use(background)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Configure the default behavior of the plugin in your Theme
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import { createTheme } from 'tona'
|
|
26
|
+
import { background } from 'tona-plugins'
|
|
27
|
+
|
|
28
|
+
createTheme().use(background, {
|
|
29
|
+
// The default configuration of the Theme
|
|
30
|
+
enable: true,
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Configure background plugin
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import { createTheme } from 'tona'
|
|
38
|
+
import { background } from 'tona-plugins'
|
|
39
|
+
|
|
40
|
+
createTheme().use(
|
|
41
|
+
background,
|
|
42
|
+
{},
|
|
43
|
+
{
|
|
44
|
+
// The configuration of the plugin
|
|
45
|
+
opacitySelector: '#sideBar,#mainContent,#footer',
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
```
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
declare module 'tona-plugins' {
|
|
2
|
+
export function musicPlayer(theme: any, devOptions?: any): void
|
|
3
|
+
export function background(theme: any, devOptions?: any): void
|
|
4
|
+
export function barrage(theme: any, devOptions?: any): void
|
|
5
|
+
export function catalog(theme: any, devOptions?: any): void
|
|
6
|
+
export function charts(theme: any, devOptions?: any): void
|
|
7
|
+
export function clickEffects(theme: any, devOptions?: any): void
|
|
8
|
+
export function codeCopy(theme: any, devOptions?: any): void
|
|
9
|
+
export function codeHighlight(theme: any, devOptions?: any): void
|
|
10
|
+
export function codeLang(theme: any, devOptions?: any): void
|
|
11
|
+
export function codeLinenumbers(theme: any, devOptions?: any): void
|
|
12
|
+
export function codeTrafficLight(theme: any, devOptions?: any): void
|
|
13
|
+
export function colorMode(theme: any, devOptions?: any): void
|
|
14
|
+
export function commentsAvatars(theme: any, devOptions?: any): void
|
|
15
|
+
export function darkMode(theme: any, devOptions?: any): void
|
|
16
|
+
export function donation(theme: any, devOptions?: any): void
|
|
17
|
+
export function emoji(theme: any, devOptions?: any): void
|
|
18
|
+
export function footer(theme: any, devOptions?: any): void
|
|
19
|
+
export function imagePreview(theme: any, devOptions?: any): void
|
|
20
|
+
export function license(theme: any, devOptions?: any): void
|
|
21
|
+
export function live2d(theme: any, devOptions?: any): void
|
|
22
|
+
export function lock(theme: any, devOptions?: any): void
|
|
23
|
+
export function notation(theme: any, devOptions?: any): void
|
|
24
|
+
export function notice(theme: any, devOptions?: any): void
|
|
25
|
+
export function postBottomImage(theme: any, devOptions?: any): void
|
|
26
|
+
export function postMessage(theme: any, devOptions?: any): void
|
|
27
|
+
export function postTopImage(theme: any, devOptions?: any): void
|
|
28
|
+
export function qrcode(theme: any, devOptions?: any): void
|
|
29
|
+
export function signature(theme: any, devOptions?: any): void
|
|
30
|
+
export function tools(theme: any, devOptions?: any): void
|
|
31
|
+
export function webTag(theme: any, devOptions?: any): void
|
|
32
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tona-plugins",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "guangzan",
|
|
7
|
+
"url": "https://www.cnblogs.com/guangzan",
|
|
8
|
+
"email": "guangzan1999@outlook.com"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"homepage": "https://github.com/acnblogs/tona#readme",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/acnblogs/tona.git"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/acnblogs/tona/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"博客园"
|
|
21
|
+
],
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./index.d.ts",
|
|
25
|
+
"import": "./src/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"main": "./src/index.js",
|
|
29
|
+
"module": "./src/index.js",
|
|
30
|
+
"types": "./index.d.ts",
|
|
31
|
+
"files": [
|
|
32
|
+
"index.d.ts",
|
|
33
|
+
"src"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"notyf": "^3.10.0",
|
|
37
|
+
"tona-options": "1.0.1",
|
|
38
|
+
"tona": "1.0.1"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.0.3",
|
|
42
|
+
"sass": "^1.97.2",
|
|
43
|
+
"vite": "^7.3.1",
|
|
44
|
+
"vite-plugin-html": "^3.2.2",
|
|
45
|
+
"vite-plugin-singlefile": "^2.3.0",
|
|
46
|
+
"tona-vite": "1.0.1"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"dev": "vite"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const chartJs =
|
|
2
|
+
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js'
|
|
3
|
+
export const mediaZoomJs =
|
|
4
|
+
'https://cdnjs.cloudflare.com/ajax/libs/medium-zoom/1.0.6/medium-zoom.min.js'
|
|
5
|
+
export const APlayerJs =
|
|
6
|
+
'https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.10.1/APlayer.min.js'
|
|
7
|
+
export const APlayerCss =
|
|
8
|
+
'https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.10.1/APlayer.min.css'
|
|
9
|
+
export const notationJs =
|
|
10
|
+
'https://cdnjs.cloudflare.com/ajax/libs/rough-notation/0.5.1/rough-notation.iife.min.js'
|
|
11
|
+
export const typedJs =
|
|
12
|
+
'https://cdnjs.cloudflare.com/ajax/libs/typed.js/2.0.11/typed.min.js'
|
package/src/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export * from './plugins/background'
|
|
2
|
+
export * from './plugins/barrage'
|
|
3
|
+
export * from './plugins/catalog'
|
|
4
|
+
export * from './plugins/charts'
|
|
5
|
+
export * from './plugins/clickEffects'
|
|
6
|
+
export * from './plugins/codeCopy'
|
|
7
|
+
export * from './plugins/codeHighlight'
|
|
8
|
+
export * from './plugins/codeLang'
|
|
9
|
+
export * from './plugins/codeLinenumbers'
|
|
10
|
+
export * from './plugins/codeTrafficLight'
|
|
11
|
+
export * from './plugins/colorMode'
|
|
12
|
+
export * from './plugins/commentsAvatars'
|
|
13
|
+
export * from './plugins/darkMode'
|
|
14
|
+
export * from './plugins/donation'
|
|
15
|
+
export * from './plugins/emoji'
|
|
16
|
+
export * from './plugins/footer'
|
|
17
|
+
export * from './plugins/imagePreview'
|
|
18
|
+
export * from './plugins/license'
|
|
19
|
+
export * from './plugins/live2d'
|
|
20
|
+
export * from './plugins/lock'
|
|
21
|
+
export * from './plugins/musicPlayer'
|
|
22
|
+
export * from './plugins/notation'
|
|
23
|
+
export * from './plugins/notice'
|
|
24
|
+
export * from './plugins/postBottomImage'
|
|
25
|
+
export * from './plugins/postMessage'
|
|
26
|
+
export * from './plugins/postTopImage'
|
|
27
|
+
export * from './plugins/qrcode'
|
|
28
|
+
export * from './plugins/signature'
|
|
29
|
+
export * from './plugins/tools'
|
|
30
|
+
export * from './plugins/webTag'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getBackgroundOptions } from 'tona-options'
|
|
2
|
+
import { isUrl, userAgent } from '../../utils/helpers'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 设置透明度
|
|
6
|
+
* @param {number} opacity 透明度
|
|
7
|
+
*/
|
|
8
|
+
function setOpacity(opacity, opacitySelector) {
|
|
9
|
+
$(opacitySelector).css('opacity', `${opacity}`)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 设置背景
|
|
14
|
+
* @param {string} value
|
|
15
|
+
* @param {boolean} repeat 是否重复图片
|
|
16
|
+
*/
|
|
17
|
+
function setBackground(value, repeat) {
|
|
18
|
+
const type = isUrl(value) ? 'img' : 'color'
|
|
19
|
+
// const type = new RegExp('http').test(value) ? 'img' : 'color'
|
|
20
|
+
if (type === 'color') {
|
|
21
|
+
$('body').css('background-color', `${value}`)
|
|
22
|
+
}
|
|
23
|
+
if (type === 'img') {
|
|
24
|
+
$('body').css('background-image', `url(${value})`)
|
|
25
|
+
if (!repeat) {
|
|
26
|
+
$('body').css({
|
|
27
|
+
'background-repeat': 'no-repeat',
|
|
28
|
+
'background-size': '100% 100%',
|
|
29
|
+
'background-attachment': 'fixed',
|
|
30
|
+
})
|
|
31
|
+
if (userAgent() === 'phone') {
|
|
32
|
+
$('body').css('background-size', 'cover')
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function background(_, devOptions, pluginOptions) {
|
|
39
|
+
const { enable, opacity, value, repeat } = getBackgroundOptions(devOptions)
|
|
40
|
+
|
|
41
|
+
if (!enable) return
|
|
42
|
+
|
|
43
|
+
const { opacitySelector } = {
|
|
44
|
+
opacitySelector: '#main,#navigator',
|
|
45
|
+
...pluginOptions,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setBackground(value, repeat)
|
|
49
|
+
setOpacity(opacity, opacitySelector)
|
|
50
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// 弹幕
|
|
2
|
+
import { getBarragesOptions } from 'tona-options'
|
|
3
|
+
import {
|
|
4
|
+
getClientRect,
|
|
5
|
+
randomColor,
|
|
6
|
+
randomNum,
|
|
7
|
+
sleep,
|
|
8
|
+
} from '../../utils/helpers'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @description 发送弹幕
|
|
12
|
+
* @param {Array} textList 弹幕列表
|
|
13
|
+
*/
|
|
14
|
+
async function shootBarrage(textList, enable, opacity, colors, fontSize) {
|
|
15
|
+
if (!enable) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
if (!document.querySelector('#barrage-wrap')) {
|
|
19
|
+
$('body').append("<div id='barrage-wrap'></div>")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const $wrap = document.querySelector('#barrage-wrap')
|
|
23
|
+
const rect = getClientRect($wrap)
|
|
24
|
+
const wrapWidth = rect.right - rect.left
|
|
25
|
+
const wrapHeight = rect.bottom - rect.top
|
|
26
|
+
|
|
27
|
+
const defaultColors = [
|
|
28
|
+
'#FE0302',
|
|
29
|
+
'#FF7204',
|
|
30
|
+
'#FFAA02',
|
|
31
|
+
'#FFD302',
|
|
32
|
+
'#FFFF00',
|
|
33
|
+
'#A0EE00',
|
|
34
|
+
'#00CD00',
|
|
35
|
+
'#019899',
|
|
36
|
+
'#4266BE',
|
|
37
|
+
'#89D5FF',
|
|
38
|
+
'#CC0273',
|
|
39
|
+
'#CC0273',
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < textList.length; i++) {
|
|
43
|
+
const text = textList[i]
|
|
44
|
+
const $barrage = document.createElement('span')
|
|
45
|
+
const barrageStyle = `left: ${wrapWidth}px;top: ${randomNum(
|
|
46
|
+
wrapHeight - 30,
|
|
47
|
+
1,
|
|
48
|
+
)}px;color: ${randomColor(
|
|
49
|
+
colors.length ? colors : defaultColors,
|
|
50
|
+
)};opacity: ${opacity};font-size: ${fontSize};`
|
|
51
|
+
|
|
52
|
+
$barrage.style.cssText = barrageStyle
|
|
53
|
+
$barrage.textContent = text
|
|
54
|
+
$wrap.appendChild($barrage)
|
|
55
|
+
|
|
56
|
+
const roll = (timer) => {
|
|
57
|
+
const now = Date.now()
|
|
58
|
+
const rect = getClientRect($barrage)
|
|
59
|
+
let left = $barrage.offsetLeft
|
|
60
|
+
|
|
61
|
+
roll.last = roll.last || now
|
|
62
|
+
roll.timer = roll.timer || timer
|
|
63
|
+
|
|
64
|
+
if (left < rect.left - rect.right) {
|
|
65
|
+
$($barrage).remove()
|
|
66
|
+
} else {
|
|
67
|
+
if (now - roll.last >= roll.timer) {
|
|
68
|
+
roll.last = now
|
|
69
|
+
left -= 3
|
|
70
|
+
$barrage.style.left = `${left}px`
|
|
71
|
+
}
|
|
72
|
+
window.requestAnimationFrame(roll)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
roll(randomNum(30, 1))
|
|
77
|
+
|
|
78
|
+
await sleep(1000)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function barrage(_, devOptions) {
|
|
83
|
+
const { enable, opacity, colors, fontSize, barrages } =
|
|
84
|
+
getBarragesOptions(devOptions)
|
|
85
|
+
|
|
86
|
+
if (barrages.length) {
|
|
87
|
+
setTimeout(
|
|
88
|
+
() => shootBarrage(barrages, enable, opacity, colors, fontSize),
|
|
89
|
+
3000,
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// if (page === 'post' && postPageBarrages.length) {
|
|
94
|
+
// setTimeout(() => {
|
|
95
|
+
// shootBarrage(postPageBarrages, enable, opacity, colors, fontSize)
|
|
96
|
+
// }, 3000)
|
|
97
|
+
// }
|
|
98
|
+
|
|
99
|
+
// if (page === 'index' && indexBarrages.length) {
|
|
100
|
+
// setTimeout(() => {
|
|
101
|
+
// shootBarrage(indexBarrages, enable, opacity, colors, fontSize)
|
|
102
|
+
// }, 3000)
|
|
103
|
+
// }
|
|
104
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#barrage-wrap {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 90px;
|
|
4
|
+
width: 100vw;
|
|
5
|
+
height: 60vh;
|
|
6
|
+
text-shadow: 0px 0px 1px #000;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
z-index: 20;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
|
|
11
|
+
span {
|
|
12
|
+
position: absolute;
|
|
13
|
+
white-space: nowrap;
|
|
14
|
+
font-weight: 700;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { getCatalogOptions } from 'tona-options'
|
|
2
|
+
import { getCurrentPage, hasPostTitle } from '../../utils/cnblog'
|
|
3
|
+
import { debounce, getClientRect, userAgent } from '../../utils/helpers'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 构建目录容器
|
|
7
|
+
*/
|
|
8
|
+
function buildCatalogContainer(showTitle) {
|
|
9
|
+
const container = $('<nav id="catalog"></nav>')
|
|
10
|
+
if (showTitle) {
|
|
11
|
+
container.append("<h3 class='catalog-title'>目录</h3>")
|
|
12
|
+
}
|
|
13
|
+
return container
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 构建目录列表
|
|
18
|
+
*/
|
|
19
|
+
function buildCatalogList() {
|
|
20
|
+
const $list = $('<ul>')
|
|
21
|
+
const regExp = /^h[1-6]$/
|
|
22
|
+
|
|
23
|
+
// $('#cnblogs_post_body')
|
|
24
|
+
// .children()
|
|
25
|
+
$('#cnblogs_post_body :header').each(function (index) {
|
|
26
|
+
if (regExp.test(this.tagName.toLowerCase())) {
|
|
27
|
+
const className = `${this.nodeName.toLowerCase()}-list`
|
|
28
|
+
const mathNode = $(this).children('.math.inline')
|
|
29
|
+
|
|
30
|
+
let text
|
|
31
|
+
let id
|
|
32
|
+
|
|
33
|
+
if (mathNode.length) {
|
|
34
|
+
text =
|
|
35
|
+
mathNode.prop('outerHTML') +
|
|
36
|
+
$(this)
|
|
37
|
+
.contents()
|
|
38
|
+
.filter(function () {
|
|
39
|
+
return this.nodeType === 3
|
|
40
|
+
})
|
|
41
|
+
.text()
|
|
42
|
+
} else {
|
|
43
|
+
text = $(this).text()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (text.length === 0) {
|
|
47
|
+
return
|
|
48
|
+
} // 如果标题为空 只有 #
|
|
49
|
+
|
|
50
|
+
if (this.id !== '') {
|
|
51
|
+
id = this.id
|
|
52
|
+
} else {
|
|
53
|
+
id = text.trim()
|
|
54
|
+
$(this).attr('id', id)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const title = $(
|
|
58
|
+
`<li class='${className}'><a href='#${id}'>${text}</a></li>`,
|
|
59
|
+
)
|
|
60
|
+
if (index === 0) {
|
|
61
|
+
title.addClass('catalog-active')
|
|
62
|
+
}
|
|
63
|
+
$list.append(title)
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
return $list
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 构建目录
|
|
71
|
+
* @param {string} selector
|
|
72
|
+
* @param {Function} fn
|
|
73
|
+
*/
|
|
74
|
+
function buildCatalog(selector, fn, showTitle) {
|
|
75
|
+
const container = buildCatalogContainer(showTitle)
|
|
76
|
+
const catalogList = buildCatalogList()
|
|
77
|
+
const catalog = container.append(catalogList)
|
|
78
|
+
$(selector)[fn]($(catalog))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 处理滚动事件
|
|
83
|
+
*/
|
|
84
|
+
function handleScroll(scrollContainer, updateNavigation) {
|
|
85
|
+
$(scrollContainer).scroll(
|
|
86
|
+
debounce(
|
|
87
|
+
() => {
|
|
88
|
+
setActiveTitle()
|
|
89
|
+
autoScroll(scrollContainer, updateNavigation)
|
|
90
|
+
},
|
|
91
|
+
50,
|
|
92
|
+
1000 / 60,
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// TODO: 目录自动滚动
|
|
98
|
+
// https://stackoverflow.com/questions/61282426/fixed-sidebar-scroll-to-anchor-links-when-main-body-is-scrolled?r=SearchResults
|
|
99
|
+
function autoScroll(scrollContainer, updateNavigation) {
|
|
100
|
+
if (!updateNavigation) {
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
const navigation = $('#catalog')
|
|
104
|
+
|
|
105
|
+
if (scrollContainer.scrollY < 100) {
|
|
106
|
+
return navigation.stop().animate(
|
|
107
|
+
{
|
|
108
|
+
scrollTop: 0,
|
|
109
|
+
},
|
|
110
|
+
800,
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
$('#cnblogs_post_body :header').each(function () {
|
|
115
|
+
const sectionName = $(this).attr('id')
|
|
116
|
+
const navigationMatch = $(`a[href="#${sectionName}"]`, navigation)
|
|
117
|
+
|
|
118
|
+
if (
|
|
119
|
+
$(this).offset().top - $(window).height() / 2 < $(window).scrollTop() &&
|
|
120
|
+
$(this).offset().top + $(this).height() - $(window).height() / 2 >
|
|
121
|
+
$(window).scrollTop()
|
|
122
|
+
) {
|
|
123
|
+
const position = navigationMatch.position().top + navigation.scrollTop()
|
|
124
|
+
|
|
125
|
+
// TODO: Use cached selector, exit .each() when first occurrence found
|
|
126
|
+
return navigation.stop().animate(
|
|
127
|
+
{
|
|
128
|
+
scrollTop: position,
|
|
129
|
+
},
|
|
130
|
+
800,
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 标题动态高亮
|
|
138
|
+
*/
|
|
139
|
+
function setActiveTitle() {
|
|
140
|
+
for (let i = $('#catalog ul li').length - 1; i >= 0; i--) {
|
|
141
|
+
const titleId = $($('#catalog ul li')[i])
|
|
142
|
+
.find('a')
|
|
143
|
+
.attr('href')
|
|
144
|
+
.replace(/#/g, '')
|
|
145
|
+
const postTitle = document.querySelector(
|
|
146
|
+
`#cnblogs_post_body [id='${titleId}']`,
|
|
147
|
+
)
|
|
148
|
+
if (getClientRect(postTitle).top <= 100) {
|
|
149
|
+
if ($($('#catalog ul li')[i]).hasClass('catalog-active')) {
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
$($('#catalog ul li')[i]).addClass('catalog-active')
|
|
153
|
+
$($('#catalog ul li')[i]).siblings().removeClass('catalog-active')
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 目录显示隐藏
|
|
161
|
+
*/
|
|
162
|
+
function toggle() {
|
|
163
|
+
$('.catalog-title').click(() => {
|
|
164
|
+
$('#catalog ul').toggle('fast', 'linear', function () {
|
|
165
|
+
$(this).css('display') === 'none'
|
|
166
|
+
? $('.catalog-title').removeClass('is-active')
|
|
167
|
+
: $('.catalog-title').addClass('is-active')
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 设置滚动条
|
|
174
|
+
* @param {*} showScrollbar
|
|
175
|
+
*/
|
|
176
|
+
function setScrollbar(showScrollbar) {
|
|
177
|
+
if (!showScrollbar) {
|
|
178
|
+
$('#catalog').css({
|
|
179
|
+
overflow: 'hidden',
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function catalog(_, devOptions, pluginOptions = {}) {
|
|
185
|
+
const extraOptions = {
|
|
186
|
+
mountedNode: 'body',
|
|
187
|
+
fn: 'append',
|
|
188
|
+
scrollContainer: window,
|
|
189
|
+
updateNavigation: false,
|
|
190
|
+
showTitle: true,
|
|
191
|
+
showScrollbar: true,
|
|
192
|
+
}
|
|
193
|
+
$.extend(true, extraOptions, pluginOptions)
|
|
194
|
+
|
|
195
|
+
const { enable } = getCatalogOptions(devOptions)
|
|
196
|
+
|
|
197
|
+
if (
|
|
198
|
+
enable &&
|
|
199
|
+
hasPostTitle() &&
|
|
200
|
+
getCurrentPage() === 'post' &&
|
|
201
|
+
userAgent() === 'pc'
|
|
202
|
+
) {
|
|
203
|
+
buildCatalog(
|
|
204
|
+
extraOptions.mountedNode,
|
|
205
|
+
extraOptions.fn,
|
|
206
|
+
extraOptions.showTitle,
|
|
207
|
+
)
|
|
208
|
+
handleScroll(extraOptions.scrollContainer, extraOptions.updateNavigation)
|
|
209
|
+
toggle()
|
|
210
|
+
setScrollbar(extraOptions.showScrollbar)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { getChartsOptions } from 'tona-options'
|
|
2
|
+
import { chartJs } from '../../constants/cdn'
|
|
3
|
+
import { loadScript } from '../../utils/helpers'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 构建图表容器
|
|
7
|
+
*/
|
|
8
|
+
function createChartContainer(mountedNode) {
|
|
9
|
+
const container = $('<div id="chart"></div>')
|
|
10
|
+
const el = '<canvas id="myChart"></canvas>'
|
|
11
|
+
container.append(el)
|
|
12
|
+
$(mountedNode).append(container)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function createChart(labels, datasets) {
|
|
16
|
+
const _Chart = window.Chart
|
|
17
|
+
|
|
18
|
+
_Chart.defaults.color = '#999'
|
|
19
|
+
|
|
20
|
+
const config = {
|
|
21
|
+
type: 'radar',
|
|
22
|
+
data: {
|
|
23
|
+
labels,
|
|
24
|
+
datasets,
|
|
25
|
+
},
|
|
26
|
+
options: {
|
|
27
|
+
elements: {
|
|
28
|
+
line: {
|
|
29
|
+
borderWidth: 1,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
plugins: {
|
|
33
|
+
// legend: {
|
|
34
|
+
// labels: {
|
|
35
|
+
// color: '#f00',
|
|
36
|
+
// },
|
|
37
|
+
// },
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
// eslint-disable-next-line no-new
|
|
42
|
+
new _Chart(document.getElementById('myChart'), config)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function charts(_, devOptions, pluginOptions) {
|
|
46
|
+
const { enable, labels, datasets } = getChartsOptions(devOptions)
|
|
47
|
+
if (!enable) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { mountedNode } = {
|
|
52
|
+
mountedNode: '#sidebar_news',
|
|
53
|
+
...pluginOptions,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
loadScript(chartJs, () => {
|
|
57
|
+
createChartContainer(mountedNode)
|
|
58
|
+
createChart(labels, datasets)
|
|
59
|
+
})
|
|
60
|
+
}
|