Skip to content

Commit

Permalink
Merge pull request #1197 from tangly1024/feat/new-theme-gitbook
Browse files Browse the repository at this point in the history
Feat/new theme gitbook
  • Loading branch information
tangly1024 committed Jun 24, 2023
2 parents aaa3c4c + 2c1a94b commit 5f504f5
Show file tree
Hide file tree
Showing 58 changed files with 1,739 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .env.local
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
NEXT_PUBLIC_VERSION=3.15.2
NEXT_PUBLIC_VERSION=3.16.0
5 changes: 2 additions & 3 deletions components/DarkModeButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ const DarkModeButton = (props) => {
htmlElement.classList?.add(newStatus ? 'dark' : 'light')
}

return <div className={'text-gray-200 z-10 duration-200 text-xl py-2 ' + props.className}>
<i id='darkModeButton' className={`hover:scale-125 cursor-pointer transform duration-200 fas ${isDarkMode ? 'fa-sun' : 'fa-moon'}`}
onClick={handleChangeDarkMode} />
return <div onClick={handleChangeDarkMode} className={'px-1 dark:text-gray-200 text-gray-800 z-10 duration-200 text-xl hover:scale-125 cursor-pointer transform ' + props.className}>
<i id='darkModeButton' className={`${isDarkMode ? 'far fa-sun' : 'far fa-moon'}`}/>
</div>
}
export default DarkModeButton
9 changes: 3 additions & 6 deletions lib/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
Expand All @@ -34,7 +33,7 @@ export function GlobalContextProvider({ children }) {
// setOnReading(true)
}
// 监听页面元素加载完
setOnReading(false)
// setOnReading(false)
window.addEventListener('beforeunload', handleBeforeUnload)
return () => {
window.removeEventListener('beforeunload', handleBeforeUnload)
Expand Down Expand Up @@ -88,10 +87,8 @@ export function GlobalContextProvider({ children }) {
updateDarkMode,
theme,
setTheme,
switchTheme,
setOnReading
switchTheme
}}>
<LoadingCover onReading={onReading} setOnReading={setOnReading}/>
{children}
</GlobalContext.Provider>
)
Expand Down
35 changes: 35 additions & 0 deletions lib/notion/getNotionData.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "notion-next",
"version": "3.15.2",
"version": "3.16.0",
"homepage": "https://github.com/tangly1024/NotionNext.git",
"license": "MIT",
"repository": {
Expand Down
21 changes: 10 additions & 11 deletions pages/[...slug].js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ 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'
import { isBrowser } from '@/lib/utils'

/**
* 根据notion的slug访问页面
Expand All @@ -19,16 +19,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) {
Expand All @@ -51,18 +48,18 @@ const Slug = props => {
})
}
}
}, 8 * 1000) // 404时长 8秒
}, 5 * 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' })
Expand All @@ -79,7 +76,8 @@ const Slug = props => {
tags: post?.tags
}
props = { ...props, lock, meta, setLock, validPassword }

// 根据页面路径加载不同Layout文件
const Layout = getLayoutByTheme(useRouter())
return <Layout {...props} />
}

Expand Down Expand Up @@ -124,6 +122,7 @@ export async function getStaticProps({ params: { slug } }) {

// 无法获取文章
if (!props?.post) {
props.post = null
return { props, revalidate: parseInt(BLOG.NEXT_REVALIDATE_SECOND) }
}

Expand Down
1 change: 0 additions & 1 deletion styles/notion.css
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions themes/gitbook/Layout404.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import LayoutBase from './LayoutBase'

export const Layout404 = props => {
return <LayoutBase {...props}>
<div className='w-full h-96 py-80 flex justify-center items-center'>404 Not found.</div>
</LayoutBase>
}

export default Layout404
49 changes: 49 additions & 0 deletions themes/gitbook/LayoutArchive.js
Original file line number Diff line number Diff line change
@@ -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 (
<LayoutBase {...props}>
<div className="mb-10 pb-20 md:py-12 py-3 min-h-full">
{Object.keys(archivePosts)?.map(archiveTitle => (
<div key={archiveTitle}>
<div
className="pt-16 pb-4 text-3xl dark:text-gray-300"
id={archiveTitle}
>
{archiveTitle}
</div>
<ul>
{archivePosts[archiveTitle]?.map(post => (
<li
key={post.id}
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
>
<div id={post?.date?.start_date}>
<span className="text-gray-400">
{post.date?.start_date}
</span>{' '}
&nbsp;
<Link
href={`${BLOG.SUB_PATH}/${post.slug}`}
passHref
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">

{post.title}

</Link>
</div>
</li>
))}
</ul>
</div>
))}
</div>
</LayoutBase>
)
}

export default LayoutArchive
122 changes: 122 additions & 0 deletions themes/gitbook/LayoutBase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import CommonHead from '@/components/CommonHead'
import { useState, createContext, useContext, useEffect } from 'react'
import Footer from './components/Footer'
import InfoCard from './components/InfoCard'
import RevolverMaps from './components/RevolverMaps'
import CONFIG_GITBOOK from './config_gitbook'
import TopNavBar from './components/TopNavBar'
import SearchInput from './components/SearchInput'
import BottomMenuBar from './components/BottomMenuBar'
import { useGlobal } from '@/lib/global'
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'
import Announcement from './components/Announcement'
import PageNavDrawer from './components/PageNavDrawer'
const ThemeGlobalMedium = createContext()

/**
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
* @returns {JSX.Element}
* @constructor
*/
const LayoutBase = (props) => {
const { children, meta, post, allNavPages, slotLeft, slotRight, slotTop, siteInfo } = props
const [tocVisible, changeTocVisible] = useState(false)
const [pageNavVisible, changePageNavVisible] = useState(false)
const [filterPosts, setFilterPosts] = useState(allNavPages)
const { onLoading } = useGlobal()
const router = useRouter()

useEffect(() => {
setFilterPosts(allNavPages)
}, [post])

const LoadingCover = <div id='cover-loading' className={`${onLoading ? 'z-50 opacity-50' : '-z-10 opacity-0'} pointer-events-none transition-all duration-300`}>
<div className='w-full h-screen flex justify-center items-center'>
<i className="fa-solid fa-spinner text-2xl text-black dark:text-white animate-spin"> </i>
</div>
</div>

return (
<ThemeGlobalMedium.Provider value={{ tocVisible, changeTocVisible, filterPosts, setFilterPosts, allNavPages, pageNavVisible, changePageNavVisible }}>
<CommonHead meta={meta} />

<div id='theme-medium' className='bg-white dark:bg-hexo-black-gray w-full h-full min-h-screen justify-center dark:text-gray-300'>
{/* 顶部导航栏 */}
<TopNavBar {...props} />

<main id='wrapper' className={(BLOG.LAYOUT_SIDEBAR_REVERSE ? 'flex-row-reverse' : '') + 'relative flex justify-between w-full h-full mx-auto'}>

{/* 左侧推拉抽屉 */}
<div style={{ width: '32rem' }} className={'font-sans hidden md:block border-r dark:border-transparent relative z-10 '}>
<div className='py-14 px-6 sticky top-0 overflow-y-scroll h-screen'>
{slotLeft}

<SearchInput className='my-3' />

{/* 所有文章列表 */}
<BlogPostListScroll posts={filterPosts} />

</div>
</div>

<div id='center-wrapper' className='flex flex-col justify-between w-full relative z-10 pt-12 min-h-screen'>

<div id='container-inner' className='w-full px-7 max-w-3xl justify-center mx-auto'>
{slotTop}

{onLoading ? LoadingCover : children}

{/* 回顶按钮 */}
<div
data-aos="fade-up"
data-aos-duration="300"
data-aos-once="false"
data-aos-anchor-placement="top-center"
className='fixed xl:right-80 right-2 mr-10 bottom-24 hidden lg:block z-20'>
<i className='fas fa-chevron-up cursor-pointer p-2 rounded-full border' onClick={() => { window.scrollTo({ top: 0, behavior: 'smooth' }) }} />
</div>
</div>

{/* 底部 */}
<Footer title={siteInfo?.title} />
</div>

{/* 右侧侧推拉抽屉 */}
<div style={{ width: '32rem' }} className={'hidden xl:block dark:border-transparent relative z-10 '}>
<div className='py-14 px-6 sticky top-0'>
<ArticleInfo post={props?.post ? props?.post : props.notice} />

<div className='pt-6'>
<Catalog {...props} />
{slotRight}
{router.route === '/' && <>
<InfoCard {...props} />
{CONFIG_GITBOOK.WIDGET_REVOLVER_MAPS === 'true' && <RevolverMaps />}
<Live2D />
</>}
{/* gitbook主题首页只显示公告 */}
<Announcement {...props} />
</div>

</div>
</div>

</main>

<PageNavDrawer {...props}/>

{/* 移动端底部导航栏 */}
<BottomMenuBar {...props} className='block md:hidden' />
</div>
</ThemeGlobalMedium.Provider>
)
}

export default LayoutBase
export const useMediumGlobal = () => useContext(ThemeGlobalMedium)

0 comments on commit 5f504f5

Please sign in to comment.