+
diff --git a/themes/simple/components/Catalog.js b/themes/simple/components/Catalog.js
new file mode 100644
index 00000000..b267a8b2
--- /dev/null
+++ b/themes/simple/components/Catalog.js
@@ -0,0 +1,92 @@
+import React, { useRef } from 'react'
+import throttle from 'lodash.throttle'
+import { uuidToId } from 'notion-utils'
+import { useGlobal } from '@/lib/global'
+
+/**
+ * 目录导航组件
+ * @param toc
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const Catalog = ({ post }) => {
+ const { locale } = useGlobal()
+ // 监听滚动事件
+ React.useEffect(() => {
+ window.addEventListener('scroll', actionSectionScrollSpy)
+ actionSectionScrollSpy()
+ return () => {
+ window.removeEventListener('scroll', actionSectionScrollSpy)
+ }
+ }, [])
+
+ // 目录自动滚动
+ const tRef = useRef(null)
+ const tocIds = []
+
+ // 同步选中目录事件
+ const [activeSection, setActiveSection] = React.useState(null)
+ const throttleMs = 100
+ const actionSectionScrollSpy = React.useCallback(throttle(() => {
+ const sections = document.getElementsByClassName('notion-h')
+ let prevBBox = null
+ let currentSectionId = activeSection
+ for (let i = 0; i < sections.length; ++i) {
+ const section = sections[i]
+ if (!section || !(section instanceof Element)) continue
+ if (!currentSectionId) {
+ currentSectionId = section.getAttribute('data-id')
+ }
+ const bbox = section.getBoundingClientRect()
+ const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
+ const offset = Math.max(150, prevHeight / 4)
+ // GetBoundingClientRect returns values relative to viewport
+ if (bbox.top - offset < 0) {
+ currentSectionId = section.getAttribute('data-id')
+ prevBBox = bbox
+ continue
+ }
+ // No need to continue loop, if last element has been detected
+ break
+ }
+ setActiveSection(currentSectionId)
+ const index = tocIds.indexOf(currentSectionId) || 0
+ tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
+ }, throttleMs))
+
+ // 无目录就直接返回空
+ if (!post || !post?.toc || post?.toc?.length < 1) {
+ return <>>
+ }
+ const toc = post.toc
+
+ return
+
{locale.COMMON.TABLE_OF_CONTENTS}
+
+
+
+
+
+
+}
+
+export default Catalog
diff --git a/themes/simple/components/CollapseMenu.js b/themes/simple/components/CollapseMenu.js
index 73b0804b..a59f6a0a 100644
--- a/themes/simple/components/CollapseMenu.js
+++ b/themes/simple/components/CollapseMenu.js
@@ -22,7 +22,7 @@ export const CollapseMenu = ({ link }) => {
}
return <>
-
+
{!hasSubMenu &&
@@ -39,7 +39,7 @@ export const CollapseMenu = ({ link }) => {
{/* 折叠子菜单 */}
{hasSubMenu &&
{link.subMenus.map(sLink => {
- return
+ return
{sLink.title}
diff --git a/themes/simple/components/Footer.js b/themes/simple/components/Footer.js
index f92a43e5..7ebcfc32 100644
--- a/themes/simple/components/Footer.js
+++ b/themes/simple/components/Footer.js
@@ -11,7 +11,7 @@ export const Footer = (props) => {
return currentYear
})()
- return