nnbb 0.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/.dockerignore +1 -0
- package/.env.local +2 -0
- package/.eslintrc.json +15 -0
- package/.github/stale.yml +16 -0
- package/.github/workflows/codeql-analysis.yml +73 -0
- package/.github/workflows/docker-ghcr.yaml +59 -0
- package/.prettierrc +9 -0
- package/.vscode/launch.json +28 -0
- package/.vscode/settings.json +6 -0
- package/Dockerfile +38 -0
- package/LICENSE +21 -0
- package/README.md +16 -0
- package/blog.config.js +454 -0
- package/components/Ackee.js +83 -0
- package/components/AdBlockDetect.js +40 -0
- package/components/AlgoliaSearchModal.js +250 -0
- package/components/Artalk.js +30 -0
- package/components/Busuanzi.js +26 -0
- package/components/ChatBase.js +19 -0
- package/components/Collapse.tsx +134 -0
- package/components/Comment.js +161 -0
- package/components/CommonHead.tsx +101 -0
- package/components/CommonScript.js +125 -0
- package/components/CusdisComponent.js +35 -0
- package/components/CustomContextMenu.js +221 -0
- package/components/DebugPanel.js +134 -0
- package/components/DisableCopy.js +21 -0
- package/components/Draggable.js +167 -0
- package/components/Equation.js +31 -0
- package/components/ExternalPlugins.js +75 -0
- package/components/ExternalScript.js +29 -0
- package/components/FacebookMessenger.js +255 -0
- package/components/FacebookPage.js +34 -0
- package/components/Fireworks.js +210 -0
- package/components/FlipCard.js +56 -0
- package/components/FlutteringRibbon.js +322 -0
- package/components/FullScreenButton.js +48 -0
- package/components/Giscus.js +33 -0
- package/components/Gitalk.js +42 -0
- package/components/GoogleAdsense.js +111 -0
- package/components/Gtag.js +18 -0
- package/components/HeroIcons.tsx +321 -0
- package/components/KatexReact.js +53 -0
- package/components/LazyImage.js +95 -0
- package/components/Live2D.js +52 -0
- package/components/Loading.js +20 -0
- package/components/Mark.js +28 -0
- package/components/NProgress.ts +8 -0
- package/components/Nest.js +124 -0
- package/components/NotionIcon.js +20 -0
- package/components/NotionPage.tsx +206 -0
- package/components/Player.js +54 -0
- package/components/PrismMac.js +236 -0
- package/components/QrCode.js +34 -0
- package/components/Ribbon.js +98 -0
- package/components/Sakura.js +192 -0
- package/components/Select.js +40 -0
- package/components/ShareBar.js +29 -0
- package/components/ShareButtons.js +403 -0
- package/components/SideBarDrawer.js +50 -0
- package/components/StarrySky.js +130 -0
- package/components/Tabs.js +64 -0
- package/components/ThemeSwitch.js +67 -0
- package/components/Twikoo.js +27 -0
- package/components/TwikooCommentCount.js +22 -0
- package/components/TwikooCommentCounter.js +78 -0
- package/components/TwikooRecentComments.js +11 -0
- package/components/Utterances.js +35 -0
- package/components/VConsole.js +76 -0
- package/components/ValineComponent.js +59 -0
- package/components/ValineCount.js +6 -0
- package/components/ValinePanel.js +3 -0
- package/components/Vercel.tsx +54 -0
- package/components/WWAds.js +18 -0
- package/components/WalineComponent.js +83 -0
- package/components/WebMention.js +173 -0
- package/components/Webwhiz.js +17 -0
- package/components/WordCount.js +73 -0
- package/hooks/useToggleClickOutSide.ts +32 -0
- package/hooks/useWindowSize.ts +30 -0
- package/lib/algolia.js +108 -0
- package/lib/busuanzi.js +99 -0
- package/lib/cache/cacheManager.ts +49 -0
- package/lib/cache/localFileCache.ts +56 -0
- package/lib/cache/memoryMache.ts +20 -0
- package/lib/cache/mongoDbCache.ts +70 -0
- package/lib/cache/types.ts +5 -0
- package/lib/font.js +46 -0
- package/lib/global.tsx +129 -0
- package/lib/gtag.js +17 -0
- package/lib/mailchimp.js +49 -0
- package/lib/memorize.js +0 -0
- package/lib/mhchem.js +1696 -0
- package/lib/notion/getAllCategories.ts +51 -0
- package/lib/notion/getAllPageIds.ts +51 -0
- package/lib/notion/getAllPosts.js +68 -0
- package/lib/notion/getAllTags.ts +43 -0
- package/lib/notion/getNotionData.ts +340 -0
- package/lib/notion/getPageInfoOfPostPage.ts +58 -0
- package/lib/notion/getPageProperties.ts +203 -0
- package/lib/notion/getPageTableOfContents.ts +107 -0
- package/lib/notion/getPostBlocks.ts +147 -0
- package/lib/notion/mapImage.ts +130 -0
- package/lib/notion/types.ts +125 -0
- package/lib/notion.js +2 -0
- package/lib/robots.txt.js +25 -0
- package/lib/rss.js +63 -0
- package/lib/sitemap.xml.js +67 -0
- package/lib/utils.js +212 -0
- package/next-env.d.ts +5 -0
- package/next-i18next.config.js +7 -0
- package/next-sitemap.config.js +11 -0
- package/next.config.js +124 -0
- package/package.json +92 -0
- package/pages/404.tsx +40 -0
- package/pages/[prefix]/[slug].tsx +123 -0
- package/pages/[prefix]/index.tsx +223 -0
- package/pages/_app.js +59 -0
- package/pages/_document.js +42 -0
- package/pages/api/subscribe.js +22 -0
- package/pages/archive/index.tsx +79 -0
- package/pages/category/[category]/index.tsx +87 -0
- package/pages/category/[category]/page/[page].tsx +103 -0
- package/pages/category/index.tsx +43 -0
- package/pages/index.tsx +88 -0
- package/pages/page/[page].tsx +93 -0
- package/pages/search/[keyword]/index.tsx +162 -0
- package/pages/search/[keyword]/page/[page].tsx +166 -0
- package/pages/search/index.tsx +69 -0
- package/pages/sitemap.xml.js +70 -0
- package/pages/tag/[tag]/index.tsx +73 -0
- package/pages/tag/[tag]/page/[page].tsx +87 -0
- package/pages/tag/index.tsx +42 -0
- package/postcss.config.js +6 -0
- package/public/ads.txt +1 -0
- package/public/avatar.png +0 -0
- package/public/avatar.svg +11 -0
- package/public/bg_image.jpg +0 -0
- package/public/css/all.min.css +9 -0
- package/public/css/custom.css +8 -0
- package/public/css/img-shadow.css +5 -0
- package/public/css/prism-mac-style.css +58 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.svg +9 -0
- package/public/js/cusdis.es.js +107 -0
- package/public/js/custom.js +1 -0
- package/public/locales/en/common.json +44 -0
- package/public/locales/en/menu.json +9 -0
- package/public/locales/en/nav.json +11 -0
- package/public/locales/zh-CN/common.json +44 -0
- package/public/locales/zh-CN/menu.json +9 -0
- package/public/locales/zh-CN/nav.json +9 -0
- package/public/webfonts/fa-brands-400.ttf +0 -0
- package/public/webfonts/fa-brands-400.woff2 +0 -0
- package/public/webfonts/fa-regular-400.ttf +0 -0
- package/public/webfonts/fa-regular-400.woff2 +0 -0
- package/public/webfonts/fa-solid-900.ttf +0 -0
- package/public/webfonts/fa-solid-900.woff2 +0 -0
- package/public/webfonts/fa-v4compatibility.ttf +0 -0
- package/public/webfonts/fa-v4compatibility.woff2 +0 -0
- package/styles/animate.css +503 -0
- package/styles/globals.css +183 -0
- package/styles/notion.css +2064 -0
- package/styles/nprogress.css +84 -0
- package/styles/prism-theme.css +119 -0
- package/styles/utility-patterns.css +79 -0
- package/tailwind.config.js +37 -0
- package/theme/index.ts +6 -0
- package/theme/types/@theme-components.d.ts +29 -0
- package/theme/useLayout.ts +41 -0
- package/theme/utils.ts +108 -0
- package/themes/innocent/package.json +7 -0
- package/themes/innocent/theme.config.js +1 -0
- package/themes/nobelium/components/Announcement.tsx +27 -0
- package/themes/nobelium/components/ArticleFooter.tsx +39 -0
- package/themes/nobelium/components/ArticleInfo.tsx +58 -0
- package/themes/nobelium/components/ArticleLock.tsx +86 -0
- package/themes/nobelium/components/BlogArchiveItem.js +41 -0
- package/themes/nobelium/components/BlogListBar.js +39 -0
- package/themes/nobelium/components/BlogListPage.tsx +67 -0
- package/themes/nobelium/components/BlogListScroll.tsx +96 -0
- package/themes/nobelium/components/BlogPost.tsx +33 -0
- package/themes/nobelium/components/DarkModeButton.tsx +50 -0
- package/themes/nobelium/components/ExampleRecentComments.js +35 -0
- package/themes/nobelium/components/Footer.tsx +35 -0
- package/themes/nobelium/components/JumpToTopButton.tsx +39 -0
- package/themes/nobelium/components/LanguageSwitchButton.tsx +58 -0
- package/themes/nobelium/components/MenuItemCollapse.tsx +92 -0
- package/themes/nobelium/components/MenuItemDrop.tsx +83 -0
- package/themes/nobelium/components/Nav/Nav.module.css +50 -0
- package/themes/nobelium/components/Nav/Nav.tsx +187 -0
- package/themes/nobelium/components/RandomPostButton.tsx +31 -0
- package/themes/nobelium/components/SearchButton.tsx +31 -0
- package/themes/nobelium/components/SearchInput.tsx +94 -0
- package/themes/nobelium/components/SearchNavBar.js +19 -0
- package/themes/nobelium/components/SideBar.js +83 -0
- package/themes/nobelium/components/SvgIcon.js +29 -0
- package/themes/nobelium/components/TagItem.js +13 -0
- package/themes/nobelium/components/Tags.tsx +44 -0
- package/themes/nobelium/components/Title.js +19 -0
- package/themes/nobelium/index.tsx +28 -0
- package/themes/nobelium/layout/LayoutBase.tsx +79 -0
- package/themes/nobelium/pages/Archive.tsx +30 -0
- package/themes/nobelium/pages/Category.tsx +43 -0
- package/themes/nobelium/pages/Home.tsx +22 -0
- package/themes/nobelium/pages/PageNotFound.tsx +15 -0
- package/themes/nobelium/pages/Post.tsx +34 -0
- package/themes/nobelium/pages/PostList.tsx +74 -0
- package/themes/nobelium/pages/Search.tsx +65 -0
- package/themes/nobelium/pages/Tag.tsx +42 -0
- package/themes/nobelium/providers/index.tsx +60 -0
- package/themes/nobelium/stores/index.tsx +42 -0
- package/themes/nobelium/theme.config.ts +17 -0
- package/themes/nobelium/types/index.ts +10 -0
- package/tsconfig.json +29 -0
- package/types/index.ts +1 -0
- package/types/page.ts +102 -0
- package/vercel.json +5 -0
@@ -0,0 +1,210 @@
|
|
1
|
+
/**
|
2
|
+
* https://codepen.io/juliangarnier/pen/gmOwJX
|
3
|
+
* custom by hexo-theme-yun @YunYouJun
|
4
|
+
*/
|
5
|
+
import { useEffect } from 'react'
|
6
|
+
import anime from 'animejs'
|
7
|
+
import BLOG from 'blog.config'
|
8
|
+
|
9
|
+
const Fireworks = () => {
|
10
|
+
useEffect(() => {
|
11
|
+
createFireworks({})
|
12
|
+
}, [])
|
13
|
+
return <canvas id='fireworks' className='fireworks'></canvas>
|
14
|
+
}
|
15
|
+
export default Fireworks
|
16
|
+
|
17
|
+
/**
|
18
|
+
* 创建烟花
|
19
|
+
* @param config
|
20
|
+
*/
|
21
|
+
function createFireworks(config) {
|
22
|
+
const defaultConfig = {
|
23
|
+
colors: BLOG.FIREWORKS_COLOR,
|
24
|
+
numberOfParticules: 20,
|
25
|
+
orbitRadius: {
|
26
|
+
min: 50,
|
27
|
+
max: 100
|
28
|
+
},
|
29
|
+
circleRadius: {
|
30
|
+
min: 10,
|
31
|
+
max: 20
|
32
|
+
},
|
33
|
+
diffuseRadius: {
|
34
|
+
min: 50,
|
35
|
+
max: 100
|
36
|
+
},
|
37
|
+
animeDuration: {
|
38
|
+
min: 900,
|
39
|
+
max: 1500
|
40
|
+
}
|
41
|
+
}
|
42
|
+
config = Object.assign(defaultConfig, config)
|
43
|
+
|
44
|
+
let pointerX = 0
|
45
|
+
let pointerY = 0
|
46
|
+
|
47
|
+
// sky blue
|
48
|
+
const colors = config.colors
|
49
|
+
|
50
|
+
const canvasEl = document.querySelector('.fireworks')
|
51
|
+
const ctx = canvasEl.getContext('2d')
|
52
|
+
|
53
|
+
/**
|
54
|
+
* 设置画布尺寸
|
55
|
+
*/
|
56
|
+
function setCanvasSize(canvasEl) {
|
57
|
+
canvasEl.width = window.innerWidth
|
58
|
+
canvasEl.height = window.innerHeight
|
59
|
+
canvasEl.style.width = `${window.innerWidth}px`
|
60
|
+
canvasEl.style.height = `${window.innerHeight}px`
|
61
|
+
}
|
62
|
+
|
63
|
+
/**
|
64
|
+
* update pointer
|
65
|
+
* @param {TouchEvent} e
|
66
|
+
*/
|
67
|
+
function updateCoords(e) {
|
68
|
+
pointerX =
|
69
|
+
e.clientX ||
|
70
|
+
(e.touches[0] ? e.touches[0].clientX : e.changedTouches[0].clientX)
|
71
|
+
pointerY =
|
72
|
+
e.clientY ||
|
73
|
+
(e.touches[0] ? e.touches[0].clientY : e.changedTouches[0].clientY)
|
74
|
+
}
|
75
|
+
|
76
|
+
function setParticuleDirection(p) {
|
77
|
+
const angle = (anime.random(0, 360) * Math.PI) / 180
|
78
|
+
const value = anime.random(
|
79
|
+
config.diffuseRadius.min,
|
80
|
+
config.diffuseRadius.max
|
81
|
+
)
|
82
|
+
const radius = [-1, 1][anime.random(0, 1)] * value
|
83
|
+
return {
|
84
|
+
x: p.x + radius * Math.cos(angle),
|
85
|
+
y: p.y + radius * Math.sin(angle)
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* 在指定位置创建粒子
|
91
|
+
* @param {number} x
|
92
|
+
* @param {number} y
|
93
|
+
* @returns
|
94
|
+
*/
|
95
|
+
function createParticule(x, y) {
|
96
|
+
const p = {
|
97
|
+
x,
|
98
|
+
y,
|
99
|
+
color: `rgba(${
|
100
|
+
colors[anime.random(0, colors.length - 1)]
|
101
|
+
},${
|
102
|
+
anime.random(0.2, 0.8)
|
103
|
+
})`,
|
104
|
+
radius: anime.random(config.circleRadius.min, config.circleRadius.max),
|
105
|
+
endPos: null,
|
106
|
+
draw() {}
|
107
|
+
}
|
108
|
+
p.endPos = setParticuleDirection(p)
|
109
|
+
p.draw = function() {
|
110
|
+
ctx.beginPath()
|
111
|
+
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true)
|
112
|
+
ctx.fillStyle = p.color
|
113
|
+
ctx.fill()
|
114
|
+
}
|
115
|
+
return p
|
116
|
+
}
|
117
|
+
|
118
|
+
function createCircle(x, y) {
|
119
|
+
const p = {
|
120
|
+
x,
|
121
|
+
y,
|
122
|
+
color: '#000',
|
123
|
+
radius: 0.1,
|
124
|
+
alpha: 0.5,
|
125
|
+
lineWidth: 6,
|
126
|
+
draw() {}
|
127
|
+
}
|
128
|
+
p.draw = function() {
|
129
|
+
ctx.globalAlpha = p.alpha
|
130
|
+
ctx.beginPath()
|
131
|
+
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true)
|
132
|
+
ctx.lineWidth = p.lineWidth
|
133
|
+
ctx.strokeStyle = p.color
|
134
|
+
ctx.stroke()
|
135
|
+
ctx.globalAlpha = 1
|
136
|
+
}
|
137
|
+
return p
|
138
|
+
}
|
139
|
+
|
140
|
+
function renderParticule(anim) {
|
141
|
+
for (let i = 0; i < anim.animatables.length; i++) { anim.animatables[i].target.draw() }
|
142
|
+
}
|
143
|
+
|
144
|
+
function animateParticules(x, y) {
|
145
|
+
const circle = createCircle(x, y)
|
146
|
+
const particules = []
|
147
|
+
for (let i = 0; i < config.numberOfParticules; i++) { particules.push(createParticule(x, y)) }
|
148
|
+
|
149
|
+
anime
|
150
|
+
.timeline()
|
151
|
+
.add({
|
152
|
+
targets: particules,
|
153
|
+
x(p) {
|
154
|
+
return p.endPos.x
|
155
|
+
},
|
156
|
+
y(p) {
|
157
|
+
return p.endPos.y
|
158
|
+
},
|
159
|
+
radius: 0.1,
|
160
|
+
duration: anime.random(
|
161
|
+
config.animeDuration.min,
|
162
|
+
config.animeDuration.max
|
163
|
+
),
|
164
|
+
easing: 'easeOutExpo',
|
165
|
+
update: renderParticule
|
166
|
+
})
|
167
|
+
.add(
|
168
|
+
{
|
169
|
+
targets: circle,
|
170
|
+
radius: anime.random(config.orbitRadius.min, config.orbitRadius.max),
|
171
|
+
lineWidth: 0,
|
172
|
+
alpha: {
|
173
|
+
value: 0,
|
174
|
+
easing: 'linear',
|
175
|
+
duration: anime.random(600, 800)
|
176
|
+
},
|
177
|
+
duration: anime.random(1200, 1800),
|
178
|
+
easing: 'easeOutExpo',
|
179
|
+
update: renderParticule
|
180
|
+
},
|
181
|
+
0
|
182
|
+
)
|
183
|
+
}
|
184
|
+
|
185
|
+
const render = anime({
|
186
|
+
duration: Infinity,
|
187
|
+
update: () => {
|
188
|
+
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height)
|
189
|
+
}
|
190
|
+
})
|
191
|
+
|
192
|
+
document.addEventListener(
|
193
|
+
'mousedown',
|
194
|
+
(e) => {
|
195
|
+
render.play()
|
196
|
+
updateCoords(e)
|
197
|
+
animateParticules(pointerX, pointerY)
|
198
|
+
},
|
199
|
+
false
|
200
|
+
)
|
201
|
+
|
202
|
+
setCanvasSize(canvasEl)
|
203
|
+
window.addEventListener(
|
204
|
+
'resize',
|
205
|
+
() => {
|
206
|
+
setCanvasSize(canvasEl)
|
207
|
+
},
|
208
|
+
false
|
209
|
+
)
|
210
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
|
3
|
+
/**
|
4
|
+
* 翻转组件
|
5
|
+
* @param {*} props
|
6
|
+
* @returns
|
7
|
+
*/
|
8
|
+
export default function FlipCard(props) {
|
9
|
+
const [isFlipped, setIsFlipped] = useState(false)
|
10
|
+
|
11
|
+
function handleCardFlip() {
|
12
|
+
setIsFlipped(!isFlipped)
|
13
|
+
}
|
14
|
+
|
15
|
+
return (
|
16
|
+
<div className={`flip-card ${isFlipped ? 'flipped' : ''}`} >
|
17
|
+
<div className={`flip-card-front ${props.className || ''}`} onMouseEnter={handleCardFlip}>
|
18
|
+
{props.frontContent}
|
19
|
+
</div>
|
20
|
+
<div className={`flip-card-back ${props.className || ''}`} onMouseLeave={handleCardFlip}>
|
21
|
+
{props.backContent}
|
22
|
+
</div>
|
23
|
+
<style jsx>{`
|
24
|
+
.flip-card {
|
25
|
+
width: 100%;
|
26
|
+
height: 100%;
|
27
|
+
display: inline-block;
|
28
|
+
position: relative;
|
29
|
+
transform-style: preserve-3d;
|
30
|
+
transition: transform 0.2s;
|
31
|
+
}
|
32
|
+
|
33
|
+
.flip-card-front,
|
34
|
+
.flip-card-back {
|
35
|
+
position: absolute;
|
36
|
+
width: 100%;
|
37
|
+
height: 100%;
|
38
|
+
backface-visibility: hidden;
|
39
|
+
}
|
40
|
+
|
41
|
+
.flip-card-front {
|
42
|
+
z-index: 2;
|
43
|
+
transform: rotateY(0);
|
44
|
+
}
|
45
|
+
|
46
|
+
.flip-card-back {
|
47
|
+
transform: rotateY(180deg);
|
48
|
+
}
|
49
|
+
|
50
|
+
.flip-card.flipped {
|
51
|
+
transform: rotateY(180deg);
|
52
|
+
}
|
53
|
+
`}</style>
|
54
|
+
</div>
|
55
|
+
)
|
56
|
+
}
|
@@ -0,0 +1,322 @@
|
|
1
|
+
/* eslint-disable */
|
2
|
+
import { useEffect } from 'react'
|
3
|
+
const id = 'canvasFlutteringRibbon'
|
4
|
+
export const FlutteringRibbon = () => {
|
5
|
+
const destroyRibbon = ()=>{
|
6
|
+
const ribbon = document.getElementById(id)
|
7
|
+
if(ribbon && ribbon.parentNode){
|
8
|
+
ribbon.parentNode.removeChild(ribbon)
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
useEffect(() => {
|
13
|
+
createFlutteringRibbon()
|
14
|
+
return () => destroyRibbon()
|
15
|
+
|
16
|
+
}, [])
|
17
|
+
return <></>
|
18
|
+
}
|
19
|
+
|
20
|
+
export default FlutteringRibbon
|
21
|
+
|
22
|
+
|
23
|
+
/**
|
24
|
+
* 创建连接点
|
25
|
+
* @param config
|
26
|
+
*/
|
27
|
+
function createFlutteringRibbon() {
|
28
|
+
'object' == typeof window &&
|
29
|
+
(window.Ribbons = (function () {
|
30
|
+
const t = window,
|
31
|
+
i = document.body,
|
32
|
+
n = document.documentElement
|
33
|
+
var o = function () {
|
34
|
+
if (1 === arguments.length) {
|
35
|
+
if (Array.isArray(arguments[0])) {
|
36
|
+
const t = Math.round(o(0, arguments[0].length - 1))
|
37
|
+
return arguments[0][t]
|
38
|
+
}
|
39
|
+
return o(0, arguments[0])
|
40
|
+
}
|
41
|
+
return 2 === arguments.length
|
42
|
+
? Math.random() * (arguments[1] - arguments[0]) + arguments[0]
|
43
|
+
: 0
|
44
|
+
}
|
45
|
+
const s = function (o) {
|
46
|
+
const s = Math.max(
|
47
|
+
0,
|
48
|
+
t.innerWidth || n.clientWidth || i.clientWidth || 0
|
49
|
+
),
|
50
|
+
e = Math.max(
|
51
|
+
0,
|
52
|
+
t.innerHeight || n.clientHeight || i.clientHeight || 0
|
53
|
+
)
|
54
|
+
return {
|
55
|
+
width: s,
|
56
|
+
height: e,
|
57
|
+
ratio: s / e,
|
58
|
+
centerx: s / 2,
|
59
|
+
centery: e / 2,
|
60
|
+
scrollx:
|
61
|
+
Math.max(0, t.pageXOffset || n.scrollLeft || i.scrollLeft || 0) -
|
62
|
+
(n.clientLeft || 0),
|
63
|
+
scrolly:
|
64
|
+
Math.max(0, t.pageYOffset || n.scrollTop || i.scrollTop || 0) -
|
65
|
+
(n.clientTop || 0)
|
66
|
+
}
|
67
|
+
},
|
68
|
+
e = function (t, i) {
|
69
|
+
;(this.x = 0), (this.y = 0), this.set(t, i)
|
70
|
+
}
|
71
|
+
e.prototype = {
|
72
|
+
constructor: e,
|
73
|
+
set: function (t, i) {
|
74
|
+
;(this.x = t || 0), (this.y = i || 0)
|
75
|
+
},
|
76
|
+
copy: function (t) {
|
77
|
+
return (this.x = t.x || 0), (this.y = t.y || 0), this
|
78
|
+
},
|
79
|
+
multiply: function (t, i) {
|
80
|
+
return (this.x *= t || 1), (this.y *= i || 1), this
|
81
|
+
},
|
82
|
+
divide: function (t, i) {
|
83
|
+
return (this.x /= t || 1), (this.y /= i || 1), this
|
84
|
+
},
|
85
|
+
add: function (t, i) {
|
86
|
+
return (this.x += t || 0), (this.y += i || 0), this
|
87
|
+
},
|
88
|
+
subtract: function (t, i) {
|
89
|
+
return (this.x -= t || 0), (this.y -= i || 0), this
|
90
|
+
},
|
91
|
+
clampX: function (t, i) {
|
92
|
+
return (this.x = Math.max(t, Math.min(this.x, i))), this
|
93
|
+
},
|
94
|
+
clampY: function (t, i) {
|
95
|
+
return (this.y = Math.max(t, Math.min(this.y, i))), this
|
96
|
+
},
|
97
|
+
flipX: function () {
|
98
|
+
return (this.x *= -1), this
|
99
|
+
},
|
100
|
+
flipY: function () {
|
101
|
+
return (this.y *= -1), this
|
102
|
+
}
|
103
|
+
}
|
104
|
+
const h = function (t) {
|
105
|
+
;(this._canvas = null),
|
106
|
+
(this._context = null),
|
107
|
+
(this._sto = null),
|
108
|
+
(this._width = 0),
|
109
|
+
(this._height = 0),
|
110
|
+
(this._scroll = 0),
|
111
|
+
(this._ribbons = []),
|
112
|
+
(this._options = {
|
113
|
+
colorSaturation: '80%',
|
114
|
+
colorBrightness: '60%',
|
115
|
+
colorAlpha: 0.65,
|
116
|
+
colorCycleSpeed: 6,
|
117
|
+
verticalPosition: 'center',
|
118
|
+
horizontalSpeed: 150,
|
119
|
+
ribbonCount: 5,
|
120
|
+
strokeSize: 5,
|
121
|
+
parallaxAmount: -0.5,
|
122
|
+
animateSections: !0
|
123
|
+
}),
|
124
|
+
(this._onDraw = this._onDraw.bind(this)),
|
125
|
+
(this._onResize = this._onResize.bind(this)),
|
126
|
+
(this._onScroll = this._onScroll.bind(this)),
|
127
|
+
this.setOptions(t),
|
128
|
+
this.init()
|
129
|
+
}
|
130
|
+
return (
|
131
|
+
(h.prototype = {
|
132
|
+
constructor: h,
|
133
|
+
setOptions: function (t) {
|
134
|
+
if ('object' == typeof t)
|
135
|
+
for (const i in t)
|
136
|
+
t.hasOwnProperty(i) && (this._options[i] = t[i])
|
137
|
+
},
|
138
|
+
init: function () {
|
139
|
+
try {
|
140
|
+
;(this._canvas = document.createElement('canvas')),
|
141
|
+
(this._canvas.id = id),
|
142
|
+
(this._canvas.style.display = 'block'),
|
143
|
+
(this._canvas.style.position = 'fixed'),
|
144
|
+
(this._canvas.style.margin = '0'),
|
145
|
+
(this._canvas.style.padding = '0'),
|
146
|
+
(this._canvas.style.border = '0'),
|
147
|
+
(this._canvas.style.outline = '0'),
|
148
|
+
(this._canvas.style.left = '0'),
|
149
|
+
(this._canvas.style.top = '0'),
|
150
|
+
(this._canvas.style.width = '100%'),
|
151
|
+
(this._canvas.style.height = '100%'),
|
152
|
+
(this._canvas.style['z-index'] = '0'),
|
153
|
+
(this._canvas.style['pointer-events'] = 'none'),
|
154
|
+
this._onResize(),
|
155
|
+
(this._context = this._canvas.getContext('2d')),
|
156
|
+
this._context.clearRect(0, 0, this._width, this._height),
|
157
|
+
(this._context.globalAlpha = this._options.colorAlpha),
|
158
|
+
window.addEventListener('resize', this._onResize),
|
159
|
+
window.addEventListener('scroll', this._onScroll),
|
160
|
+
document.body.appendChild(this._canvas)
|
161
|
+
} catch (t) {
|
162
|
+
return void console.warn('Canvas Context Error: ' + t.toString())
|
163
|
+
}
|
164
|
+
this._onDraw()
|
165
|
+
},
|
166
|
+
addRibbon: function () {
|
167
|
+
const t = Math.round(o(1, 9)) > 5 ? 'right' : 'left'
|
168
|
+
let i = 1e3
|
169
|
+
const n = 200,
|
170
|
+
s = 0 - n,
|
171
|
+
h = this._width + n
|
172
|
+
let a = 0,
|
173
|
+
r = 0
|
174
|
+
const l = 'right' === t ? s : h
|
175
|
+
let c = Math.round(o(0, this._height))
|
176
|
+
;/^(top|min)$/i.test(this._options.verticalPosition)
|
177
|
+
? (c = 0 + n)
|
178
|
+
: /^(middle|center)$/i.test(this._options.verticalPosition)
|
179
|
+
? (c = this._height / 2)
|
180
|
+
: /^(bottom|max)$/i.test(this._options.verticalPosition) &&
|
181
|
+
(c = this._height - n)
|
182
|
+
const p = [],
|
183
|
+
_ = new e(l, c),
|
184
|
+
d = new e(l, c)
|
185
|
+
let u = null,
|
186
|
+
b = Math.round(o(0, 360)),
|
187
|
+
f = 0
|
188
|
+
for (; !(i <= 0); ) {
|
189
|
+
if (
|
190
|
+
(i--,
|
191
|
+
(a = Math.round(
|
192
|
+
(1 * Math.random() - 0.2) * this._options.horizontalSpeed
|
193
|
+
)),
|
194
|
+
(r = Math.round(
|
195
|
+
(1 * Math.random() - 0.5) * (0.25 * this._height)
|
196
|
+
)),
|
197
|
+
(u = new e()),
|
198
|
+
u.copy(d),
|
199
|
+
'right' === t)
|
200
|
+
) {
|
201
|
+
if ((u.add(a, r), d.x >= h)) break
|
202
|
+
} else if ('left' === t && (u.subtract(a, r), d.x <= s)) break
|
203
|
+
p.push({
|
204
|
+
point1: new e(_.x, _.y),
|
205
|
+
point2: new e(d.x, d.y),
|
206
|
+
point3: u,
|
207
|
+
color: b,
|
208
|
+
delay: f,
|
209
|
+
dir: t,
|
210
|
+
alpha: 0,
|
211
|
+
phase: 0
|
212
|
+
}),
|
213
|
+
_.copy(d),
|
214
|
+
d.copy(u),
|
215
|
+
(f += 4),
|
216
|
+
(b += this._options.colorCycleSpeed)
|
217
|
+
}
|
218
|
+
this._ribbons.push(p)
|
219
|
+
},
|
220
|
+
_drawRibbonSection: function (t) {
|
221
|
+
if (t) {
|
222
|
+
if (t.phase >= 1 && t.alpha <= 0) return !0
|
223
|
+
if (t.delay <= 0) {
|
224
|
+
if (
|
225
|
+
((t.phase += 0.02),
|
226
|
+
(t.alpha = 1 * Math.sin(t.phase)),
|
227
|
+
(t.alpha = t.alpha <= 0 ? 0 : t.alpha),
|
228
|
+
(t.alpha = t.alpha >= 1 ? 1 : t.alpha),
|
229
|
+
this._options.animateSections)
|
230
|
+
) {
|
231
|
+
const i = 0.1 * Math.sin(1 + (t.phase * Math.PI) / 2)
|
232
|
+
'right' === t.dir
|
233
|
+
? (t.point1.add(i, 0),
|
234
|
+
t.point2.add(i, 0),
|
235
|
+
t.point3.add(i, 0))
|
236
|
+
: (t.point1.subtract(i, 0),
|
237
|
+
t.point2.subtract(i, 0),
|
238
|
+
t.point3.subtract(i, 0)),
|
239
|
+
t.point1.add(0, i),
|
240
|
+
t.point2.add(0, i),
|
241
|
+
t.point3.add(0, i)
|
242
|
+
}
|
243
|
+
} else t.delay -= 0.5
|
244
|
+
const i = this._options.colorSaturation,
|
245
|
+
n = this._options.colorBrightness,
|
246
|
+
o =
|
247
|
+
'hsla(' +
|
248
|
+
t.color +
|
249
|
+
', ' +
|
250
|
+
i +
|
251
|
+
', ' +
|
252
|
+
n +
|
253
|
+
', ' +
|
254
|
+
t.alpha +
|
255
|
+
' )'
|
256
|
+
this._context.save(),
|
257
|
+
0 !== this._options.parallaxAmount &&
|
258
|
+
this._context.translate(
|
259
|
+
0,
|
260
|
+
this._scroll * this._options.parallaxAmount
|
261
|
+
),
|
262
|
+
this._context.beginPath(),
|
263
|
+
this._context.moveTo(t.point1.x, t.point1.y),
|
264
|
+
this._context.lineTo(t.point2.x, t.point2.y),
|
265
|
+
this._context.lineTo(t.point3.x, t.point3.y),
|
266
|
+
(this._context.fillStyle = o),
|
267
|
+
this._context.fill(),
|
268
|
+
this._options.strokeSize > 0 &&
|
269
|
+
((this._context.lineWidth = this._options.strokeSize),
|
270
|
+
(this._context.strokeStyle = o),
|
271
|
+
(this._context.lineCap = 'round'),
|
272
|
+
this._context.stroke()),
|
273
|
+
this._context.restore()
|
274
|
+
}
|
275
|
+
return !1
|
276
|
+
},
|
277
|
+
_onDraw: function () {
|
278
|
+
for (let t = 0, i = this._ribbons.length; t < i; ++t)
|
279
|
+
this._ribbons[t] || this._ribbons.splice(t, 1)
|
280
|
+
this._context.clearRect(0, 0, this._width, this._height)
|
281
|
+
for (let t = 0; t < this._ribbons.length; ++t) {
|
282
|
+
const i = this._ribbons[t],
|
283
|
+
n = i.length
|
284
|
+
let o = 0
|
285
|
+
for (let t = 0; t < n; ++t) this._drawRibbonSection(i[t]) && o++
|
286
|
+
o >= n && (this._ribbons[t] = null)
|
287
|
+
}
|
288
|
+
this._ribbons.length < this._options.ribbonCount &&
|
289
|
+
this.addRibbon(),
|
290
|
+
requestAnimationFrame(this._onDraw)
|
291
|
+
},
|
292
|
+
_onResize: function (t) {
|
293
|
+
const i = s(t)
|
294
|
+
;(this._width = i.width),
|
295
|
+
(this._height = i.height),
|
296
|
+
this._canvas &&
|
297
|
+
((this._canvas.width = this._width),
|
298
|
+
(this._canvas.height = this._height),
|
299
|
+
this._context &&
|
300
|
+
(this._context.globalAlpha = this._options.colorAlpha))
|
301
|
+
},
|
302
|
+
_onScroll: function (t) {
|
303
|
+
const i = s(t)
|
304
|
+
this._scroll = i.scrolly
|
305
|
+
}
|
306
|
+
}),
|
307
|
+
h
|
308
|
+
)
|
309
|
+
})())
|
310
|
+
new Ribbons({
|
311
|
+
colorSaturation: '60%',
|
312
|
+
colorBrightness: '50%',
|
313
|
+
colorAlpha: 0.5,
|
314
|
+
colorCycleSpeed: 5,
|
315
|
+
verticalPosition: 'random',
|
316
|
+
horizontalSpeed: 200,
|
317
|
+
ribbonCount: 3,
|
318
|
+
strokeSize: 0,
|
319
|
+
parallaxAmount: -0.2,
|
320
|
+
animateSections: !0
|
321
|
+
})
|
322
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { isBrowser } from '@/lib/utils'
|
2
|
+
import React, { useState } from 'react'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* 全屏按钮
|
6
|
+
* @returns
|
7
|
+
*/
|
8
|
+
const FullScreenButton = () => {
|
9
|
+
const [isFullScreen, setIsFullScreen] = useState(false)
|
10
|
+
|
11
|
+
const handleFullScreenClick = () => {
|
12
|
+
if (!isBrowser) {
|
13
|
+
return
|
14
|
+
}
|
15
|
+
const element = document.documentElement
|
16
|
+
if (!isFullScreen) {
|
17
|
+
if (element.requestFullscreen) {
|
18
|
+
element.requestFullscreen()
|
19
|
+
} else if (element.webkitRequestFullscreen) {
|
20
|
+
element.webkitRequestFullscreen()
|
21
|
+
} else if (element.mozRequestFullScreen) {
|
22
|
+
element.mozRequestFullScreen()
|
23
|
+
} else if (element.msRequestFullscreen) {
|
24
|
+
element.msRequestFullscreen()
|
25
|
+
}
|
26
|
+
setIsFullScreen(true)
|
27
|
+
} else {
|
28
|
+
if (document.exitFullscreen) {
|
29
|
+
document.exitFullscreen()
|
30
|
+
} else if (document.webkitExitFullscreen) {
|
31
|
+
document.webkitExitFullscreen()
|
32
|
+
} else if (document.mozCancelFullScreen) {
|
33
|
+
document.mozCancelFullScreen()
|
34
|
+
} else if (document.msExitFullscreen) {
|
35
|
+
document.msExitFullscreen()
|
36
|
+
}
|
37
|
+
setIsFullScreen(false)
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
return (
|
42
|
+
<button onClick={handleFullScreenClick} className='dark:text-gray-300'>
|
43
|
+
{isFullScreen ? '退出全屏' : <i className="fa-solid fa-expand"></i>}
|
44
|
+
</button>
|
45
|
+
)
|
46
|
+
}
|
47
|
+
|
48
|
+
export default FullScreenButton
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import BLOG from '@/blog.config'
|
2
|
+
import { useGlobal } from '@/lib/global'
|
3
|
+
import Giscus from '@giscus/react'
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Giscus评论 @see https://giscus.app/zh-CN
|
7
|
+
* Contribute by @txs https://github.com/txs/NotionNext/commit/1bf7179d0af21fb433e4c7773504f244998678cb
|
8
|
+
* @returns {JSX.Element}
|
9
|
+
* @constructor
|
10
|
+
*/
|
11
|
+
|
12
|
+
const GiscusComponent = () => {
|
13
|
+
const { isDarkMode } = useGlobal()
|
14
|
+
const theme = isDarkMode ? 'dark' : 'light'
|
15
|
+
|
16
|
+
return (
|
17
|
+
<Giscus
|
18
|
+
repo={BLOG.COMMENT_GISCUS_REPO}
|
19
|
+
repoId={BLOG.COMMENT_GISCUS_REPO_ID}
|
20
|
+
categoryId={BLOG.COMMENT_GISCUS_CATEGORY_ID}
|
21
|
+
mapping={BLOG.COMMENT_GISCUS_MAPPING}
|
22
|
+
reactionsEnabled={BLOG.COMMENT_GISCUS_REACTIONS_ENABLED}
|
23
|
+
emitMetadata={BLOG.COMMENT_GISCUS_EMIT_METADATA}
|
24
|
+
theme={theme}
|
25
|
+
inputPosition={BLOG.COMMENT_GISCUS_INPUT_POSITION}
|
26
|
+
lang={BLOG.COMMENT_GISCUS_LANG}
|
27
|
+
loading={BLOG.COMMENT_GISCUS_LOADING}
|
28
|
+
crossorigin={BLOG.COMMENT_GISCUS_CROSSORIGIN}
|
29
|
+
/>
|
30
|
+
)
|
31
|
+
}
|
32
|
+
|
33
|
+
export default GiscusComponent
|
@@ -0,0 +1,42 @@
|
|
1
|
+
// import 'gitalk/dist/gitalk.css'
|
2
|
+
import BLOG from '@/blog.config'
|
3
|
+
import { loadExternalResource } from '@/lib/utils'
|
4
|
+
import { useEffect } from 'react'
|
5
|
+
// import GitalkComponent from 'gitalk/dist/gitalk-component'
|
6
|
+
|
7
|
+
const Gitalk = ({ frontMatter }) => {
|
8
|
+
// return <GitalkComponent options={{
|
9
|
+
// id: frontMatter.id,
|
10
|
+
// title: frontMatter.title,
|
11
|
+
// clientID: BLOG.COMMENT_GITALK_CLIENT_ID,
|
12
|
+
// clientSecret: BLOG.COMMENT_GITALK_CLIENT_SECRET,
|
13
|
+
// repo: BLOG.COMMENT_GITALK_REPO,
|
14
|
+
// owner: BLOG.COMMENT_GITALK_OWNER,
|
15
|
+
// admin: BLOG.COMMENT_GITALK_ADMIN.split(','),
|
16
|
+
// distractionFreeMode: JSON.parse(BLOG.COMMENT_GITALK_DISTRACTION_FREE_MODE)
|
17
|
+
// }} />
|
18
|
+
const loadGitalk = async() => {
|
19
|
+
await loadExternalResource(BLOG.COMMENT_GITALK_CSS_CDN_URL, 'css')
|
20
|
+
await loadExternalResource(BLOG.COMMENT_GITALK_JS_CDN_URL, 'js')
|
21
|
+
const Gitalk = window.Gitalk
|
22
|
+
|
23
|
+
const gitalk = new Gitalk({
|
24
|
+
clientID: BLOG.COMMENT_GITALK_CLIENT_ID,
|
25
|
+
clientSecret: BLOG.COMMENT_GITALK_CLIENT_SECRET,
|
26
|
+
repo: BLOG.COMMENT_GITALK_REPO,
|
27
|
+
owner: BLOG.COMMENT_GITALK_OWNER,
|
28
|
+
admin: BLOG.COMMENT_GITALK_ADMIN.split(','),
|
29
|
+
id: frontMatter.id, // Ensure uniqueness and length less than 50
|
30
|
+
distractionFreeMode: JSON.parse(BLOG.COMMENT_GITALK_DISTRACTION_FREE_MODE) // Facebook-like distraction free mode
|
31
|
+
})
|
32
|
+
|
33
|
+
gitalk.render('gitalk-container')
|
34
|
+
}
|
35
|
+
useEffect(() => {
|
36
|
+
loadGitalk()
|
37
|
+
}, [])
|
38
|
+
|
39
|
+
return <div id="gitalk-container"></div>
|
40
|
+
}
|
41
|
+
|
42
|
+
export default Gitalk
|