From ee2872d72dea371a499f7f772d401d08001b04bb Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Fri, 23 Jun 2023 10:41:43 +0800 Subject: [PATCH 01/12] =?UTF-8?q?gitbook=20=E4=B8=BB=E9=A2=98=E6=A1=86?= =?UTF-8?q?=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- themes/gitbook/Layout404.js | 9 ++ themes/gitbook/LayoutArchive.js | 49 ++++++++ themes/gitbook/LayoutBase.js | 93 +++++++++++++++ themes/gitbook/LayoutCategory.js | 15 +++ themes/gitbook/LayoutCategoryIndex.js | 34 ++++++ themes/gitbook/LayoutIndex.js | 12 ++ themes/gitbook/LayoutPage.js | 10 ++ themes/gitbook/LayoutSearch.js | 53 +++++++++ themes/gitbook/LayoutSlug.js | 97 ++++++++++++++++ themes/gitbook/LayoutTag.js | 15 +++ themes/gitbook/LayoutTagIndex.js | 29 +++++ themes/gitbook/components/ArticleAround.js | 32 ++++++ themes/gitbook/components/ArticleLock.js | 53 +++++++++ themes/gitbook/components/BlogPostCard.js | 83 ++++++++++++++ .../gitbook/components/BlogPostListEmpty.js | 12 ++ themes/gitbook/components/BlogPostListPage.js | 34 ++++++ .../gitbook/components/BlogPostListScroll.js | 106 ++++++++++++++++++ themes/gitbook/components/BottomMenuBar.js | 36 ++++++ themes/gitbook/components/Card.js | 9 ++ themes/gitbook/components/Catalog.js | 91 +++++++++++++++ themes/gitbook/components/CategoryGroup.js | 19 ++++ themes/gitbook/components/CategoryItem.js | 18 +++ themes/gitbook/components/Footer.js | 35 ++++++ themes/gitbook/components/InfoCard.js | 21 ++++ themes/gitbook/components/JumpToTopButton.js | 26 +++++ themes/gitbook/components/LeftMenuBar.js | 16 +++ themes/gitbook/components/LogoBar.js | 12 ++ themes/gitbook/components/MenuBarMobile.js | 39 +++++++ themes/gitbook/components/MenuItemCollapse.js | 62 ++++++++++ themes/gitbook/components/MenuItemDrop.js | 50 +++++++++ .../components/MenuItemMobileNormal.js | 27 +++++ themes/gitbook/components/MenuItemPCNormal.js | 24 ++++ themes/gitbook/components/PaginationSimple.js | 54 +++++++++ themes/gitbook/components/Progress.js | 44 ++++++++ themes/gitbook/components/RevolverMaps.js | 36 ++++++ themes/gitbook/components/SearchInput.js | 86 ++++++++++++++ themes/gitbook/components/SocialButton.js | 37 ++++++ themes/gitbook/components/TagGroups.js | 27 +++++ themes/gitbook/components/TagItemMini.js | 21 ++++ themes/gitbook/components/TocDrawer.js | 34 ++++++ themes/gitbook/components/TopNavBar.js | 74 ++++++++++++ themes/gitbook/config_medium.js | 24 ++++ themes/gitbook/index.js | 25 +++++ themes/medium/LayoutBase.js | 4 +- themes/medium/LayoutSlug.js | 4 +- themes/theme.js | 2 +- 46 files changed, 1688 insertions(+), 5 deletions(-) create mode 100644 themes/gitbook/Layout404.js create mode 100644 themes/gitbook/LayoutArchive.js create mode 100644 themes/gitbook/LayoutBase.js create mode 100644 themes/gitbook/LayoutCategory.js create mode 100644 themes/gitbook/LayoutCategoryIndex.js create mode 100644 themes/gitbook/LayoutIndex.js create mode 100644 themes/gitbook/LayoutPage.js create mode 100644 themes/gitbook/LayoutSearch.js create mode 100644 themes/gitbook/LayoutSlug.js create mode 100644 themes/gitbook/LayoutTag.js create mode 100644 themes/gitbook/LayoutTagIndex.js create mode 100644 themes/gitbook/components/ArticleAround.js create mode 100644 themes/gitbook/components/ArticleLock.js create mode 100644 themes/gitbook/components/BlogPostCard.js create mode 100644 themes/gitbook/components/BlogPostListEmpty.js create mode 100644 themes/gitbook/components/BlogPostListPage.js create mode 100644 themes/gitbook/components/BlogPostListScroll.js create mode 100644 themes/gitbook/components/BottomMenuBar.js create mode 100644 themes/gitbook/components/Card.js create mode 100644 themes/gitbook/components/Catalog.js create mode 100644 themes/gitbook/components/CategoryGroup.js create mode 100644 themes/gitbook/components/CategoryItem.js create mode 100644 themes/gitbook/components/Footer.js create mode 100644 themes/gitbook/components/InfoCard.js create mode 100644 themes/gitbook/components/JumpToTopButton.js create mode 100644 themes/gitbook/components/LeftMenuBar.js create mode 100644 themes/gitbook/components/LogoBar.js create mode 100644 themes/gitbook/components/MenuBarMobile.js create mode 100644 themes/gitbook/components/MenuItemCollapse.js create mode 100644 themes/gitbook/components/MenuItemDrop.js create mode 100644 themes/gitbook/components/MenuItemMobileNormal.js create mode 100644 themes/gitbook/components/MenuItemPCNormal.js create mode 100644 themes/gitbook/components/PaginationSimple.js create mode 100644 themes/gitbook/components/Progress.js create mode 100644 themes/gitbook/components/RevolverMaps.js create mode 100644 themes/gitbook/components/SearchInput.js create mode 100644 themes/gitbook/components/SocialButton.js create mode 100644 themes/gitbook/components/TagGroups.js create mode 100644 themes/gitbook/components/TagItemMini.js create mode 100644 themes/gitbook/components/TocDrawer.js create mode 100644 themes/gitbook/components/TopNavBar.js create mode 100644 themes/gitbook/config_medium.js create mode 100644 themes/gitbook/index.js diff --git a/themes/gitbook/Layout404.js b/themes/gitbook/Layout404.js new file mode 100644 index 00000000..68b656cc --- /dev/null +++ b/themes/gitbook/Layout404.js @@ -0,0 +1,9 @@ +import LayoutBase from './LayoutBase' + +export const Layout404 = props => { + return +
404 Not found.
+
+} + +export default Layout404 diff --git a/themes/gitbook/LayoutArchive.js b/themes/gitbook/LayoutArchive.js new file mode 100644 index 00000000..101b7119 --- /dev/null +++ b/themes/gitbook/LayoutArchive.js @@ -0,0 +1,49 @@ +import BLOG from '@/blog.config' +import Link from 'next/link' +import LayoutBase from './LayoutBase' + +export const LayoutArchive = props => { + const { archivePosts } = props + + return ( + +
+ {Object.keys(archivePosts)?.map(archiveTitle => ( +
+
+ {archiveTitle} +
+
    + {archivePosts[archiveTitle]?.map(post => ( +
  • +
    + + {post.date?.start_date} + {' '} +   + + + {post.title} + + +
    +
  • + ))} +
+
+ ))} +
+
+ ) +} + +export default LayoutArchive diff --git a/themes/gitbook/LayoutBase.js b/themes/gitbook/LayoutBase.js new file mode 100644 index 00000000..09cb681c --- /dev/null +++ b/themes/gitbook/LayoutBase.js @@ -0,0 +1,93 @@ +import CommonHead from '@/components/CommonHead' +import { useState, createContext, useContext } from 'react' +import Footer from './components/Footer' +import InfoCard from './components/InfoCard' +import RevolverMaps from './components/RevolverMaps' +import CONFIG_MEDIUM from './config_medium' +import Tabs from '@/components/Tabs' +import TopNavBar from './components/TopNavBar' +import SearchInput from './components/SearchInput' +import BottomMenuBar from './components/BottomMenuBar' +import { useGlobal } from '@/lib/global' +import { useRouter } from 'next/router' +import Live2D from '@/components/Live2D' +import BLOG from '@/blog.config' +const ThemeGlobalMedium = createContext() + +/** + * 基础布局 采用左右两侧布局,移动端使用顶部导航栏 + + * @returns {JSX.Element} + * @constructor + */ +const LayoutBase = props => { + const { children, meta, showInfoCard = true, slotLeft, slotTop, siteInfo } = props + const { locale } = useGlobal() + const router = useRouter() + const [tocVisible, changeTocVisible] = useState(false) + const { onLoading } = useGlobal() + + const LoadingCover =
+
+ +
+
+ + return ( + + + +
+ +
+ + {/* 左侧推拉抽屉 */} +
+
+ + {slotLeft} +
+ {router.pathname !== '/search' && } + {showInfoCard && } + {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && } +
+
+ +
+
+ +
+ {/* 顶部导航栏 */} + + +
+ {slotTop} + + {onLoading ? LoadingCover : children} + + {/* 回顶按钮 */} +
+ { window.scrollTo({ top: 0, behavior: 'smooth' }) }} /> +
+
+ + {/* 底部 */} +
+
+ +
+ + {/* 移动端底部导航栏 */} + +
+
+ ) +} + +export default LayoutBase +export const useMediumGlobal = () => useContext(ThemeGlobalMedium) diff --git a/themes/gitbook/LayoutCategory.js b/themes/gitbook/LayoutCategory.js new file mode 100644 index 00000000..a947b70e --- /dev/null +++ b/themes/gitbook/LayoutCategory.js @@ -0,0 +1,15 @@ +import LayoutBase from './LayoutBase' +import BlogPostListScroll from './components/BlogPostListScroll' +import BlogPostListPage from './components/BlogPostListPage' +import BLOG from '@/blog.config' + +export const LayoutCategory = props => { + const { category } = props + const slotTop =
分类:
{category}
+ + return + {BLOG.POST_LIST_STYLE === 'page' ? : } + +} + +export default LayoutCategory diff --git a/themes/gitbook/LayoutCategoryIndex.js b/themes/gitbook/LayoutCategoryIndex.js new file mode 100644 index 00000000..2c8121ad --- /dev/null +++ b/themes/gitbook/LayoutCategoryIndex.js @@ -0,0 +1,34 @@ +import { useGlobal } from '@/lib/global' +import Link from 'next/link' +import LayoutBase from './LayoutBase' + +export const LayoutCategoryIndex = (props) => { + const { categoryOptions } = props + const { locale } = useGlobal() + return ( + +
+
+ {locale.COMMON.CATEGORY}: +
+
+ {categoryOptions?.map(category => { + return ( + +
+ {category.name}({category.count}) +
+ + ) + })} +
+
+
+ ) +} +export default LayoutCategoryIndex diff --git a/themes/gitbook/LayoutIndex.js b/themes/gitbook/LayoutIndex.js new file mode 100644 index 00000000..41410467 --- /dev/null +++ b/themes/gitbook/LayoutIndex.js @@ -0,0 +1,12 @@ +import BLOG from '@/blog.config' +import BlogPostListPage from './components/BlogPostListPage' +import BlogPostListScroll from './components/BlogPostListScroll' +import LayoutBase from './LayoutBase' + +export const LayoutIndex = (props) => { + return + {BLOG.POST_LIST_STYLE === 'page' ? : } + +} + +export default LayoutIndex diff --git a/themes/gitbook/LayoutPage.js b/themes/gitbook/LayoutPage.js new file mode 100644 index 00000000..563df90b --- /dev/null +++ b/themes/gitbook/LayoutPage.js @@ -0,0 +1,10 @@ +import LayoutBase from './LayoutBase' +import BlogPostListPage from './components/BlogPostListPage' + +export const LayoutPage = (props) => { + return + + +} + +export default LayoutPage diff --git a/themes/gitbook/LayoutSearch.js b/themes/gitbook/LayoutSearch.js new file mode 100644 index 00000000..1aaf3d20 --- /dev/null +++ b/themes/gitbook/LayoutSearch.js @@ -0,0 +1,53 @@ +import LayoutBase from './LayoutBase' +import SearchInput from './components/SearchInput' +import { useGlobal } from '@/lib/global' +import TagGroups from './components/TagGroups' +import CategoryGroup from './components/CategoryGroup' +import { useEffect } from 'react' +import { isBrowser } from '@/lib/utils' +import BLOG from '@/blog.config' +import Mark from 'mark.js' +import BlogPostListScroll from './components/BlogPostListScroll' +import BlogPostListPage from './components/BlogPostListPage' +import { useRouter } from 'next/router' + +export const LayoutSearch = (props) => { + const { locale } = useGlobal() + const { keyword } = props + const router = useRouter() + const currentSearch = keyword || router?.query?.s + + useEffect(() => { + setTimeout(() => { + const container = isBrowser() && document.getElementById('container') + if (container && container.innerHTML) { + const re = new RegExp(currentSearch, 'gim') + const instance = new Mark(container) + instance.markRegExp(re, { + element: 'span', + className: 'text-red-500 border-b border-dashed' + }) + } + }, + 100) + }) + return + +
+
{locale.NAV.SEARCH}
+ + + {!currentSearch && <> + + + } + +
+ + {currentSearch &&
+ {BLOG.POST_LIST_STYLE === 'page' ? : } +
} +
+} + +export default LayoutSearch diff --git a/themes/gitbook/LayoutSlug.js b/themes/gitbook/LayoutSlug.js new file mode 100644 index 00000000..68308ab7 --- /dev/null +++ b/themes/gitbook/LayoutSlug.js @@ -0,0 +1,97 @@ +import LayoutBase from './LayoutBase' +import { useGlobal } from '@/lib/global' +import React from 'react' +import Catalog from './components/Catalog' +import { ArticleLock } from './components/ArticleLock' +import formatDate from '@/lib/formatDate' +import BLOG from '@/blog.config' +import Link from 'next/link' +import NotionPage from '@/components/NotionPage' +import CONFIG_MEDIUM from './config_medium' +import Comment from '@/components/Comment' +import ArticleAround from './components/ArticleAround' +import TocDrawer from './components/TocDrawer' +import CategoryItem from './components/CategoryItem' +import TagItemMini from './components/TagItemMini' +import ShareBar from '@/components/ShareBar' + +export const LayoutSlug = props => { + const { post, prev, next, siteInfo, lock, validPassword } = props + const { locale } = useGlobal() + + const date = formatDate( + post?.date?.start_date || post?.createdTime, + locale.LOCALE + ) + if (!post) { + return + } + + const slotLeft = post?.toc && post?.toc?.length > 3 && ( +
+ + {/* */} +
+ ) + + return ( + + {/* 文章锁 */} + {lock && } + + {!lock &&
+ + {/* title */} +

{post?.title}

+ + {/* meta */} +
+
+ {date} + | + {post.lastEditedTime} +
+ +
+
+ +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {BLOG.AUTHOR} + +
+ {BLOG.AUTHOR} +
+
+ +
+ + {/* Notion文章主体 */} +
+ {post && ()} +
+ +
+ + {/* 分享 */} + + {/* 文章分类和标签信息 */} +
+ {CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && } +
+ {CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => )} +
+
+ + {post.type === 'Post' && } + +
+ + +
} +
+ ) +} + +export default LayoutSlug diff --git a/themes/gitbook/LayoutTag.js b/themes/gitbook/LayoutTag.js new file mode 100644 index 00000000..bedb51ef --- /dev/null +++ b/themes/gitbook/LayoutTag.js @@ -0,0 +1,15 @@ +import LayoutBase from './LayoutBase' +import BLOG from '@/blog.config' +import BlogPostListScroll from './components/BlogPostListScroll' +import BlogPostListPage from './components/BlogPostListPage' + +export const LayoutTag = (props) => { + const { tag } = props + const slotTop =
标签:
{tag}
+ + return + {BLOG.POST_LIST_STYLE === 'page' ? : } + +} + +export default LayoutTag diff --git a/themes/gitbook/LayoutTagIndex.js b/themes/gitbook/LayoutTagIndex.js new file mode 100644 index 00000000..cc9f8c94 --- /dev/null +++ b/themes/gitbook/LayoutTagIndex.js @@ -0,0 +1,29 @@ +import { useGlobal } from '@/lib/global' +import TagItemMini from './components/TagItemMini' +import LayoutBase from './LayoutBase' + +export const LayoutTagIndex = props => { + const { tagOptions } = props + const { locale } = useGlobal() + return ( + +
+
+ + {locale.COMMON.TAGS}: +
+
+ {tagOptions?.map(tag => { + return ( +
+ +
+ ) + })} +
+
+
+ ) +} + +export default LayoutTagIndex diff --git a/themes/gitbook/components/ArticleAround.js b/themes/gitbook/components/ArticleAround.js new file mode 100644 index 00000000..95b6f83f --- /dev/null +++ b/themes/gitbook/components/ArticleAround.js @@ -0,0 +1,32 @@ +import Link from 'next/link' + +/** + * 上一篇,下一篇文章 + * @param {prev,next} param0 + * @returns + */ +export default function ArticleAround ({ prev, next }) { + if (!prev || !next) { + return <> + } + return ( +
+ + + {prev.title} + + + + {next.title} + + + +
+ ) +} diff --git a/themes/gitbook/components/ArticleLock.js b/themes/gitbook/components/ArticleLock.js new file mode 100644 index 00000000..4ba5a3b9 --- /dev/null +++ b/themes/gitbook/components/ArticleLock.js @@ -0,0 +1,53 @@ +import { useGlobal } from '@/lib/global' +import { useEffect, useRef } from 'react' + +/** + * 加密文章校验组件 + * @param {password, validPassword} props + * @param password 正确的密码 + * @param validPassword(bool) 回调函数,校验正确回调入参为true + * @returns + */ +export const ArticleLock = props => { + const { validPassword } = props + const { locale } = useGlobal() + + const submitPassword = () => { + const p = document.getElementById('password') + if (!validPassword(p?.value)) { + const tips = document.getElementById('tips') + if (tips) { + tips.innerHTML = '' + tips.innerHTML = `
${locale.COMMON.PASSWORD_ERROR}
` + } + } + } + + const passwordInputRef = useRef(null) + useEffect(() => { + // 选中密码输入框并将其聚焦 + passwordInputRef.current.focus() + }, []) + + return
+
+
{locale.COMMON.ARTICLE_LOCK_TIPS}
+
+ { + if (e.key === 'Enter') { + submitPassword() + } + }} + ref={passwordInputRef} // 绑定ref到passwordInputRef变量 + className='outline-none w-full text-sm pl-5 rounded-l transition focus:shadow-lg dark:text-gray-300 font-light leading-10 text-black bg-gray-100 dark:bg-gray-500'> + +
+  {locale.COMMON.SUBMIT} +
+
+
+
+
+
+} diff --git a/themes/gitbook/components/BlogPostCard.js b/themes/gitbook/components/BlogPostCard.js new file mode 100644 index 00000000..998dd086 --- /dev/null +++ b/themes/gitbook/components/BlogPostCard.js @@ -0,0 +1,83 @@ +import BLOG from '@/blog.config' +import NotionPage from '@/components/NotionPage' +import { useGlobal } from '@/lib/global' +import Link from 'next/link' +import React from 'react' +import CONFIG_MEDIUM from '../config_medium' +import CategoryItem from './CategoryItem' +import TagItemMini from './TagItemMini' +import TwikooCommentCount from '@/components/TwikooCommentCount' + +const BlogPostCard = ({ post, showSummary }) => { + const showPreview = CONFIG_MEDIUM.POST_LIST_PREVIEW && post.blockMap + const { locale } = useGlobal() + return ( +
+ +
+ +
+ {CONFIG_MEDIUM.POST_LIST_COVER &&
+ {/* eslint-disable-next-line @next/next/no-img-element */} + +
} + {post.title} +
+ + + +
+
{post.date?.start_date}
+ {CONFIG_MEDIUM.POST_LIST_CATEGORY && } + {CONFIG_MEDIUM.POST_LIST_TAG && post?.tagItems?.map(tag => )} + +
+ +
+ + {(!showPreview || showSummary) && ( +

+ {post.summary} +

+ )} + + {showPreview && ( +
+ +
+
+ + + {locale.COMMON.ARTICLE_DETAIL} + + + +
+
+
+ )} +
+
+ ) +} + +export default BlogPostCard diff --git a/themes/gitbook/components/BlogPostListEmpty.js b/themes/gitbook/components/BlogPostListEmpty.js new file mode 100644 index 00000000..86977fd0 --- /dev/null +++ b/themes/gitbook/components/BlogPostListEmpty.js @@ -0,0 +1,12 @@ + +/** + * 空白博客 列表 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostListEmpty = ({ currentSearch }) => { + return
+

没有找到文章 {(currentSearch &&

{currentSearch}
)}

+
+} +export default BlogPostListEmpty diff --git a/themes/gitbook/components/BlogPostListPage.js b/themes/gitbook/components/BlogPostListPage.js new file mode 100644 index 00000000..db74b74e --- /dev/null +++ b/themes/gitbook/components/BlogPostListPage.js @@ -0,0 +1,34 @@ +import BlogPostCard from './BlogPostCard' +import BLOG from '@/blog.config' +import BlogPostListEmpty from './BlogPostListEmpty' +import PaginationSimple from './PaginationSimple' + +/** + * 文章列表分页表格 + * @param page 当前页 + * @param posts 所有文章 + * @param tags 所有标签 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostListPage = ({ page = 1, posts = [], postCount }) => { + const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) + + if (!posts || posts.length === 0) { + return + } + + return ( +
+
+ {/* 文章列表 */} + {posts?.map(post => ( + + ))} +
+ +
+ ) +} + +export default BlogPostListPage diff --git a/themes/gitbook/components/BlogPostListScroll.js b/themes/gitbook/components/BlogPostListScroll.js new file mode 100644 index 00000000..2c7eafbd --- /dev/null +++ b/themes/gitbook/components/BlogPostListScroll.js @@ -0,0 +1,106 @@ +import BLOG from '@/blog.config' +import BlogPostCard from './BlogPostCard' +import BlogPostListEmpty from './BlogPostListEmpty' +import { useGlobal } from '@/lib/global' +import throttle from 'lodash.throttle' +import React, { useCallback, useEffect, useRef, useState } from 'react' +import { useRouter } from 'next/router' + +/** + * 博客列表滚动分页 + * @param posts 所有文章 + * @param tags 所有标签 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostListScroll = ({ posts = [], currentSearch }) => { + const postsPerPage = BLOG.POSTS_PER_PAGE + const [page, updatePage] = useState(1) + let filteredPosts = Object.assign(posts) + const searchKey = getSearchKey() + if (searchKey) { + filteredPosts = posts.filter(post => { + const tagContent = post.tags ? post.tags.join(' ') : '' + const searchContent = post.title + post.summary + tagContent + return searchContent.toLowerCase().includes(searchKey.toLowerCase()) + }) + } + const postsToShow = getPostByPage(page, filteredPosts, postsPerPage) + + let hasMore = false + if (filteredPosts) { + const totalCount = filteredPosts.length + hasMore = page * postsPerPage < totalCount + } + + const handleGetMore = () => { + if (!hasMore) return + updatePage(page + 1) + } + + // 监听滚动自动分页加载 + const scrollTrigger = useCallback(throttle(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }, 500)) + + // 监听滚动 + useEffect(() => { + window.addEventListener('scroll', scrollTrigger) + return () => { + window.removeEventListener('scroll', scrollTrigger) + } + }) + + const targetRef = useRef(null) + const { locale } = useGlobal() + + if (!postsToShow || postsToShow.length === 0) { + return + } else { + return
+ + {/* 文章列表 */} +
+ {postsToShow?.map(post => ( + + ))} +
+ +
+
{ + handleGetMore() + }} + className='w-full my-4 py-4 text-center cursor-pointer dark:text-gray-200' + > {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}
+
+
+ } +} + +/** + * 获取从第1页到指定页码的文章 + * @param page 第几页 + * @param totalPosts 所有文章 + * @param postsPerPage 每页文章数量 + * @returns {*} + */ +const getPostByPage = function (page, totalPosts, postsPerPage) { + return totalPosts.slice( + 0, + postsPerPage * page + ) +} + +function getSearchKey() { + const router = useRouter() + if (router.query && router.query.s) { + return router.query.s + } + return null +} + +export default BlogPostListScroll diff --git a/themes/gitbook/components/BottomMenuBar.js b/themes/gitbook/components/BottomMenuBar.js new file mode 100644 index 00000000..45215f50 --- /dev/null +++ b/themes/gitbook/components/BottomMenuBar.js @@ -0,0 +1,36 @@ +import Link from 'next/link' +import React from 'react' +import { useMediumGlobal } from '../LayoutBase' +import JumpToTopButton from './JumpToTopButton' + +export default function BottomMenuBar ({ post, className }) { + const { tocVisible, changeTocVisible } = useMediumGlobal() + const showTocBotton = post?.toc?.length > 0 + + const toggleToc = () => { + changeTocVisible(!tocVisible) + } + + return ( +
+
+ +
+ +
+ +
+ +
+ {showTocBotton &&
+ +
} + { !showTocBotton && +
+ +
+ } +
+
+ ) +} diff --git a/themes/gitbook/components/Card.js b/themes/gitbook/components/Card.js new file mode 100644 index 00000000..d24c046e --- /dev/null +++ b/themes/gitbook/components/Card.js @@ -0,0 +1,9 @@ +const Card = ({ children, headerSlot, className }) => { + return
+ <>{headerSlot} +
+ {children} +
+
+} +export default Card diff --git a/themes/gitbook/components/Catalog.js b/themes/gitbook/components/Catalog.js new file mode 100644 index 00000000..c9592dd2 --- /dev/null +++ b/themes/gitbook/components/Catalog.js @@ -0,0 +1,91 @@ +import { useCallback, useEffect, useRef, useState } from 'react' +import throttle from 'lodash.throttle' +import { uuidToId } from 'notion-utils' +import Progress from './Progress' + +/** + * 目录导航组件 + * @param toc + * @returns {JSX.Element} + * @constructor + */ +const Catalog = ({ toc }) => { + const tocIds = [] + + // 目录自动滚动 + const tRef = useRef(null) + // 同步选中目录事件 + const [activeSection, setActiveSection] = useState(null) + + // 监听滚动事件 + useEffect(() => { + window.addEventListener('scroll', actionSectionScrollSpy) + actionSectionScrollSpy() + return () => { + window.removeEventListener('scroll', actionSectionScrollSpy) + } + }, []) + + const throttleMs = 200 + const actionSectionScrollSpy = 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 (!toc || toc.length < 1) { + return <> + } + + return
+
+ +
+
+ +
+
+} + +export default Catalog diff --git a/themes/gitbook/components/CategoryGroup.js b/themes/gitbook/components/CategoryGroup.js new file mode 100644 index 00000000..1516c038 --- /dev/null +++ b/themes/gitbook/components/CategoryGroup.js @@ -0,0 +1,19 @@ +import React from 'react' +import CategoryItem from './CategoryItem' + +const CategoryGroup = ({ currentCategory, categoryOptions }) => { + if (!categoryOptions) { + return <> + } + return
+
分类
+
+ {categoryOptions?.map(category => { + const selected = currentCategory === category.name + return + })} +
+
+} + +export default CategoryGroup diff --git a/themes/gitbook/components/CategoryItem.js b/themes/gitbook/components/CategoryItem.js new file mode 100644 index 00000000..779488de --- /dev/null +++ b/themes/gitbook/components/CategoryItem.js @@ -0,0 +1,18 @@ +import Link from 'next/link' + +export default function CategoryItem ({ selected, category, categoryCount }) { + return ( + + +
{category} {categoryCount && `(${categoryCount})`} +
+ + + ); +} diff --git a/themes/gitbook/components/Footer.js b/themes/gitbook/components/Footer.js new file mode 100644 index 00000000..b9d4f49c --- /dev/null +++ b/themes/gitbook/components/Footer.js @@ -0,0 +1,35 @@ +import React from 'react' +import BLOG from '@/blog.config' +import DarkModeButton from '@/components/DarkModeButton' + +const Footer = ({ title }) => { + const d = new Date() + const currentYear = d.getFullYear() + const copyrightDate = (function() { + if (Number.isInteger(BLOG.SINCE) && BLOG.SINCE < currentYear) { + return BLOG.SINCE + '-' + currentYear + } + return currentYear + })() + + return ( + + ) +} + +export default Footer diff --git a/themes/gitbook/components/InfoCard.js b/themes/gitbook/components/InfoCard.js new file mode 100644 index 00000000..a18408dc --- /dev/null +++ b/themes/gitbook/components/InfoCard.js @@ -0,0 +1,21 @@ +import BLOG from '@/blog.config' +import Router from 'next/router' +import React from 'react' +import SocialButton from './SocialButton' + +const InfoCard = (props) => { + const { siteInfo } = props + return
+
+
{ Router.push('/about') }}> + {/* eslint-disable-next-line @next/next/no-img-element */} + {BLOG.AUTHOR}/ +
+
{BLOG.AUTHOR}
+
{BLOG.BIO}
+ +
+
+} + +export default InfoCard diff --git a/themes/gitbook/components/JumpToTopButton.js b/themes/gitbook/components/JumpToTopButton.js new file mode 100644 index 00000000..2d83338c --- /dev/null +++ b/themes/gitbook/components/JumpToTopButton.js @@ -0,0 +1,26 @@ +import { useGlobal } from '@/lib/global' +import React from 'react' +import CONFIG_MEDIUM from '../config_medium' + +/** + * 跳转到网页顶部 + * 当屏幕下滑500像素后会出现该控件 + * @param targetRef 关联高度的目标html标签 + * @param showPercent 是否显示百分比 + * @returns {JSX.Element} + * @constructor + */ +const JumpToTopButton = ({ showPercent = false, percent, className }) => { + const { locale } = useGlobal() + if (!CONFIG_MEDIUM.WIDGET_TO_TOP) { + return <> + } + return (
window.scrollTo({ top: 0, behavior: 'smooth' })} > +
+ +
+ {showPercent && (
{percent}%
)} +
) +} + +export default JumpToTopButton diff --git a/themes/gitbook/components/LeftMenuBar.js b/themes/gitbook/components/LeftMenuBar.js new file mode 100644 index 00000000..e6636e19 --- /dev/null +++ b/themes/gitbook/components/LeftMenuBar.js @@ -0,0 +1,16 @@ +import Link from 'next/link' +import React from 'react' + +export default function LeftMenuBar () { + return ( +
+
+ +
+ +
+ +
+
+ ); +} diff --git a/themes/gitbook/components/LogoBar.js b/themes/gitbook/components/LogoBar.js new file mode 100644 index 00000000..cbe59474 --- /dev/null +++ b/themes/gitbook/components/LogoBar.js @@ -0,0 +1,12 @@ +import Link from 'next/link' + +export default function LogoBar (props) { + const { siteInfo } = props + return ( +
+ + {siteInfo?.title} + +
+ ); +} diff --git a/themes/gitbook/components/MenuBarMobile.js b/themes/gitbook/components/MenuBarMobile.js new file mode 100644 index 00000000..538a9782 --- /dev/null +++ b/themes/gitbook/components/MenuBarMobile.js @@ -0,0 +1,39 @@ +import React from 'react' +import { useGlobal } from '@/lib/global' +import CONFIG_MEDIUM from '../config_medium' +import BLOG from '@/blog.config' +import { MenuItemCollapse } from './MenuItemCollapse' + +export const MenuBarMobile = (props) => { + const { customMenu, customNav } = props + const { locale } = useGlobal() + + let links = [ + // { name: locale.NAV.INDEX, to: '/' || '/', show: true }, + { name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_MEDIUM.MENU_CATEGORY }, + { name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_MEDIUM.MENU_TAG }, + { name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG_MEDIUM.MENU_ARCHIVE } + // { name: locale.NAV.SEARCH, to: '/search', show: CONFIG_MEDIUM.MENU_SEARCH } + ] + + if (customNav) { + links = links.concat(customNav) + } + + // 如果 开启自定义菜单,则不再使用 Page生成菜单。 + if (BLOG.CUSTOM_MENU) { + links = customMenu + } + + if (!links || links.length === 0) { + return null + } + + return ( + + ) +} diff --git a/themes/gitbook/components/MenuItemCollapse.js b/themes/gitbook/components/MenuItemCollapse.js new file mode 100644 index 00000000..539419eb --- /dev/null +++ b/themes/gitbook/components/MenuItemCollapse.js @@ -0,0 +1,62 @@ +import Collapse from '@/components/Collapse' +import Link from 'next/link' +import { useRouter } from 'next/router' +import { useState } from 'react' + +/** + * 折叠菜单 + * @param {*} param0 + * @returns + */ +export const MenuItemCollapse = (props) => { + const { link } = props + const [show, changeShow] = useState(false) + const hasSubMenu = link?.subMenus?.length > 0 + + const [isOpen, changeIsOpen] = useState(false) + + const router = useRouter() + + if (!link || !link.show) { + return null + } + + const selected = (router.pathname === link.to) || (router.asPath === link.to) + + const toggleShow = () => { + changeShow(!show) + } + + const toggleOpenSubMenu = () => { + changeIsOpen(!isOpen) + } + + return <> +
+ + {!hasSubMenu && +
{link.name}
+ } + + {hasSubMenu &&
+
{link.name}
+
+
} +
+ + {/* 折叠子菜单 */} + {hasSubMenu && + {link?.subMenus?.map(sLink => { + return
+ +
{sLink.title}
+ +
+ })} + } + +} diff --git a/themes/gitbook/components/MenuItemDrop.js b/themes/gitbook/components/MenuItemDrop.js new file mode 100644 index 00000000..e9d1b9f3 --- /dev/null +++ b/themes/gitbook/components/MenuItemDrop.js @@ -0,0 +1,50 @@ +import Link from 'next/link' +import { useState } from 'react' +import { useRouter } from 'next/router' + +export const MenuItemDrop = ({ link }) => { + const [show, changeShow] = useState(false) + // const show = true + // const changeShow = () => {} + const router = useRouter() + + if (!link || !link.show) { + return null + } + const hasSubMenu = link?.subMenus?.length > 0 + const selected = (router.pathname === link.to) || (router.asPath === link.to) + + return
  • changeShow(true)} onMouseOut={() => changeShow(false)} > + + {hasSubMenu && +
    +
    + {link?.icon && } {link?.name} + {hasSubMenu && } +
    +
    + } + + {!hasSubMenu && +
    + + {link?.icon && } {link?.name} + +
    + } + + {/* 子菜单 */} + {hasSubMenu &&
      + {link?.subMenus?.map(sLink => { + return
    • + + {link?.icon &&   }{sLink.title} + +
    • + })} +
    } + +
  • +} diff --git a/themes/gitbook/components/MenuItemMobileNormal.js b/themes/gitbook/components/MenuItemMobileNormal.js new file mode 100644 index 00000000..17f0d151 --- /dev/null +++ b/themes/gitbook/components/MenuItemMobileNormal.js @@ -0,0 +1,27 @@ +import Link from 'next/link' +import { useRouter } from 'next/router' + +export const NormalMenu = props => { + const { link } = props + const router = useRouter() + + if (!link || !link.show) { + return null + } + + const selected = (router.pathname === link.to) || (router.asPath === link.to) + + return + +
    +
    {link.name}
    +
    + {link.slot} + + +} diff --git a/themes/gitbook/components/MenuItemPCNormal.js b/themes/gitbook/components/MenuItemPCNormal.js new file mode 100644 index 00000000..809ae974 --- /dev/null +++ b/themes/gitbook/components/MenuItemPCNormal.js @@ -0,0 +1,24 @@ +import Link from 'next/link' +import { useRouter } from 'next/router' + +export const MenuItemPCNormal = props => { + const { link } = props + const router = useRouter() + const selected = (router.pathname === link.to) || (router.asPath === link.to) + if (!link || !link.show) { + return null + } + + return +
    + +
    {link.name}
    +
    + {link.slot} + +} diff --git a/themes/gitbook/components/PaginationSimple.js b/themes/gitbook/components/PaginationSimple.js new file mode 100644 index 00000000..b48259ea --- /dev/null +++ b/themes/gitbook/components/PaginationSimple.js @@ -0,0 +1,54 @@ +import Link from 'next/link' +import { useRouter } from 'next/router' +import { useGlobal } from '@/lib/global' + +/** + * 简易翻页插件 + * @param page 当前页码 + * @param totalPage 是否有下一页 + * @returns {JSX.Element} + * @constructor + */ +const PaginationSimple = ({ page, totalPage }) => { + const { locale } = useGlobal() + const router = useRouter() + const currentPage = +page + const showNext = currentPage < totalPage + const pagePrefix = router.asPath.replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '') + + return ( +
    + + ←{locale.PAGINATION.PREV} + + + + + {locale.PAGINATION.NEXT}→ + +
    + ) +} + +export default PaginationSimple diff --git a/themes/gitbook/components/Progress.js b/themes/gitbook/components/Progress.js new file mode 100644 index 00000000..48ba8e14 --- /dev/null +++ b/themes/gitbook/components/Progress.js @@ -0,0 +1,44 @@ +import React, { useEffect, useState } from 'react' +import { isBrowser } from '@/lib/utils' + +/** + * 顶部页面阅读进度条 + * @returns {JSX.Element} + * @constructor + */ +const Progress = ({ targetRef, showPercent = true }) => { + const currentRef = targetRef?.current || targetRef + const [percent, changePercent] = useState(0) + const scrollListener = () => { + const target = currentRef || (isBrowser() && document.getElementById('container')) + if (target) { + const clientHeight = target.clientHeight + const scrollY = window.pageYOffset + const fullHeight = clientHeight - window.outerHeight + let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0)) + if (per > 100) per = 100 + if (per < 0) per = 0 + changePercent(per) + } + } + + useEffect(() => { + document.addEventListener('scroll', scrollListener) + return () => document.removeEventListener('scroll', scrollListener) + }, []) + + return ( +
    +
    + {showPercent && ( +
    {percent}%
    + )} +
    +
    + ) +} + +export default Progress diff --git a/themes/gitbook/components/RevolverMaps.js b/themes/gitbook/components/RevolverMaps.js new file mode 100644 index 00000000..d839d85d --- /dev/null +++ b/themes/gitbook/components/RevolverMaps.js @@ -0,0 +1,36 @@ +import { useEffect, useState } from 'react' + +export default function RevolverMaps () { + const [load, changeLoad] = useState(false) + useEffect(() => { + if (!load) { + initRevolverMaps() + changeLoad(true) + } + }) + return
    +} + +function initRevolverMaps () { + if (screen.width >= 768) { + Promise.all([ + loadExternalResource('https://rf.revolvermaps.com/0/0/8.js?i=5jnp1havmh9&m=0&c=ff0000&cr1=ffffff&f=arial&l=33') + ]).then(() => { + console.log('地图加载完成') + }) + } +} + +// 封装异步加载资源的方法 +function loadExternalResource (url) { + return new Promise((resolve, reject) => { + const container = document.getElementById('revolvermaps') + const tag = document.createElement('script') + tag.src = url + if (tag) { + tag.onload = () => resolve(url) + tag.onerror = () => reject(url) + container.appendChild(tag) + } + }) +} diff --git a/themes/gitbook/components/SearchInput.js b/themes/gitbook/components/SearchInput.js new file mode 100644 index 00000000..f6c84d9c --- /dev/null +++ b/themes/gitbook/components/SearchInput.js @@ -0,0 +1,86 @@ +import { useRouter } from 'next/router' +import { useImperativeHandle, useRef, useState } from 'react' +let lock = false + +const SearchInput = ({ currentTag, currentSearch, cRef, className }) => { + const [onLoading, setLoadingState] = useState(false) + const router = useRouter() + const searchInputRef = useRef() + useImperativeHandle(cRef, () => { + return { + focus: () => { + searchInputRef?.current?.focus() + } + } + }) + + const handleSearch = () => { + const key = searchInputRef.current.value + + if (key && key !== '') { + setLoadingState(true) + location.href = '/search/' + key + } else { + router.push({ pathname: '/' }).then(r => { + }) + } + } + const handleKeyUp = (e) => { + if (e.keyCode === 13) { // 回车 + handleSearch(searchInputRef.current.value) + } else if (e.keyCode === 27) { // ESC + cleanSearch() + } + } + const cleanSearch = () => { + searchInputRef.current.value = '' + } + + const [showClean, setShowClean] = useState(false) + const updateSearchKey = (val) => { + if (lock) { + return + } + searchInputRef.current.value = val + + if (val) { + setShowClean(true) + } else { + setShowClean(false) + } + } + function lockSearchInput () { + lock = true + } + + function unLockSearchInput () { + lock = false + } + + return
    + updateSearchKey(e.target.value)} + defaultValue={currentSearch} + /> + +
    + +
    + + {(showClean && +
    + +
    + )} +
    +} + +export default SearchInput diff --git a/themes/gitbook/components/SocialButton.js b/themes/gitbook/components/SocialButton.js new file mode 100644 index 00000000..5f51033d --- /dev/null +++ b/themes/gitbook/components/SocialButton.js @@ -0,0 +1,37 @@ +import BLOG from '@/blog.config' +import React from 'react' + +/** + * 社交联系方式按钮组 + * @returns {JSX.Element} + * @constructor + */ +const SocialButton = () => { + return
    + {BLOG.CONTACT_GITHUB && + + } + {BLOG.CONTACT_TWITTER && + + } + {BLOG.CONTACT_TELEGRAM && + + } + {BLOG.CONTACT_LINKEDIN && + + } + {BLOG.CONTACT_WEIBO && + + } + {BLOG.CONTACT_INSTAGRAM && + + } + {BLOG.CONTACT_EMAIL && + + } + {BLOG.ENABLE_RSS && + + } +
    +} +export default SocialButton diff --git a/themes/gitbook/components/TagGroups.js b/themes/gitbook/components/TagGroups.js new file mode 100644 index 00000000..390a6306 --- /dev/null +++ b/themes/gitbook/components/TagGroups.js @@ -0,0 +1,27 @@ +import TagItemMini from './TagItemMini' + +/** + * 标签组 + * @param tags + * @param currentTag + * @returns {JSX.Element} + * @constructor + */ +const TagGroups = ({ tagOptions, currentTag }) => { + if (!tagOptions) return <> + return ( +
    +
    标签
    +
    + { + tagOptions?.map(tag => { + const selected = tag.name === currentTag + return + }) + } +
    +
    + ) +} + +export default TagGroups diff --git a/themes/gitbook/components/TagItemMini.js b/themes/gitbook/components/TagItemMini.js new file mode 100644 index 00000000..9922a069 --- /dev/null +++ b/themes/gitbook/components/TagItemMini.js @@ -0,0 +1,21 @@ +import Link from 'next/link' + +const TagItemMini = ({ tag, selected = false }) => { + return ( + + +
    {selected && } {tag.name + (tag.count ? `(${tag.count})` : '')}
    + + + ) +} + +export default TagItemMini diff --git a/themes/gitbook/components/TocDrawer.js b/themes/gitbook/components/TocDrawer.js new file mode 100644 index 00000000..9a9270db --- /dev/null +++ b/themes/gitbook/components/TocDrawer.js @@ -0,0 +1,34 @@ +import Catalog from './Catalog' +import { useMediumGlobal } from '../LayoutBase' + +/** + * 悬浮抽屉目录 + * @param toc + * @param post + * @returns {JSX.Element} + * @constructor + */ +const TocDrawer = ({ post, cRef }) => { + const { tocVisible, changeTocVisible } = useMediumGlobal() + const switchVisible = () => { + changeTocVisible(!tocVisible) + } + return <> +
    + {/* 侧边菜单 */} +
    + {post && <> +
    + +
    + } +
    +
    + {/* 背景蒙版 */} +
    + +} +export default TocDrawer diff --git a/themes/gitbook/components/TopNavBar.js b/themes/gitbook/components/TopNavBar.js new file mode 100644 index 00000000..b4e01345 --- /dev/null +++ b/themes/gitbook/components/TopNavBar.js @@ -0,0 +1,74 @@ +import LogoBar from './LogoBar' +import { useRef, useState } from 'react' +import Collapse from '@/components/Collapse' +import { MenuBarMobile } from './MenuBarMobile' +import { useGlobal } from '@/lib/global' +import CONFIG_MEDIUM from '../config_medium' +import BLOG from '@/blog.config' +import { MenuItemDrop } from './MenuItemDrop' + +/** + * 顶部导航栏 + 菜单 + * @param {} param0 + * @returns + */ +export default function TopNavBar(props) { + const { className, customNav, customMenu } = props + const [isOpen, changeShow] = useState(false) + const collapseRef = useRef(null) + + const { locale } = useGlobal() + + const defaultLinks = [ + { icon: 'fas fa-th', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_MEDIUM.MENU_CATEGORY }, + { icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_MEDIUM.MENU_TAG }, + { icon: 'fas fa-archive', name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG_MEDIUM.MENU_ARCHIVE }, + { icon: 'fas fa-search', name: locale.NAV.SEARCH, to: '/search', show: CONFIG_MEDIUM.MENU_SEARCH } + ] + + let links = defaultLinks.concat(customNav) + + const toggleMenuOpen = () => { + changeShow(!isOpen) + } + + // 如果 开启自定义菜单,则覆盖Page生成的菜单 + if (BLOG.CUSTOM_MENU) { + links = customMenu + } + + if (!links || links.length === 0) { + return null + } + + return ( +
    + + {/* 移动端折叠菜单 */} + +
    + collapseRef.current?.updateCollapseHeight(param)} /> +
    +
    + + {/* 导航栏菜单 */} +
    + + {/* 左侧图标Logo */} + + + {/* 折叠按钮、仅移动端显示 */} +
    +
    + {isOpen ? : } +
    +
    + + {/* 桌面端顶部菜单 */} +
    + {links && links?.map(link => )} +
    +
    +
    + ) +} diff --git a/themes/gitbook/config_medium.js b/themes/gitbook/config_medium.js new file mode 100644 index 00000000..40f41c97 --- /dev/null +++ b/themes/gitbook/config_medium.js @@ -0,0 +1,24 @@ +const CONFIG_MEDIUM = { + + // Style + RIGHT_PANEL_DARK: process.env.NEXT_PUBLIC_MEDIUM_RIGHT_DARK || false, // 右侧面板深色模式 + + POST_LIST_COVER: true, // 文章列表显示图片封面 + POST_LIST_PREVIEW: true, // 列表显示文章预览 + POST_LIST_CATEGORY: true, // 列表显示文章分类 + POST_LIST_TAG: true, // 列表显示文章标签 + + POST_DETAIL_CATEGORY: true, // 文章显示分类 + POST_DETAIL_TAG: true, // 文章显示标签 + + // 菜单 + MENU_CATEGORY: true, // 显示分类 + MENU_TAG: true, // 显示标签 + MENU_ARCHIVE: true, // 显示归档 + MENU_SEARCH: true, // 显示搜索 + + // Widget + WIDGET_REVOLVER_MAPS: process.env.NEXT_PUBLIC_WIDGET_REVOLVER_MAPS || 'false', // 地图插件 + WIDGET_TO_TOP: true // 跳回顶部 +} +export default CONFIG_MEDIUM diff --git a/themes/gitbook/index.js b/themes/gitbook/index.js new file mode 100644 index 00000000..81961c58 --- /dev/null +++ b/themes/gitbook/index.js @@ -0,0 +1,25 @@ +import CONFIG_MEDIUM from './config_medium' +import { LayoutIndex } from './LayoutIndex' +import { LayoutSearch } from './LayoutSearch' +import { LayoutArchive } from './LayoutArchive' +import { LayoutSlug } from './LayoutSlug' +import { Layout404 } from './Layout404' +import { LayoutCategory } from './LayoutCategory' +import { LayoutCategoryIndex } from './LayoutCategoryIndex' +import { LayoutPage } from './LayoutPage' +import { LayoutTag } from './LayoutTag' +import { LayoutTagIndex } from './LayoutTagIndex' + +export { + CONFIG_MEDIUM as THEME_CONFIG, + LayoutIndex, + LayoutSearch, + LayoutArchive, + LayoutSlug, + Layout404, + LayoutCategory, + LayoutCategoryIndex, + LayoutPage, + LayoutTag, + LayoutTagIndex +} diff --git a/themes/medium/LayoutBase.js b/themes/medium/LayoutBase.js index 9d3a9eff..19948d25 100644 --- a/themes/medium/LayoutBase.js +++ b/themes/medium/LayoutBase.js @@ -21,7 +21,7 @@ const ThemeGlobalMedium = createContext() * @constructor */ const LayoutBase = props => { - const { children, meta, showInfoCard = true, slotRight, slotTop, siteInfo } = props + const { children, meta, showInfoCard = true, slotLeft, slotTop, siteInfo } = props const { locale } = useGlobal() const router = useRouter() const [tocVisible, changeTocVisible] = useState(false) @@ -71,7 +71,7 @@ const LayoutBase = props => {
    - {slotRight} + {slotLeft}
    {router.pathname !== '/search' && } {showInfoCard && } diff --git a/themes/medium/LayoutSlug.js b/themes/medium/LayoutSlug.js index 9217f281..68308ab7 100644 --- a/themes/medium/LayoutSlug.js +++ b/themes/medium/LayoutSlug.js @@ -28,7 +28,7 @@ export const LayoutSlug = props => { /> } - const slotRight = post?.toc && post?.toc?.length > 3 && ( + const slotLeft = post?.toc && post?.toc?.length > 3 && (
    {/* */} @@ -36,7 +36,7 @@ export const LayoutSlug = props => { ) return ( - + {/* 文章锁 */} {lock && } diff --git a/themes/theme.js b/themes/theme.js index f0db2291..0214c1bc 100644 --- a/themes/theme.js +++ b/themes/theme.js @@ -8,7 +8,7 @@ import * as ThemeComponents from '@theme-components' * 所有主题枚举 */ export const ALL_THEME = [ - 'hexo', 'matery', 'next', 'medium', 'fukasawa', 'nobelium', 'example', 'simple' + 'hexo', 'matery', 'next', 'medium', 'fukasawa', 'nobelium', 'example', 'simple', 'gitbook' ] /** From a1708605da6f7317f5b79ea8fa5de9dbac4906b2 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Fri, 23 Jun 2023 15:56:59 +0800 Subject: [PATCH 02/12] gitbook --- lib/global.js | 9 +++------ themes/gitbook/LayoutBase.js | 23 +++++++++++++++++++---- themes/gitbook/components/LogoBar.js | 16 +++++++++------- themes/gitbook/components/MenuItemDrop.js | 4 ++-- themes/gitbook/components/TopNavBar.js | 2 +- themes/medium/LayoutBase.js | 6 +++--- themes/medium/components/MenuItemDrop.js | 4 ++-- 7 files changed, 39 insertions(+), 25 deletions(-) diff --git a/lib/global.js b/lib/global.js index 599a14cb..a6e45b3f 100644 --- a/lib/global.js +++ b/lib/global.js @@ -4,7 +4,6 @@ import { useRouter } from 'next/router' import BLOG from '@/blog.config' import { ALL_THEME, initDarkMode } from '@/themes/theme' import NProgress from 'nprogress' -import LoadingCover from '@/components/LoadingCover' import { getQueryVariable, isBrowser } from './utils' const GlobalContext = createContext() @@ -22,7 +21,7 @@ export function GlobalContextProvider({ children }) { const [theme, setTheme] = useState(BLOG.THEME) // 默认博客主题 const [isDarkMode, updateDarkMode] = useState(BLOG.APPEARANCE === 'dark') // 默认深色模式 const [onLoading, setOnLoading] = useState(false) // 抓取文章数据 - const [onReading, setOnReading] = useState(false) // 网页资源加载 + // const [onReading, setOnReading] = useState(false) // 网页资源加载 useEffect(() => { initLocale(lang, locale, updateLang, updateLocale) @@ -34,7 +33,7 @@ export function GlobalContextProvider({ children }) { // setOnReading(true) } // 监听页面元素加载完 - setOnReading(false) + // setOnReading(false) window.addEventListener('beforeunload', handleBeforeUnload) return () => { window.removeEventListener('beforeunload', handleBeforeUnload) @@ -88,10 +87,8 @@ export function GlobalContextProvider({ children }) { updateDarkMode, theme, setTheme, - switchTheme, - setOnReading + switchTheme }}> - {children} ) diff --git a/themes/gitbook/LayoutBase.js b/themes/gitbook/LayoutBase.js index 09cb681c..970a3e55 100644 --- a/themes/gitbook/LayoutBase.js +++ b/themes/gitbook/LayoutBase.js @@ -38,6 +38,8 @@ const LayoutBase = props => {
    + {/* 顶部导航栏 */} +
    @@ -56,11 +58,9 @@ const LayoutBase = props => {
    -
    - {/* 顶部导航栏 */} - +
    -
    +
    {slotTop} {onLoading ? LoadingCover : children} @@ -80,6 +80,21 @@ const LayoutBase = props => {
    + {/* 左侧推拉抽屉 */} +
    +
    + + {slotLeft} +
    + {router.pathname !== '/search' && } + {showInfoCard && } + {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && } +
    +
    + +
    +
    + {/* 移动端底部导航栏 */} diff --git a/themes/gitbook/components/LogoBar.js b/themes/gitbook/components/LogoBar.js index cbe59474..a7fceebd 100644 --- a/themes/gitbook/components/LogoBar.js +++ b/themes/gitbook/components/LogoBar.js @@ -1,12 +1,14 @@ +import BLOG from '@/blog.config' import Link from 'next/link' -export default function LogoBar (props) { +export default function LogoBar(props) { const { siteInfo } = props return ( -
    - - {siteInfo?.title} - -
    - ); +
    + + {/* eslint-disable-next-line @next/next/no-img-element */} + {BLOG.AUTHOR} {siteInfo?.title} + +
    + ) } diff --git a/themes/gitbook/components/MenuItemDrop.js b/themes/gitbook/components/MenuItemDrop.js index e9d1b9f3..92cd9142 100644 --- a/themes/gitbook/components/MenuItemDrop.js +++ b/themes/gitbook/components/MenuItemDrop.js @@ -17,7 +17,7 @@ export const MenuItemDrop = ({ link }) => { return
  • changeShow(true)} onMouseOut={() => changeShow(false)} > {hasSubMenu && -
    {link?.icon && } {link?.name} @@ -27,7 +27,7 @@ export const MenuItemDrop = ({ link }) => { } {!hasSubMenu && -
    {link?.icon && } {link?.name} diff --git a/themes/gitbook/components/TopNavBar.js b/themes/gitbook/components/TopNavBar.js index b4e01345..8b07a5de 100644 --- a/themes/gitbook/components/TopNavBar.js +++ b/themes/gitbook/components/TopNavBar.js @@ -42,7 +42,7 @@ export default function TopNavBar(props) { } return ( -
    +
    {/* 移动端折叠菜单 */} diff --git a/themes/medium/LayoutBase.js b/themes/medium/LayoutBase.js index 19948d25..25c8be11 100644 --- a/themes/medium/LayoutBase.js +++ b/themes/medium/LayoutBase.js @@ -21,7 +21,7 @@ const ThemeGlobalMedium = createContext() * @constructor */ const LayoutBase = props => { - const { children, meta, showInfoCard = true, slotLeft, slotTop, siteInfo } = props + const { children, meta, showInfoCard = true, slotRight, slotTop, siteInfo } = props const { locale } = useGlobal() const router = useRouter() const [tocVisible, changeTocVisible] = useState(false) @@ -43,7 +43,7 @@ const LayoutBase = props => { {/* 桌面端左侧菜单 */} {/* */} -
    +
    {/* 顶部导航栏 */} @@ -71,7 +71,7 @@ const LayoutBase = props => {
    - {slotLeft} + {slotRight}
    {router.pathname !== '/search' && } {showInfoCard && } diff --git a/themes/medium/components/MenuItemDrop.js b/themes/medium/components/MenuItemDrop.js index e9d1b9f3..92cd9142 100644 --- a/themes/medium/components/MenuItemDrop.js +++ b/themes/medium/components/MenuItemDrop.js @@ -17,7 +17,7 @@ export const MenuItemDrop = ({ link }) => { return
  • changeShow(true)} onMouseOut={() => changeShow(false)} > {hasSubMenu && -
    {link?.icon && } {link?.name} @@ -27,7 +27,7 @@ export const MenuItemDrop = ({ link }) => { } {!hasSubMenu && -
    {link?.icon && } {link?.name} From 190bc50d9a8c6d5ac7fd38ee6e1b3be0ce48f5e0 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Fri, 23 Jun 2023 19:55:01 +0800 Subject: [PATCH 03/12] gitbook --- themes/gitbook/LayoutBase.js | 44 +++++++------ themes/gitbook/LayoutIndex.js | 8 +-- themes/gitbook/LayoutSlug.js | 19 +++--- themes/gitbook/components/Announcement.js | 21 +++++++ themes/gitbook/components/ArticleInfo.js | 9 +++ themes/gitbook/components/BlogPostCard.js | 61 ++----------------- .../gitbook/components/BlogPostListScroll.js | 15 +---- themes/gitbook/components/Footer.js | 2 +- themes/medium/LayoutBase.js | 4 +- themes/medium/components/Announcement.js | 21 +++++++ 10 files changed, 94 insertions(+), 110 deletions(-) create mode 100755 themes/gitbook/components/Announcement.js create mode 100644 themes/gitbook/components/ArticleInfo.js create mode 100755 themes/medium/components/Announcement.js diff --git a/themes/gitbook/LayoutBase.js b/themes/gitbook/LayoutBase.js index 970a3e55..8ceb9442 100644 --- a/themes/gitbook/LayoutBase.js +++ b/themes/gitbook/LayoutBase.js @@ -12,6 +12,8 @@ import { useGlobal } from '@/lib/global' import { useRouter } from 'next/router' import Live2D from '@/components/Live2D' import BLOG from '@/blog.config' +import BlogPostListScroll from './components/BlogPostListScroll' +import ArticleInfo from './components/ArticleInfo' const ThemeGlobalMedium = createContext() /** @@ -21,7 +23,7 @@ const ThemeGlobalMedium = createContext() * @constructor */ const LayoutBase = props => { - const { children, meta, showInfoCard = true, slotLeft, slotTop, siteInfo } = props + const { children, meta, posts, post, showInfoCard = true, slotLeft, slotRight, slotTop, siteInfo } = props const { locale } = useGlobal() const router = useRouter() const [tocVisible, changeTocVisible] = useState(false) @@ -45,22 +47,20 @@ const LayoutBase = props => { {/* 左侧推拉抽屉 */}
    -
    - - {slotLeft} -
    - {router.pathname !== '/search' && } - {showInfoCard && } - {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && } -
    -
    - +
    + {slotLeft} + + {router.pathname !== '/search' && } + + {/* 所有文章列表 */} + +
    -
    +
    -
    +
    {slotTop} {onLoading ? LoadingCover : children} @@ -80,17 +80,15 @@ const LayoutBase = props => {
    - {/* 左侧推拉抽屉 */} -
    + {/* 右侧侧推拉抽屉 */} +
    - - {slotLeft} -
    - {router.pathname !== '/search' && } - {showInfoCard && } - {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && } -
    -
    + {slotRight} + +
    + + {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && } +
    diff --git a/themes/gitbook/LayoutIndex.js b/themes/gitbook/LayoutIndex.js index 41410467..6071f9fc 100644 --- a/themes/gitbook/LayoutIndex.js +++ b/themes/gitbook/LayoutIndex.js @@ -1,11 +1,11 @@ -import BLOG from '@/blog.config' -import BlogPostListPage from './components/BlogPostListPage' -import BlogPostListScroll from './components/BlogPostListScroll' import LayoutBase from './LayoutBase' +import Announcement from './components/Announcement' +import ArticleInfo from './components/ArticleInfo' export const LayoutIndex = (props) => { return - {BLOG.POST_LIST_STYLE === 'page' ? : } + {/* gitbook主题首页只显示公告 */} + } diff --git a/themes/gitbook/LayoutSlug.js b/themes/gitbook/LayoutSlug.js index 68308ab7..78b0f5b2 100644 --- a/themes/gitbook/LayoutSlug.js +++ b/themes/gitbook/LayoutSlug.js @@ -15,7 +15,7 @@ import CategoryItem from './components/CategoryItem' import TagItemMini from './components/TagItemMini' import ShareBar from '@/components/ShareBar' -export const LayoutSlug = props => { +export const LayoutSlug = (props) => { const { post, prev, next, siteInfo, lock, validPassword } = props const { locale } = useGlobal() @@ -23,20 +23,15 @@ export const LayoutSlug = props => { post?.date?.start_date || post?.createdTime, locale.LOCALE ) + + const slotRight = post?.toc && post?.toc?.length > 3 && + console.log(slotRight, post, 'jhhh') + if (!post) { - return + return } - - const slotLeft = post?.toc && post?.toc?.length > 3 && ( -
    - - {/* */} -
    - ) - return ( - + {/* 文章锁 */} {lock && } diff --git a/themes/gitbook/components/Announcement.js b/themes/gitbook/components/Announcement.js new file mode 100755 index 00000000..62df1ec2 --- /dev/null +++ b/themes/gitbook/components/Announcement.js @@ -0,0 +1,21 @@ +// import { useGlobal } from '@/lib/global' +import dynamic from 'next/dynamic' + +const NotionPage = dynamic(() => import('@/components/NotionPage')) + +const Announcement = ({ notice, className }) => { +// const { locale } = useGlobal() + if (notice?.blockMap) { + return
    +
    + {/*
    {locale.COMMON.ANNOUNCEMENT}
    */} + {notice && (
    + +
    )} +
    +
    + } else { + return <> + } +} +export default Announcement diff --git a/themes/gitbook/components/ArticleInfo.js b/themes/gitbook/components/ArticleInfo.js new file mode 100644 index 00000000..b2d58efe --- /dev/null +++ b/themes/gitbook/components/ArticleInfo.js @@ -0,0 +1,9 @@ +export default function ArticleInfo({ post }) { + if (!post) { + return null + } + return
    + + Last update: { post.date?.start_date} +
    +} diff --git a/themes/gitbook/components/BlogPostCard.js b/themes/gitbook/components/BlogPostCard.js index 998dd086..fd277508 100644 --- a/themes/gitbook/components/BlogPostCard.js +++ b/themes/gitbook/components/BlogPostCard.js @@ -1,80 +1,27 @@ import BLOG from '@/blog.config' -import NotionPage from '@/components/NotionPage' -import { useGlobal } from '@/lib/global' import Link from 'next/link' import React from 'react' -import CONFIG_MEDIUM from '../config_medium' -import CategoryItem from './CategoryItem' -import TagItemMini from './TagItemMini' -import TwikooCommentCount from '@/components/TwikooCommentCount' const BlogPostCard = ({ post, showSummary }) => { - const showPreview = CONFIG_MEDIUM.POST_LIST_PREVIEW && post.blockMap - const { locale } = useGlobal() return (
    -
    +
    - {CONFIG_MEDIUM.POST_LIST_COVER &&
    - {/* eslint-disable-next-line @next/next/no-img-element */} - -
    } - {post.title} + {post.category} - {post.title}
    -
    -
    {post.date?.start_date}
    - {CONFIG_MEDIUM.POST_LIST_CATEGORY && } - {CONFIG_MEDIUM.POST_LIST_TAG && post?.tagItems?.map(tag => )} - -
    - -
    - - {(!showPreview || showSummary) && ( -

    - {post.summary} -

    - )} - - {showPreview && ( -
    - -
    -
    - - - {locale.COMMON.ARTICLE_DETAIL} - - - -
    -
    -
    - )}
    ) diff --git a/themes/gitbook/components/BlogPostListScroll.js b/themes/gitbook/components/BlogPostListScroll.js index 2c7eafbd..2212d51e 100644 --- a/themes/gitbook/components/BlogPostListScroll.js +++ b/themes/gitbook/components/BlogPostListScroll.js @@ -1,7 +1,6 @@ import BLOG from '@/blog.config' import BlogPostCard from './BlogPostCard' import BlogPostListEmpty from './BlogPostListEmpty' -import { useGlobal } from '@/lib/global' import throttle from 'lodash.throttle' import React, { useCallback, useEffect, useRef, useState } from 'react' import { useRouter } from 'next/router' @@ -17,7 +16,8 @@ const BlogPostListScroll = ({ posts = [], currentSearch }) => { const postsPerPage = BLOG.POSTS_PER_PAGE const [page, updatePage] = useState(1) let filteredPosts = Object.assign(posts) - const searchKey = getSearchKey() + const router = useRouter() + const searchKey = getSearchKey(router) if (searchKey) { filteredPosts = posts.filter(post => { const tagContent = post.tags ? post.tags.join(' ') : '' @@ -56,7 +56,6 @@ const BlogPostListScroll = ({ posts = [], currentSearch }) => { }) const targetRef = useRef(null) - const { locale } = useGlobal() if (!postsToShow || postsToShow.length === 0) { return @@ -70,13 +69,6 @@ const BlogPostListScroll = ({ posts = [], currentSearch }) => { ))}
    -
    -
    { - handleGetMore() - }} - className='w-full my-4 py-4 text-center cursor-pointer dark:text-gray-200' - > {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}
    -
    } } @@ -95,8 +87,7 @@ const getPostByPage = function (page, totalPosts, postsPerPage) { ) } -function getSearchKey() { - const router = useRouter() +function getSearchKey(router) { if (router.query && router.query.s) { return router.query.s } diff --git a/themes/gitbook/components/Footer.js b/themes/gitbook/components/Footer.js index b9d4f49c..cde8885e 100644 --- a/themes/gitbook/components/Footer.js +++ b/themes/gitbook/components/Footer.js @@ -14,7 +14,7 @@ const Footer = ({ title }) => { return (
    {`${copyrightDate}`} {BLOG.AUTHOR}.
    diff --git a/themes/medium/LayoutBase.js b/themes/medium/LayoutBase.js index 25c8be11..a50a071b 100644 --- a/themes/medium/LayoutBase.js +++ b/themes/medium/LayoutBase.js @@ -12,6 +12,7 @@ import { useGlobal } from '@/lib/global' import { useRouter } from 'next/router' import Live2D from '@/components/Live2D' import BLOG from '@/blog.config' +import Announcement from './components/Announcement' const ThemeGlobalMedium = createContext() /** @@ -21,7 +22,7 @@ const ThemeGlobalMedium = createContext() * @constructor */ const LayoutBase = props => { - const { children, meta, showInfoCard = true, slotRight, slotTop, siteInfo } = props + const { children, meta, showInfoCard = true, slotRight, slotTop, siteInfo, notice } = props const { locale } = useGlobal() const router = useRouter() const [tocVisible, changeTocVisible] = useState(false) @@ -78,6 +79,7 @@ const LayoutBase = props => { {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && }
    +
    diff --git a/themes/medium/components/Announcement.js b/themes/medium/components/Announcement.js new file mode 100755 index 00000000..854aa388 --- /dev/null +++ b/themes/medium/components/Announcement.js @@ -0,0 +1,21 @@ +// import { useGlobal } from '@/lib/global' +import dynamic from 'next/dynamic' + +const NotionPage = dynamic(() => import('@/components/NotionPage')) + +const Announcement = ({ post, className }) => { +// const { locale } = useGlobal() + if (post?.blockMap) { + return
    +
    + {/*
    {locale.COMMON.ANNOUNCEMENT}
    */} + {post && (
    + +
    )} +
    +
    + } else { + return <> + } +} +export default Announcement From b5c1752666beb97b992f44e28c6c8bc11607ce02 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Fri, 23 Jun 2023 22:25:28 +0800 Subject: [PATCH 04/12] medium --- themes/medium/LayoutSlug.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/themes/medium/LayoutSlug.js b/themes/medium/LayoutSlug.js index 68308ab7..1d235f32 100644 --- a/themes/medium/LayoutSlug.js +++ b/themes/medium/LayoutSlug.js @@ -24,19 +24,18 @@ export const LayoutSlug = props => { locale.LOCALE ) if (!post) { - return + return } - const slotLeft = post?.toc && post?.toc?.length > 3 && ( -
    + const slotRight = post?.toc && post?.toc?.length >= 3 && ( +
    {/* */}
    ) return ( - + {/* 文章锁 */} {lock && } From c14ca330eb82a861ad0172479ce838ea862728a1 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Fri, 23 Jun 2023 23:35:03 +0800 Subject: [PATCH 05/12] group-nav-page --- components/DarkModeButton.js | 5 +- lib/notion/getNotionData.js | 35 ++++++++ pages/[...slug].js | 41 +++++---- styles/notion.css | 1 - themes/gitbook/LayoutBase.js | 47 +++++----- themes/gitbook/LayoutIndex.js | 1 - themes/gitbook/LayoutSearch.js | 2 +- themes/gitbook/LayoutSlug.js | 47 ++-------- themes/gitbook/components/BlogPostCard.js | 14 ++- .../gitbook/components/BlogPostListScroll.js | 85 ++----------------- themes/gitbook/components/Catalog.js | 29 +++---- themes/gitbook/components/Footer.js | 34 ++++---- themes/gitbook/components/MenuItemDrop.js | 4 +- themes/gitbook/components/RevolverMaps.js | 2 +- themes/gitbook/components/SearchInput.js | 52 +++++++++--- themes/gitbook/components/TopNavBar.js | 2 + 16 files changed, 182 insertions(+), 219 deletions(-) diff --git a/components/DarkModeButton.js b/components/DarkModeButton.js index f1f8784d..62bace09 100644 --- a/components/DarkModeButton.js +++ b/components/DarkModeButton.js @@ -13,9 +13,8 @@ const DarkModeButton = (props) => { htmlElement.classList?.add(newStatus ? 'dark' : 'light') } - return
    - + return
    +
    } export default DarkModeButton diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js index 977193b2..f2550855 100644 --- a/lib/notion/getNotionData.js +++ b/lib/notion/getNotionData.js @@ -26,6 +26,7 @@ export async function getGlobalNotionData({ }) { // 获取Notion数据 const notionPageData = deepClone(await getNotionPageData({ pageId, from })) + notionPageData.allNavPages = getNavPages({ allPages: notionPageData.allPages }) delete notionPageData.block delete notionPageData.schema delete notionPageData.rawMetadata @@ -168,6 +169,37 @@ function getSiteInfo({ collection, block }) { return { title, description, pageCover, icon } } +/** + * 获取导航pages + * 转为gitbook这类文档主题设计,精减的标题和内容 + * 导航页面的条件,必须是Posts + * @param {*} param0 + */ +export function getNavPages({ allPages }) { + const allNavPages = allPages.filter(post => { + return post && post?.slug && (!post?.slug?.startsWith('http')) && post?.type === 'Post' && post?.status === 'Published' + }) + const result = allNavPages.map(item => ({ id: item.id, title: item.title, category: item.category || null, tags: item.tags || null, summary: item.summary || null, slug: item.slug })) + + const groupedArray = result.reduce((groups, item) => { + const categoryName = item.category ? item.category.join('/') : '' // 将category转换为字符串 + const lastGroup = groups[groups.length - 1] // 获取最后一个分组 + + if (!lastGroup || lastGroup.category !== categoryName) { // 如果当前元素的category与上一个元素不同,则创建新分组 + groups.push({ category: categoryName, items: [] }) + } + + groups[groups.length - 1].items.push(item) // 将元素加入对应的分组 + + return groups + }, []) + + return groupedArray +} + +/** + * 获取公告 + */ async function getNotice(post) { if (!post) { return null @@ -183,6 +215,7 @@ const EmptyData = (pageId) => { notice: null, siteInfo: getSiteInfo({}), allPages: [{ id: 1, title: `无法获取Notion数据,请检查Notion_ID: \n 当前 ${pageId}`, summary: '访问文档获取帮助→ https://tangly1024.com/article/vercel-deploy-notion-next', status: 'Published', type: 'Post', slug: '13a171332816461db29d50e9f575b00d', date: { start_date: '2023-04-24', lastEditedTime: '2023-04-24', tagItems: [] } }], + allNavPages: [], collection: [], collectionQuery: {}, collectionId: null, @@ -275,11 +308,13 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) { // 新的菜单 const customMenu = await getCustomMenu({ collectionData }) const latestPosts = getLatestPosts({ allPages, from, latestPostCount: 5 }) + const allNavPages = getNavPages({ allPages }) return { notice, siteInfo, allPages, + allNavPages, collection, collectionQuery, collectionId, diff --git a/pages/[...slug].js b/pages/[...slug].js index f28b0a42..a39e81d6 100644 --- a/pages/[...slug].js +++ b/pages/[...slug].js @@ -4,11 +4,10 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData' import { useEffect, useState } from 'react' import { idToUuid } from 'notion-utils' import { useRouter } from 'next/router' -import { isBrowser } from '@/lib/utils' import { getNotion } from '@/lib/notion/getNotion' import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents' -import md5 from 'js-md5' import { getLayoutByTheme } from '@/themes/theme' +import md5 from 'js-md5' /** * 根据notion的slug访问页面 @@ -19,16 +18,13 @@ const Slug = props => { const { post, siteInfo } = props const router = useRouter() - // 根据页面路径加载不同Layout文件 - const Layout = getLayoutByTheme(useRouter()) - // 文章锁🔐 const [lock, setLock] = useState(post?.password && post?.password !== '') /** - * 验证文章密码 - * @param {*} result - */ + * 验证文章密码 + * @param {*} result + */ const validPassword = passInput => { const encrypt = md5(post.slug + passInput) if (passInput && encrypt === post.password) { @@ -41,28 +37,28 @@ const Slug = props => { // 文章加载 useEffect(() => { // 404 - if (!post) { - setTimeout(() => { - if (isBrowser()) { - const article = document.getElementById('notion-article') - if (!article) { - router.push('/404').then(() => { - console.warn('找不到页面', router.asPath) - }) - } - } - }, 8 * 1000) // 404时长 8秒 - } + // if (!post) { + // setTimeout(() => { + // if (isBrowser()) { + // const article = document.getElementById('notion-article') + // if (!article) { + // router.push('/404').then(() => { + // console.warn('找不到页面', router.asPath) + // }) + // } + // } + // }, 8 * 1000) // 404时长 8秒 + // } // 文章加密 if (post?.password && post?.password !== '') { setLock(true) } else { + setLock(false) if (!lock && 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) } - setLock(false) } router.events.on('routeChangeComplete', () => { window.scrollTo({ top: 0, behavior: 'smooth' }) @@ -79,7 +75,8 @@ const Slug = props => { tags: post?.tags } props = { ...props, lock, meta, setLock, validPassword } - + // 根据页面路径加载不同Layout文件 + const Layout = getLayoutByTheme(useRouter()) return } diff --git a/styles/notion.css b/styles/notion.css index c309b68b..746189ec 100644 --- a/styles/notion.css +++ b/styles/notion.css @@ -1142,7 +1142,6 @@ code[class*='language-'] { overflow: hidden; text-overflow: ellipsis; - @apply text-blue-600 dark:text-blue-200 } .notion-table-of-contents-item:hover { diff --git a/themes/gitbook/LayoutBase.js b/themes/gitbook/LayoutBase.js index 8ceb9442..457fcdc6 100644 --- a/themes/gitbook/LayoutBase.js +++ b/themes/gitbook/LayoutBase.js @@ -1,19 +1,19 @@ import CommonHead from '@/components/CommonHead' -import { useState, createContext, useContext } from 'react' +import { useState, createContext, useContext, useEffect } from 'react' import Footer from './components/Footer' import InfoCard from './components/InfoCard' import RevolverMaps from './components/RevolverMaps' import CONFIG_MEDIUM from './config_medium' -import Tabs from '@/components/Tabs' import TopNavBar from './components/TopNavBar' import SearchInput from './components/SearchInput' import BottomMenuBar from './components/BottomMenuBar' import { useGlobal } from '@/lib/global' -import { useRouter } from 'next/router' import Live2D from '@/components/Live2D' import BLOG from '@/blog.config' import BlogPostListScroll from './components/BlogPostListScroll' import ArticleInfo from './components/ArticleInfo' +import Catalog from './components/Catalog' +import { useRouter } from 'next/router' const ThemeGlobalMedium = createContext() /** @@ -22,12 +22,16 @@ const ThemeGlobalMedium = createContext() * @returns {JSX.Element} * @constructor */ -const LayoutBase = props => { - const { children, meta, posts, post, showInfoCard = true, slotLeft, slotRight, slotTop, siteInfo } = props - const { locale } = useGlobal() - const router = useRouter() +const LayoutBase = (props) => { + const { children, meta, post, allNavPages, slotLeft, slotRight, slotTop, siteInfo } = props const [tocVisible, changeTocVisible] = useState(false) + const [filterPosts, setFilterPosts] = useState(allNavPages) const { onLoading } = useGlobal() + const router = useRouter() + + useEffect(() => { + setFilterPosts(allNavPages) + }, [post]) const LoadingCover =
    @@ -36,7 +40,7 @@ const LayoutBase = props => {
    return ( - +
    @@ -46,21 +50,21 @@ const LayoutBase = props => {
    {/* 左侧推拉抽屉 */} -
    +
    -
    +
    {slotTop} {onLoading ? LoadingCover : children} @@ -81,15 +85,20 @@ const LayoutBase = props => {
    {/* 右侧侧推拉抽屉 */} -
    +
    - {slotRight} - -
    - - {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && } + + +
    + + {slotRight} + {router.route === '/' && <> + + {CONFIG_MEDIUM.WIDGET_REVOLVER_MAPS === 'true' && } + + }
    - +
    diff --git a/themes/gitbook/LayoutIndex.js b/themes/gitbook/LayoutIndex.js index 6071f9fc..50c89f12 100644 --- a/themes/gitbook/LayoutIndex.js +++ b/themes/gitbook/LayoutIndex.js @@ -1,6 +1,5 @@ import LayoutBase from './LayoutBase' import Announcement from './components/Announcement' -import ArticleInfo from './components/ArticleInfo' export const LayoutIndex = (props) => { return diff --git a/themes/gitbook/LayoutSearch.js b/themes/gitbook/LayoutSearch.js index 1aaf3d20..eaecbd84 100644 --- a/themes/gitbook/LayoutSearch.js +++ b/themes/gitbook/LayoutSearch.js @@ -30,7 +30,7 @@ export const LayoutSearch = (props) => { } }, 100) - }) + }, [currentSearch]) return
    diff --git a/themes/gitbook/LayoutSlug.js b/themes/gitbook/LayoutSlug.js index 78b0f5b2..f3b7d058 100644 --- a/themes/gitbook/LayoutSlug.js +++ b/themes/gitbook/LayoutSlug.js @@ -1,11 +1,6 @@ import LayoutBase from './LayoutBase' -import { useGlobal } from '@/lib/global' import React from 'react' -import Catalog from './components/Catalog' import { ArticleLock } from './components/ArticleLock' -import formatDate from '@/lib/formatDate' -import BLOG from '@/blog.config' -import Link from 'next/link' import NotionPage from '@/components/NotionPage' import CONFIG_MEDIUM from './config_medium' import Comment from '@/components/Comment' @@ -16,22 +11,14 @@ import TagItemMini from './components/TagItemMini' import ShareBar from '@/components/ShareBar' export const LayoutSlug = (props) => { - const { post, prev, next, siteInfo, lock, validPassword } = props - const { locale } = useGlobal() - - const date = formatDate( - post?.date?.start_date || post?.createdTime, - locale.LOCALE - ) - - const slotRight = post?.toc && post?.toc?.length > 3 && - console.log(slotRight, post, 'jhhh') + const { post, prev, next, lock, validPassword } = props if (!post) { return } + return ( - + {/* 文章锁 */} {lock && } @@ -40,30 +27,8 @@ export const LayoutSlug = (props) => { {/* title */}

    {post?.title}

    - {/* meta */} -
    -
    - {date} - | - {post.lastEditedTime} -
    - -
    -
    - -
    - {/* eslint-disable-next-line @next/next/no-img-element */} - {BLOG.AUTHOR} - -
    - {BLOG.AUTHOR} -
    -
    - -
    - {/* Notion文章主体 */} -
    +
    {post && ()}
    @@ -73,13 +38,13 @@ export const LayoutSlug = (props) => { {/* 文章分类和标签信息 */}
    - {CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && } + {CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post?.category && }
    {CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => )}
    - {post.type === 'Post' && } + {post?.type === 'Post' && }
    diff --git a/themes/gitbook/components/BlogPostCard.js b/themes/gitbook/components/BlogPostCard.js index fd277508..299bc7f3 100644 --- a/themes/gitbook/components/BlogPostCard.js +++ b/themes/gitbook/components/BlogPostCard.js @@ -1,27 +1,25 @@ import BLOG from '@/blog.config' import Link from 'next/link' +import { useRouter } from 'next/router' import React from 'react' -const BlogPostCard = ({ post, showSummary }) => { +const BlogPostCard = ({ post }) => { + const router = useRouter() + const currentSelected = router.asPath.split('?')[0] === '/' + post.slug return ( -
    - +
    {post.category} - {post.title}
    -
    ) diff --git a/themes/gitbook/components/BlogPostListScroll.js b/themes/gitbook/components/BlogPostListScroll.js index 2212d51e..ae2f0951 100644 --- a/themes/gitbook/components/BlogPostListScroll.js +++ b/themes/gitbook/components/BlogPostListScroll.js @@ -1,9 +1,6 @@ -import BLOG from '@/blog.config' import BlogPostCard from './BlogPostCard' import BlogPostListEmpty from './BlogPostListEmpty' -import throttle from 'lodash.throttle' -import React, { useCallback, useEffect, useRef, useState } from 'react' -import { useRouter } from 'next/router' +import React, { useRef } from 'react' /** * 博客列表滚动分页 @@ -13,85 +10,19 @@ import { useRouter } from 'next/router' * @constructor */ const BlogPostListScroll = ({ posts = [], currentSearch }) => { - const postsPerPage = BLOG.POSTS_PER_PAGE - const [page, updatePage] = useState(1) - let filteredPosts = Object.assign(posts) - const router = useRouter() - const searchKey = getSearchKey(router) - if (searchKey) { - filteredPosts = posts.filter(post => { - const tagContent = post.tags ? post.tags.join(' ') : '' - const searchContent = post.title + post.summary + tagContent - return searchContent.toLowerCase().includes(searchKey.toLowerCase()) - }) - } - const postsToShow = getPostByPage(page, filteredPosts, postsPerPage) - - let hasMore = false - if (filteredPosts) { - const totalCount = filteredPosts.length - hasMore = page * postsPerPage < totalCount - } - - const handleGetMore = () => { - if (!hasMore) return - updatePage(page + 1) - } - - // 监听滚动自动分页加载 - const scrollTrigger = useCallback(throttle(() => { - const scrollS = window.scrollY + window.outerHeight - const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 - if (scrollS > clientHeight + 100) { - handleGetMore() - } - }, 500)) - - // 监听滚动 - useEffect(() => { - window.addEventListener('scroll', scrollTrigger) - return () => { - window.removeEventListener('scroll', scrollTrigger) - } - }) - const targetRef = useRef(null) + const filteredPosts = Object.assign(posts) - if (!postsToShow || postsToShow.length === 0) { + if (!filteredPosts || filteredPosts.length === 0) { return } else { return
    - - {/* 文章列表 */} -
    - {postsToShow?.map(post => ( - - ))} -
    - -
    + {/* 文章列表 */} + {filteredPosts?.map(post => ( + + ))} +
    } } -/** - * 获取从第1页到指定页码的文章 - * @param page 第几页 - * @param totalPosts 所有文章 - * @param postsPerPage 每页文章数量 - * @returns {*} - */ -const getPostByPage = function (page, totalPosts, postsPerPage) { - return totalPosts.slice( - 0, - postsPerPage * page - ) -} - -function getSearchKey(router) { - if (router.query && router.query.s) { - return router.query.s - } - return null -} - export default BlogPostListScroll diff --git a/themes/gitbook/components/Catalog.js b/themes/gitbook/components/Catalog.js index c9592dd2..a8f01fcf 100644 --- a/themes/gitbook/components/Catalog.js +++ b/themes/gitbook/components/Catalog.js @@ -1,7 +1,7 @@ -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import throttle from 'lodash.throttle' import { uuidToId } from 'notion-utils' -import Progress from './Progress' +import { isBrowser } from '@/lib/utils' /** * 目录导航组件 @@ -9,11 +9,9 @@ import Progress from './Progress' * @returns {JSX.Element} * @constructor */ -const Catalog = ({ toc }) => { +const Catalog = ({ post }) => { const tocIds = [] - - // 目录自动滚动 - const tRef = useRef(null) + const toc = post?.toc // 同步选中目录事件 const [activeSection, setActiveSection] = useState(null) @@ -24,7 +22,7 @@ const Catalog = ({ toc }) => { return () => { window.removeEventListener('scroll', actionSectionScrollSpy) } - }, []) + }, [post]) const throttleMs = 200 const actionSectionScrollSpy = useCallback(throttle(() => { @@ -51,19 +49,18 @@ const Catalog = ({ toc }) => { } setActiveSection(currentSectionId) const index = tocIds.indexOf(currentSectionId) || 0 - tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' }) + if (isBrowser()) { + document?.getElementById('toc-wrapper')?.scrollTo({ top: 28 * index, behavior: 'smooth' }) + } }, throttleMs)) // 无目录就直接返回空 if (!toc || toc.length < 1) { - return <> + return null } - return
    -
    - -
    -
    + return <> +
    -
    + } export default Catalog diff --git a/themes/gitbook/components/Footer.js b/themes/gitbook/components/Footer.js index cde8885e..744f9e61 100644 --- a/themes/gitbook/components/Footer.js +++ b/themes/gitbook/components/Footer.js @@ -5,7 +5,7 @@ import DarkModeButton from '@/components/DarkModeButton' const Footer = ({ title }) => { const d = new Date() const currentYear = d.getFullYear() - const copyrightDate = (function() { + const copyrightDate = (function () { if (Number.isInteger(BLOG.SINCE) && BLOG.SINCE < currentYear) { return BLOG.SINCE + '-' + currentYear } @@ -13,22 +13,26 @@ const Footer = ({ title }) => { })() return ( - ) } diff --git a/themes/gitbook/components/MenuItemDrop.js b/themes/gitbook/components/MenuItemDrop.js index 92cd9142..3ef482b5 100644 --- a/themes/gitbook/components/MenuItemDrop.js +++ b/themes/gitbook/components/MenuItemDrop.js @@ -17,7 +17,7 @@ export const MenuItemDrop = ({ link }) => { return
  • changeShow(true)} onMouseOut={() => changeShow(false)} > {hasSubMenu && -
    {link?.icon && } {link?.name} @@ -27,7 +27,7 @@ export const MenuItemDrop = ({ link }) => { } {!hasSubMenu && -
    {link?.icon && } {link?.name} diff --git a/themes/gitbook/components/RevolverMaps.js b/themes/gitbook/components/RevolverMaps.js index d839d85d..c6eb6252 100644 --- a/themes/gitbook/components/RevolverMaps.js +++ b/themes/gitbook/components/RevolverMaps.js @@ -7,7 +7,7 @@ export default function RevolverMaps () { initRevolverMaps() changeLoad(true) } - }) + }, []) return
    } diff --git a/themes/gitbook/components/SearchInput.js b/themes/gitbook/components/SearchInput.js index f6c84d9c..6828d111 100644 --- a/themes/gitbook/components/SearchInput.js +++ b/themes/gitbook/components/SearchInput.js @@ -1,11 +1,11 @@ -import { useRouter } from 'next/router' import { useImperativeHandle, useRef, useState } from 'react' +import { useMediumGlobal } from '../LayoutBase' let lock = false -const SearchInput = ({ currentTag, currentSearch, cRef, className }) => { - const [onLoading, setLoadingState] = useState(false) - const router = useRouter() +const SearchInput = ({ currentSearch, cRef, className }) => { const searchInputRef = useRef() + const { setFilterPosts, allNavPages } = useMediumGlobal() + useImperativeHandle(cRef, () => { return { focus: () => { @@ -15,15 +15,43 @@ const SearchInput = ({ currentTag, currentSearch, cRef, className }) => { }) const handleSearch = () => { - const key = searchInputRef.current.value - - if (key && key !== '') { - setLoadingState(true) - location.href = '/search/' + key + let keyword = searchInputRef.current.value + const filterPosts = [] + if (keyword) { + keyword = keyword.trim() } else { - router.push({ pathname: '/' }).then(r => { - }) + setFilterPosts(allNavPages) } + for (const post of allNavPages) { + const tagContent = post.tags && Array.isArray(post.tags) ? post.tags.join(' ') : '' + const categoryContent = post.category && Array.isArray(post.category) ? post.category.join(' ') : '' + const articleInfo = post.title + post.summary + tagContent + categoryContent + let hit = articleInfo.toLowerCase().indexOf(keyword) > -1 + const indexContent = [post.summary] + // console.log('全文搜索缓存', cacheKey, page != null) + post.results = [] + let hitCount = 0 + for (const i in indexContent) { + const c = indexContent[i] + if (!c) { + continue + } + const index = c.toLowerCase().indexOf(keyword.toLowerCase()) + if (index > -1) { + hit = true + hitCount += 1 + post.results.push(c) + } else { + if ((post.results.length - 1) / hitCount < 3 || i === 0) { + post.results.push(c) + } + } + } + if (hit) { + filterPosts.push(post) + } + } + setFilterPosts(filterPosts) } const handleKeyUp = (e) => { if (e.keyCode === 13) { // 回车 @@ -72,7 +100,7 @@ const SearchInput = ({ currentTag, currentSearch, cRef, className }) => {
    - +
    {(showClean && diff --git a/themes/gitbook/components/TopNavBar.js b/themes/gitbook/components/TopNavBar.js index 8b07a5de..e5081945 100644 --- a/themes/gitbook/components/TopNavBar.js +++ b/themes/gitbook/components/TopNavBar.js @@ -6,6 +6,7 @@ import { useGlobal } from '@/lib/global' import CONFIG_MEDIUM from '../config_medium' import BLOG from '@/blog.config' import { MenuItemDrop } from './MenuItemDrop' +import DarkModeButton from '@/components/DarkModeButton' /** * 顶部导航栏 + 菜单 @@ -67,6 +68,7 @@ export default function TopNavBar(props) { {/* 桌面端顶部菜单 */}
    {links && links?.map(link => )} +
    From 505f713241d38cbe1ef5272694ec2077b70e41f7 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Sat, 24 Jun 2023 11:27:30 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=E5=88=86=E7=BB=84-page-nav?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- themes/gitbook/components/BlogPostCard.js | 6 +++--- themes/gitbook/components/BlogPostListScroll.js | 13 ++++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/themes/gitbook/components/BlogPostCard.js b/themes/gitbook/components/BlogPostCard.js index 299bc7f3..7dc9db14 100644 --- a/themes/gitbook/components/BlogPostCard.js +++ b/themes/gitbook/components/BlogPostCard.js @@ -3,7 +3,7 @@ import Link from 'next/link' import { useRouter } from 'next/router' import React from 'react' -const BlogPostCard = ({ post }) => { +const BlogPostCard = ({ post, className }) => { const router = useRouter() const currentSelected = router.asPath.split('?')[0] === '/' + post.slug return ( @@ -13,10 +13,10 @@ const BlogPostCard = ({ post }) => { href={`${BLOG.SUB_PATH}/${post.slug}`} passHref className={ - `${currentSelected ? 'bg-gray-500 text-white' : 'text-gray-700 dark:text-gray-300 '} hover:font-bold py-0.5 px-1 text-sm cursor-pointer` + `${className} ${currentSelected ? 'bg-gray-500 text-white' : 'text-gray-700 dark:text-gray-300 '} hover:font-bold py-0.5 cursor-pointer` }>
    - {post.category} - {post.title} + {post.title}
    diff --git a/themes/gitbook/components/BlogPostListScroll.js b/themes/gitbook/components/BlogPostListScroll.js index ae2f0951..b8269a4d 100644 --- a/themes/gitbook/components/BlogPostListScroll.js +++ b/themes/gitbook/components/BlogPostListScroll.js @@ -18,9 +18,16 @@ const BlogPostListScroll = ({ posts = [], currentSearch }) => { } else { return
    {/* 文章列表 */} - {filteredPosts?.map(post => ( - - ))} + {filteredPosts?.map(group => { + if (group.category) { + return <> +
    {group.category}
    + {group.items?.map(post => (
    ))} + + } else { + return <> {group.items?.map(post => ())} + } + })}
    } } From 80fc0e29e8fdf6eb9f2b2701d3efbe2bf5e07c7f Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Sat, 24 Jun 2023 12:06:03 +0800 Subject: [PATCH 07/12] =?UTF-8?q?gitbook=E9=A6=96=E9=A1=B5=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/[...slug].js | 26 ++++++++-------- themes/gitbook/LayoutBase.js | 13 ++++---- themes/gitbook/LayoutIndex.js | 31 +++++++++++++++++--- themes/gitbook/LayoutSlug.js | 16 ++++------ themes/gitbook/components/JumpToTopButton.js | 4 +-- themes/gitbook/components/MenuBarMobile.js | 10 +++---- themes/gitbook/components/TopNavBar.js | 10 +++---- themes/gitbook/config_gitbook.js | 15 ++++++++++ themes/gitbook/config_medium.js | 24 --------------- themes/gitbook/index.js | 4 +-- 10 files changed, 84 insertions(+), 69 deletions(-) create mode 100644 themes/gitbook/config_gitbook.js delete mode 100644 themes/gitbook/config_medium.js diff --git a/pages/[...slug].js b/pages/[...slug].js index a39e81d6..511ca761 100644 --- a/pages/[...slug].js +++ b/pages/[...slug].js @@ -8,6 +8,7 @@ import { getNotion } from '@/lib/notion/getNotion' import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents' import { getLayoutByTheme } from '@/themes/theme' import md5 from 'js-md5' +import { isBrowser } from '@/lib/utils' /** * 根据notion的slug访问页面 @@ -37,18 +38,18 @@ const Slug = props => { // 文章加载 useEffect(() => { // 404 - // if (!post) { - // setTimeout(() => { - // if (isBrowser()) { - // const article = document.getElementById('notion-article') - // if (!article) { - // router.push('/404').then(() => { - // console.warn('找不到页面', router.asPath) - // }) - // } - // } - // }, 8 * 1000) // 404时长 8秒 - // } + if (!post) { + setTimeout(() => { + if (isBrowser()) { + const article = document.getElementById('notion-article') + if (!article) { + router.push('/404').then(() => { + console.warn('找不到页面', router.asPath) + }) + } + } + }, 5 * 1000) // 404时长 8秒 + } // 文章加密 if (post?.password && post?.password !== '') { @@ -121,6 +122,7 @@ export async function getStaticProps({ params: { slug } }) { // 无法获取文章 if (!props?.post) { + props.post = null return { props, revalidate: parseInt(BLOG.NEXT_REVALIDATE_SECOND) } } diff --git a/themes/gitbook/LayoutBase.js b/themes/gitbook/LayoutBase.js index 457fcdc6..0d169314 100644 --- a/themes/gitbook/LayoutBase.js +++ b/themes/gitbook/LayoutBase.js @@ -3,7 +3,7 @@ import { useState, createContext, useContext, useEffect } from 'react' import Footer from './components/Footer' import InfoCard from './components/InfoCard' import RevolverMaps from './components/RevolverMaps' -import CONFIG_MEDIUM from './config_medium' +import CONFIG_GITBOOK from './config_gitbook' import TopNavBar from './components/TopNavBar' import SearchInput from './components/SearchInput' import BottomMenuBar from './components/BottomMenuBar' @@ -14,6 +14,7 @@ import BlogPostListScroll from './components/BlogPostListScroll' import ArticleInfo from './components/ArticleInfo' import Catalog from './components/Catalog' import { useRouter } from 'next/router' +import Announcement from './components/Announcement' const ThemeGlobalMedium = createContext() /** @@ -50,7 +51,7 @@ const LayoutBase = (props) => {
    {/* 左侧推拉抽屉 */} -
    + + {/* 移动端底部导航栏 */}
    diff --git a/themes/gitbook/LayoutSlug.js b/themes/gitbook/LayoutSlug.js index ef8998ec..b33d9b61 100644 --- a/themes/gitbook/LayoutSlug.js +++ b/themes/gitbook/LayoutSlug.js @@ -25,7 +25,7 @@ export const LayoutSlug = (props) => { {/* Notion文章主体 */} {post && (
    - +
    )}
    diff --git a/themes/gitbook/components/BottomMenuBar.js b/themes/gitbook/components/BottomMenuBar.js index 45215f50..c3348bc3 100644 --- a/themes/gitbook/components/BottomMenuBar.js +++ b/themes/gitbook/components/BottomMenuBar.js @@ -3,34 +3,36 @@ import React from 'react' import { useMediumGlobal } from '../LayoutBase' import JumpToTopButton from './JumpToTopButton' -export default function BottomMenuBar ({ post, className }) { - const { tocVisible, changeTocVisible } = useMediumGlobal() +export default function BottomMenuBar({ post, className }) { + const { tocVisible, changeTocVisible, pageNavVisible, changePageNavVisible } = useMediumGlobal() const showTocBotton = post?.toc?.length > 0 const toggleToc = () => { changeTocVisible(!tocVisible) } + const togglePageNavVisible = () => { + changePageNavVisible(!pageNavVisible) + } + return ( -
    -
    - -
    - -
    - -
    - +
    +
    +
    + +
    +
    + +
    + {showTocBotton &&
    + +
    } + {!showTocBotton && +
    + +
    + } +
    - {showTocBotton &&
    - -
    } - { !showTocBotton && -
    - -
    - } -
    -
    ) } diff --git a/themes/gitbook/components/PageNavDrawer.js b/themes/gitbook/components/PageNavDrawer.js new file mode 100644 index 00000000..846428b2 --- /dev/null +++ b/themes/gitbook/components/PageNavDrawer.js @@ -0,0 +1,36 @@ +import Catalog from './Catalog' +import { useMediumGlobal } from '../LayoutBase' +import BlogPostListScroll from './BlogPostListScroll' + +/** + * 悬浮抽屉 页面内导航 + * @param toc + * @param post + * @returns {JSX.Element} + * @constructor + */ +const PageNavDrawer = ({ post, cRef }) => { + const { pageNavVisible, changePageNavVisible, filterPosts } = useMediumGlobal() + const switchVisible = () => { + changePageNavVisible(!pageNavVisible) + } + + console.log('page', pageNavVisible) + return <> +
    + {/* 侧边菜单 */} +
    +
    + {/* 所有文章列表 */} + +
    +
    +
    + {/* 背景蒙版 */} +
    + +} +export default PageNavDrawer diff --git a/themes/gitbook/components/TocDrawer.js b/themes/gitbook/components/TocDrawer.js index 9a9270db..b58adb44 100644 --- a/themes/gitbook/components/TocDrawer.js +++ b/themes/gitbook/components/TocDrawer.js @@ -20,8 +20,8 @@ const TocDrawer = ({ post, cRef }) => { className={(tocVisible ? 'animate__slideInRight ' : ' -mr-72 animate__slideOutRight') + ' overflow-y-hidden shadow-card w-60 duration-200 fixed right-1 bottom-16 rounded py-2 bg-white dark:bg-gray-600'}> {post && <> -
    - +
    +
    }
    From 041c7977b6ea1576e264f737d7694971d735bd97 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Sat, 24 Jun 2023 12:36:50 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E8=87=AA=E9=80=82=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- themes/gitbook/LayoutBase.js | 2 +- themes/gitbook/components/PageNavDrawer.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/themes/gitbook/LayoutBase.js b/themes/gitbook/LayoutBase.js index 61a340bf..99384af9 100644 --- a/themes/gitbook/LayoutBase.js +++ b/themes/gitbook/LayoutBase.js @@ -53,7 +53,7 @@ const LayoutBase = (props) => {
    {/* 左侧推拉抽屉 */} -