diff --git a/pages/[prefix]/index.js b/pages/[prefix]/index.js index 0f038881..cd407348 100644 --- a/pages/[prefix]/index.js +++ b/pages/[prefix]/index.js @@ -18,6 +18,7 @@ import { useEffect, useState } from 'react' */ const Slug = props => { const { post } = props + const router = useRouter() // 文章锁🔐 const [lock, setLock] = useState(post?.password && post?.password !== '') @@ -27,9 +28,14 @@ const Slug = props => { * @param {*} result */ const validPassword = passInput => { - const encrypt = md5(post.slug + passInput) - if (passInput && encrypt === post.password) { + if (!post) { + return false + } + const encrypt = md5(post?.slug + passInput) + if (passInput && encrypt === post?.password) { setLock(false) + // 输入密码存入localStorage,下次自动提交 + localStorage.setItem('password_' + router.asPath, passInput) return true } return false @@ -49,8 +55,28 @@ const Slug = props => { post.toc = getPageTableOfContents(post, post.blockMap) } } + + // 从localStorage中读取上次记录 自动提交密码 + const passInput = localStorage.getItem('password_' + router.asPath) + if (passInput) { + validPassword(passInput) + } }, [post]) + // 文章加载 + useEffect(() => { + if (lock) { + return + } + // 文章解锁后生成目录与内容 + if (post?.blockMap?.block) { + post.content = Object.keys(post.blockMap.block).filter( + key => post.blockMap.block[key]?.value?.parent_id === post.id + ) + post.toc = getPageTableOfContents(post, post.blockMap) + } + }, [post, lock]) + props = { ...props, lock, setLock, validPassword } // 根据页面路径加载不同Layout文件 const Layout = getLayoutByTheme({ diff --git a/themes/gitbook/components/ArticleLock.js b/themes/gitbook/components/ArticleLock.js index 03d11d1a..98d3cb89 100644 --- a/themes/gitbook/components/ArticleLock.js +++ b/themes/gitbook/components/ArticleLock.js @@ -20,7 +20,6 @@ export const ArticleLock = props => { */ const submitPassword = () => { const p = document.getElementById('password') - // 验证失败提示 if (!validPassword(p?.value)) { const tips = document.getElementById('tips') @@ -28,23 +27,12 @@ export const ArticleLock = props => { tips.innerHTML = '' tips.innerHTML = `
${locale.COMMON.PASSWORD_ERROR}
` } - } else { - // 输入密码存入localStorage,下次自动提交 - localStorage.setItem('password_' + router.asPath, p?.value) } } useEffect(() => { // 选中密码输入框并将其聚焦 passwordInputRef.current.focus() - - // 从localStorage中读取上次记录 自动提交密码 - const p = localStorage.getItem('password_' + router.asPath) - console.log('pp', p, document.getElementById('password')) - if (p) { - document.getElementById('password').value = p - submitPassword() - } }, [router]) return ( diff --git a/themes/gitbook/components/Catalog.js b/themes/gitbook/components/Catalog.js index cf8e606f..df6cb74f 100644 --- a/themes/gitbook/components/Catalog.js +++ b/themes/gitbook/components/Catalog.js @@ -1,7 +1,7 @@ -import { useCallback, useEffect, useState } from 'react' +import { isBrowser } from '@/lib/utils' import throttle from 'lodash.throttle' import { uuidToId } from 'notion-utils' -import { isBrowser } from '@/lib/utils' +import { useCallback, useEffect, useState } from 'react' /** * 目录导航组件 @@ -24,66 +24,78 @@ const Catalog = ({ post }) => { }, [post]) const throttleMs = 200 - const actionSectionScrollSpy = useCallback(throttle(() => { - const sections = document.getElementsByClassName('notion-h') - let prevBBox = null - let currentSectionId = null - 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 actionSectionScrollSpy = useCallback( + throttle(() => { + const sections = document.getElementsByClassName('notion-h') + let prevBBox = null + let currentSectionId = null + 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 } - 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 + setActiveSection(currentSectionId) + const tocIds = post?.toc?.map(t => uuidToId(t.id)) || [] + const index = tocIds.indexOf(currentSectionId) || 0 + if (isBrowser && tocIds?.length > 0) { + for (const tocWrapper of document?.getElementsByClassName( + 'toc-wrapper' + )) { + tocWrapper?.scrollTo({ top: 28 * index, behavior: 'smooth' }) + } } - // No need to continue loop, if last element has been detected - break - } - setActiveSection(currentSectionId) - const tocIds = post?.toc?.map((t) => uuidToId(t.id)) || [] - const index = tocIds.indexOf(currentSectionId) || 0 - if (isBrowser && tocIds?.length > 0) { - for (const tocWrapper of document?.getElementsByClassName('toc-wrapper')) { - tocWrapper?.scrollTo({ top: 28 * index, behavior: 'smooth' }) - } - } - }, throttleMs)) + }, throttleMs) + ) // 无目录就直接返回空 - if (!toc || toc.length < 1) { - return null + if (!toc || toc?.length < 1) { + return <> } - return <> -
- -
- + console.log('渲染toc', toc) + + return ( + <> +
+ +
+ + ) } export default Catalog