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.
Files changed (218) hide show
  1. package/.dockerignore +1 -0
  2. package/.env.local +2 -0
  3. package/.eslintrc.json +15 -0
  4. package/.github/stale.yml +16 -0
  5. package/.github/workflows/codeql-analysis.yml +73 -0
  6. package/.github/workflows/docker-ghcr.yaml +59 -0
  7. package/.prettierrc +9 -0
  8. package/.vscode/launch.json +28 -0
  9. package/.vscode/settings.json +6 -0
  10. package/Dockerfile +38 -0
  11. package/LICENSE +21 -0
  12. package/README.md +16 -0
  13. package/blog.config.js +454 -0
  14. package/components/Ackee.js +83 -0
  15. package/components/AdBlockDetect.js +40 -0
  16. package/components/AlgoliaSearchModal.js +250 -0
  17. package/components/Artalk.js +30 -0
  18. package/components/Busuanzi.js +26 -0
  19. package/components/ChatBase.js +19 -0
  20. package/components/Collapse.tsx +134 -0
  21. package/components/Comment.js +161 -0
  22. package/components/CommonHead.tsx +101 -0
  23. package/components/CommonScript.js +125 -0
  24. package/components/CusdisComponent.js +35 -0
  25. package/components/CustomContextMenu.js +221 -0
  26. package/components/DebugPanel.js +134 -0
  27. package/components/DisableCopy.js +21 -0
  28. package/components/Draggable.js +167 -0
  29. package/components/Equation.js +31 -0
  30. package/components/ExternalPlugins.js +75 -0
  31. package/components/ExternalScript.js +29 -0
  32. package/components/FacebookMessenger.js +255 -0
  33. package/components/FacebookPage.js +34 -0
  34. package/components/Fireworks.js +210 -0
  35. package/components/FlipCard.js +56 -0
  36. package/components/FlutteringRibbon.js +322 -0
  37. package/components/FullScreenButton.js +48 -0
  38. package/components/Giscus.js +33 -0
  39. package/components/Gitalk.js +42 -0
  40. package/components/GoogleAdsense.js +111 -0
  41. package/components/Gtag.js +18 -0
  42. package/components/HeroIcons.tsx +321 -0
  43. package/components/KatexReact.js +53 -0
  44. package/components/LazyImage.js +95 -0
  45. package/components/Live2D.js +52 -0
  46. package/components/Loading.js +20 -0
  47. package/components/Mark.js +28 -0
  48. package/components/NProgress.ts +8 -0
  49. package/components/Nest.js +124 -0
  50. package/components/NotionIcon.js +20 -0
  51. package/components/NotionPage.tsx +206 -0
  52. package/components/Player.js +54 -0
  53. package/components/PrismMac.js +236 -0
  54. package/components/QrCode.js +34 -0
  55. package/components/Ribbon.js +98 -0
  56. package/components/Sakura.js +192 -0
  57. package/components/Select.js +40 -0
  58. package/components/ShareBar.js +29 -0
  59. package/components/ShareButtons.js +403 -0
  60. package/components/SideBarDrawer.js +50 -0
  61. package/components/StarrySky.js +130 -0
  62. package/components/Tabs.js +64 -0
  63. package/components/ThemeSwitch.js +67 -0
  64. package/components/Twikoo.js +27 -0
  65. package/components/TwikooCommentCount.js +22 -0
  66. package/components/TwikooCommentCounter.js +78 -0
  67. package/components/TwikooRecentComments.js +11 -0
  68. package/components/Utterances.js +35 -0
  69. package/components/VConsole.js +76 -0
  70. package/components/ValineComponent.js +59 -0
  71. package/components/ValineCount.js +6 -0
  72. package/components/ValinePanel.js +3 -0
  73. package/components/Vercel.tsx +54 -0
  74. package/components/WWAds.js +18 -0
  75. package/components/WalineComponent.js +83 -0
  76. package/components/WebMention.js +173 -0
  77. package/components/Webwhiz.js +17 -0
  78. package/components/WordCount.js +73 -0
  79. package/hooks/useToggleClickOutSide.ts +32 -0
  80. package/hooks/useWindowSize.ts +30 -0
  81. package/lib/algolia.js +108 -0
  82. package/lib/busuanzi.js +99 -0
  83. package/lib/cache/cacheManager.ts +49 -0
  84. package/lib/cache/localFileCache.ts +56 -0
  85. package/lib/cache/memoryMache.ts +20 -0
  86. package/lib/cache/mongoDbCache.ts +70 -0
  87. package/lib/cache/types.ts +5 -0
  88. package/lib/font.js +46 -0
  89. package/lib/global.tsx +129 -0
  90. package/lib/gtag.js +17 -0
  91. package/lib/mailchimp.js +49 -0
  92. package/lib/memorize.js +0 -0
  93. package/lib/mhchem.js +1696 -0
  94. package/lib/notion/getAllCategories.ts +51 -0
  95. package/lib/notion/getAllPageIds.ts +51 -0
  96. package/lib/notion/getAllPosts.js +68 -0
  97. package/lib/notion/getAllTags.ts +43 -0
  98. package/lib/notion/getNotionData.ts +340 -0
  99. package/lib/notion/getPageInfoOfPostPage.ts +58 -0
  100. package/lib/notion/getPageProperties.ts +203 -0
  101. package/lib/notion/getPageTableOfContents.ts +107 -0
  102. package/lib/notion/getPostBlocks.ts +147 -0
  103. package/lib/notion/mapImage.ts +130 -0
  104. package/lib/notion/types.ts +125 -0
  105. package/lib/notion.js +2 -0
  106. package/lib/robots.txt.js +25 -0
  107. package/lib/rss.js +63 -0
  108. package/lib/sitemap.xml.js +67 -0
  109. package/lib/utils.js +212 -0
  110. package/next-env.d.ts +5 -0
  111. package/next-i18next.config.js +7 -0
  112. package/next-sitemap.config.js +11 -0
  113. package/next.config.js +124 -0
  114. package/package.json +92 -0
  115. package/pages/404.tsx +40 -0
  116. package/pages/[prefix]/[slug].tsx +123 -0
  117. package/pages/[prefix]/index.tsx +223 -0
  118. package/pages/_app.js +59 -0
  119. package/pages/_document.js +42 -0
  120. package/pages/api/subscribe.js +22 -0
  121. package/pages/archive/index.tsx +79 -0
  122. package/pages/category/[category]/index.tsx +87 -0
  123. package/pages/category/[category]/page/[page].tsx +103 -0
  124. package/pages/category/index.tsx +43 -0
  125. package/pages/index.tsx +88 -0
  126. package/pages/page/[page].tsx +93 -0
  127. package/pages/search/[keyword]/index.tsx +162 -0
  128. package/pages/search/[keyword]/page/[page].tsx +166 -0
  129. package/pages/search/index.tsx +69 -0
  130. package/pages/sitemap.xml.js +70 -0
  131. package/pages/tag/[tag]/index.tsx +73 -0
  132. package/pages/tag/[tag]/page/[page].tsx +87 -0
  133. package/pages/tag/index.tsx +42 -0
  134. package/postcss.config.js +6 -0
  135. package/public/ads.txt +1 -0
  136. package/public/avatar.png +0 -0
  137. package/public/avatar.svg +11 -0
  138. package/public/bg_image.jpg +0 -0
  139. package/public/css/all.min.css +9 -0
  140. package/public/css/custom.css +8 -0
  141. package/public/css/img-shadow.css +5 -0
  142. package/public/css/prism-mac-style.css +58 -0
  143. package/public/favicon.ico +0 -0
  144. package/public/favicon.svg +9 -0
  145. package/public/js/cusdis.es.js +107 -0
  146. package/public/js/custom.js +1 -0
  147. package/public/locales/en/common.json +44 -0
  148. package/public/locales/en/menu.json +9 -0
  149. package/public/locales/en/nav.json +11 -0
  150. package/public/locales/zh-CN/common.json +44 -0
  151. package/public/locales/zh-CN/menu.json +9 -0
  152. package/public/locales/zh-CN/nav.json +9 -0
  153. package/public/webfonts/fa-brands-400.ttf +0 -0
  154. package/public/webfonts/fa-brands-400.woff2 +0 -0
  155. package/public/webfonts/fa-regular-400.ttf +0 -0
  156. package/public/webfonts/fa-regular-400.woff2 +0 -0
  157. package/public/webfonts/fa-solid-900.ttf +0 -0
  158. package/public/webfonts/fa-solid-900.woff2 +0 -0
  159. package/public/webfonts/fa-v4compatibility.ttf +0 -0
  160. package/public/webfonts/fa-v4compatibility.woff2 +0 -0
  161. package/styles/animate.css +503 -0
  162. package/styles/globals.css +183 -0
  163. package/styles/notion.css +2064 -0
  164. package/styles/nprogress.css +84 -0
  165. package/styles/prism-theme.css +119 -0
  166. package/styles/utility-patterns.css +79 -0
  167. package/tailwind.config.js +37 -0
  168. package/theme/index.ts +6 -0
  169. package/theme/types/@theme-components.d.ts +29 -0
  170. package/theme/useLayout.ts +41 -0
  171. package/theme/utils.ts +108 -0
  172. package/themes/innocent/package.json +7 -0
  173. package/themes/innocent/theme.config.js +1 -0
  174. package/themes/nobelium/components/Announcement.tsx +27 -0
  175. package/themes/nobelium/components/ArticleFooter.tsx +39 -0
  176. package/themes/nobelium/components/ArticleInfo.tsx +58 -0
  177. package/themes/nobelium/components/ArticleLock.tsx +86 -0
  178. package/themes/nobelium/components/BlogArchiveItem.js +41 -0
  179. package/themes/nobelium/components/BlogListBar.js +39 -0
  180. package/themes/nobelium/components/BlogListPage.tsx +67 -0
  181. package/themes/nobelium/components/BlogListScroll.tsx +96 -0
  182. package/themes/nobelium/components/BlogPost.tsx +33 -0
  183. package/themes/nobelium/components/DarkModeButton.tsx +50 -0
  184. package/themes/nobelium/components/ExampleRecentComments.js +35 -0
  185. package/themes/nobelium/components/Footer.tsx +35 -0
  186. package/themes/nobelium/components/JumpToTopButton.tsx +39 -0
  187. package/themes/nobelium/components/LanguageSwitchButton.tsx +58 -0
  188. package/themes/nobelium/components/MenuItemCollapse.tsx +92 -0
  189. package/themes/nobelium/components/MenuItemDrop.tsx +83 -0
  190. package/themes/nobelium/components/Nav/Nav.module.css +50 -0
  191. package/themes/nobelium/components/Nav/Nav.tsx +187 -0
  192. package/themes/nobelium/components/RandomPostButton.tsx +31 -0
  193. package/themes/nobelium/components/SearchButton.tsx +31 -0
  194. package/themes/nobelium/components/SearchInput.tsx +94 -0
  195. package/themes/nobelium/components/SearchNavBar.js +19 -0
  196. package/themes/nobelium/components/SideBar.js +83 -0
  197. package/themes/nobelium/components/SvgIcon.js +29 -0
  198. package/themes/nobelium/components/TagItem.js +13 -0
  199. package/themes/nobelium/components/Tags.tsx +44 -0
  200. package/themes/nobelium/components/Title.js +19 -0
  201. package/themes/nobelium/index.tsx +28 -0
  202. package/themes/nobelium/layout/LayoutBase.tsx +79 -0
  203. package/themes/nobelium/pages/Archive.tsx +30 -0
  204. package/themes/nobelium/pages/Category.tsx +43 -0
  205. package/themes/nobelium/pages/Home.tsx +22 -0
  206. package/themes/nobelium/pages/PageNotFound.tsx +15 -0
  207. package/themes/nobelium/pages/Post.tsx +34 -0
  208. package/themes/nobelium/pages/PostList.tsx +74 -0
  209. package/themes/nobelium/pages/Search.tsx +65 -0
  210. package/themes/nobelium/pages/Tag.tsx +42 -0
  211. package/themes/nobelium/providers/index.tsx +60 -0
  212. package/themes/nobelium/stores/index.tsx +42 -0
  213. package/themes/nobelium/theme.config.ts +17 -0
  214. package/themes/nobelium/types/index.ts +10 -0
  215. package/tsconfig.json +29 -0
  216. package/types/index.ts +1 -0
  217. package/types/page.ts +102 -0
  218. 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