站点信息读取Notion数据

This commit is contained in:
tangly1024
2022-03-30 15:34:25 +08:00
parent 914e9a108f
commit 53c004843e
61 changed files with 322 additions and 463 deletions

View File

@@ -1,7 +1,5 @@
// 注: process.env.XX是Vercel的环境变量配置方式见https://docs.tangly1024.com/zh/features/personality
const BLOG = {
TITLE: process.env.NEXT_PUBLIC_TITLE || 'NotionNext BLOG', // 站点标题
DESCRIPTION: process.env.NEXT_PUBLIC_DESCRIPTION || '这是一个由NotionNext生成的站点', // 站点描述
AUTHOR: 'tangly1024', // 作者
BIO: '一个普通的干饭人🍚', // 作者简介
LINK: 'https://tangly1024.com', // 网站地址
@@ -14,6 +12,7 @@ const BLOG = {
THEME: process.env.NEXT_PUBLIC_THEME || 'next', // 主题, 支持 ['next','hexo',"fukasawa','medium']
THEME_SWITCH: process.env.NEXT_PUBLIC_THEME_SWITCH || false, // 是否显示切换主题按钮
LANG: 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more.
HOME_BANNER_IMAGE: './bg_image.jpg', // 首页背景大图,默认文件:/public/bg_image.jpg 。会被Notion中的封面图覆盖。
SINCE: 2021, // e.g if leave this empty, current year will be used.
BEI_AN: process.env.NEXT_PUBLIC_BEI_AN || '', // 备案号 闽ICP备XXXXXXX
APPEARANCE: 'light', // ['light', 'dark', 'auto'], // light 日间模式 dark夜间模式 auto根据时间和主题自动夜间模式
@@ -91,8 +90,12 @@ const BLOG = {
ADSENSE_GOOGLE_ID: process.env.NEXT_PUBLIC_ADSENSE_GOOGLE_ID || '', // 谷歌广告ID e.g ca-pub-xxxxxxxxxxxxxxxx
// 无关紧要的配置
TITLE: process.env.NEXT_PUBLIC_TITLE || 'NotionNext BLOG', // 站点标题 被notion中的页面标题覆盖
DESCRIPTION: process.env.NEXT_PUBLIC_DESCRIPTION || '这是一个由NotionNext生成的站点', // 站点描述被notion中的页面描述覆盖
isProd: process.env.VERCEL_ENV === 'production', // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
VERSION: '2.8.4' // 版本号
VERSION: '2.9.0' // 版本号
}
module.exports = BLOG

View File

@@ -20,7 +20,12 @@ import { getAllTags } from './getAllTags'
categories, 所有分类
postCount,
customNav, 自定义导航菜单
tags 所有标签
tags, 所有标签
siteInfo:{
title,
description,
pageCover
}
}
*
*/
@@ -33,15 +38,16 @@ export async function getGlobalNotionData ({
pageType = ['Post']
}) {
const notionPageData = await getNotionPageData({ pageId, from })
const siteInfo = await getBlogInfo({ notionPageData, from })
const tagOptions = notionPageData.tagOptions
const categoryOptions = notionPageData.categoryOptions
const customNav = await getCustomNav({ notionPageData })
const allPosts = await getAllPosts({ notionPageData, from, pageType })
const postCount = await getAllPostCount({ notionPageData, from })
const customNav = await getCustomNav({ notionPageData })
const categories = await getAllCategories({ allPosts, categoryOptions, sliceCount: categoryCount })
const tags = await getAllTags({ allPosts, tagOptions, sliceCount: tagsCount })
const latestPosts = await getLatestPosts({ notionPageData, from, latestPostCount })
return { allPosts, latestPosts, categories, postCount, customNav, tags }
return { allPosts, latestPosts, categories, postCount, customNav, tags, siteInfo }
}
/**
@@ -83,12 +89,16 @@ export async function getNotionPageData ({ pageId, from }) {
const pageRecordMap = await getPageRecordMapByNotionAPI({ pageId, from })
// 存入缓存
if (pageRecordMap) {
console.log('[站点数据]', pageRecordMap)
await setDataToCache(cacheKey, pageRecordMap)
}
return pageRecordMap
}
/**
* 获取用户自定义单页菜单
* @param notionPageData
* @returns {Promise<[]|*[]>}
*/
async function getCustomNav ({ notionPageData }) {
if (!notionPageData) {
notionPageData = await getNotionPageData({ from: 'custom-nav' })
@@ -121,12 +131,53 @@ function getTagOptions (schema) {
return tagSchema?.options || []
}
/**
* 获取分类选项
* @param schema
* @returns {{}|*|*[]}
*/
function getCategoryOptions (schema) {
if (!schema) return {}
const categorySchema = Object.values(schema).find(e => e.name === 'category')
return categorySchema?.options || []
}
/**
* 站点信息
* @param notionPageData
* @param from
* @returns {Promise<{title,description,pageCover}>}
*/
async function getBlogInfo ({ notionPageData, from }) {
if (!notionPageData) {
notionPageData = await getNotionPageData({ from })
}
if (!notionPageData) {
return null
}
const collection = notionPageData?.collection
const title = collection?.name[0][0] || BLOG.TITLE
const description = collection?.description[0][0] || BLOG.DESCRIPTION
const pageCover = mapCoverUrl(collection?.cover)
return { title, description, pageCover }
}
/**
* 网站封面背景图
* @param pageCover
* @returns {string}
*/
const mapCoverUrl = pageCover => {
if (!pageCover || pageCover === '') {
return BLOG.HOME_BANNER_IMAGE
}
if (pageCover.indexOf('/images') === 0) {
return 'https://www.notion.so' + pageCover
} else {
return pageCover
}
}
/**
* 调用NotionAPI获取Page数据
* @returns {Promise<JSX.Element|null|*>}

View File

@@ -1,6 +1,6 @@
{
"name": "notion-next",
"version": "2.8.4",
"version": "2.9.0",
"homepage": "https://github.com/tangly1024/NotionNext.git",
"license": "MIT",
"repository": {

25
pages/404.js Normal file
View File

@@ -0,0 +1,25 @@
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import * as ThemeMap from '@/themes'
import { useGlobal } from '@/lib/global'
/**
* 404
* @param {*} props
* @returns
*/
const NoFound = props => {
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
const meta = { title: `${props?.siteInfo?.title} | 页面找不到啦` }
return <ThemeComponents.Layout404 {...props} meta={meta}/>
}
export async function getStaticProps () {
const props = await getGlobalNotionData({ from: 'category-index-props', categoryCount: 0 })
return {
props,
revalidate: 1
}
}
export default NoFound

View File

@@ -10,7 +10,7 @@ import { useEffect, useState } from 'react'
* @param {*} props
* @returns
*/
const Slug = (props) => {
const Slug = props => {
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
const { post } = props
@@ -38,7 +38,15 @@ const Slug = (props) => {
}
}
props = { ...props, lock, setLock, validPassword }
const { siteInfo } = props
const meta = {
title: `${post.title} | ${siteInfo.title}`,
description: post.summary,
type: 'article',
tags: post.tags
}
props = { ...props, meta, lock, setLock, validPassword }
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={false}/>
}
@@ -63,23 +71,23 @@ export async function getStaticPaths () {
export async function getStaticProps ({ params: { slug } }) {
const from = `slug-props-${slug}`
const { allPosts, categories, tags, postCount, latestPosts, customNav } = await getGlobalNotionData({ from, pageType: ['Page'] })
const props = await getGlobalNotionData({ from, pageType: ['Page'] })
const { allPosts } = props
const post = allPosts.find(p => p.slug === slug)
if (!post) {
return { props: {}, revalidate: 1 }
}
post.blockMap = await getPostBlocks(post.id, 'slug')
try {
post.blockMap = await getPostBlocks(post.id, 'slug')
} catch (error) {
console.error('获取文章详情失败', error)
}
props.post = post
return {
props: {
post,
tags,
categories,
postCount,
latestPosts,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -3,24 +3,24 @@ import React from 'react'
import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
const ArchiveIndex = (props) => {
const { theme } = useGlobal()
const ArchiveIndex = props => {
const { theme, locale } = useGlobal()
const ThemeComponents = ThemeMap[theme]
return <ThemeComponents.LayoutArchive {...props}/>
const { siteInfo } = props
const meta = {
title: `${locale.NAV.ARCHIVE} | ${siteInfo.title}`,
description: siteInfo.description,
type: 'website'
}
return <ThemeComponents.LayoutArchive {...props} meta={meta}/>
}
export async function getStaticProps () {
const { allPosts, categories, tags, postCount, customNav } =
await getGlobalNotionData({ from: 'archive-index' })
const props = await getGlobalNotionData({ from: 'archive-index' })
props.posts = props.allPosts
return {
props: {
posts: allPosts,
tags,
categories,
postCount,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -4,18 +4,34 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
import { useEffect, useState } from 'react'
import { useRouter } from 'next/router'
/**
* 根据notion的slug访问页面
* @param {*} props
* @returns
*/
const Slug = (props) => {
const Slug = props => {
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
const { post } = props
if (!post) {
return <ThemeComponents.Layout404 {...props}/>
const router = useRouter()
useEffect(() => {
setTimeout(() => {
if (window) {
const article = document.getElementById('container')
if (!article) {
router.push('/404').then(() => {
console.log('找不到页面', router.asPath)
})
}
}
}, 3000)
})
return <p>Redirecting...</p>
}
// 文章锁🔐
@@ -40,7 +56,15 @@ const Slug = (props) => {
props = { ...props, lock, setLock, validPassword }
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={true}/>
const { siteInfo } = props
const meta = {
title: `${props.post.title} | ${siteInfo.title}`,
description: props.post.summary,
type: 'article',
tags: props.post.tags
}
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={true} meta={meta}/>
}
export async function getStaticPaths () {
@@ -61,35 +85,20 @@ export async function getStaticPaths () {
export async function getStaticProps ({ params: { slug } }) {
const from = `slug-props-${slug}`
const { customNav, allPosts, categories, tags, postCount, latestPosts } =
await getGlobalNotionData({ from, pageType: ['Post'] })
const post = allPosts.find(p => p.slug === slug)
if (!post) {
return { props: {}, revalidate: 1 }
const props = await getGlobalNotionData({ from, pageType: ['Post'] })
const allPosts = props.allPosts
props.post = props.allPosts.find(p => p.slug === slug)
if (!props.post) {
return { props, revalidate: 1 }
}
props.post.blockMap = await getPostBlocks(props.post.id, 'slug')
post.blockMap = await getPostBlocks(post.id, 'slug')
const index = allPosts.indexOf(post)
const prev = allPosts.slice(index - 1, index)[0] ?? allPosts.slice(-1)[0]
const next = allPosts.slice(index + 1, index + 2)[0] ?? allPosts[0]
const recommendPosts = getRecommendPost(post, allPosts, BLOG.POST_RECOMMEND_COUNT)
const index = allPosts.indexOf(props.post)
props.prev = allPosts.slice(index - 1, index)[0] ?? allPosts.slice(-1)[0]
props.next = allPosts.slice(index + 1, index + 2)[0] ?? allPosts[0]
props.recommendPosts = getRecommendPost(props.post, allPosts, BLOG.POST_RECOMMEND_COUNT)
return {
props: {
post,
tags,
prev,
next,
recommendPosts,
categories,
postCount,
latestPosts,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -6,33 +6,29 @@ import * as ThemeMap from '@/themes'
export default function Category (props) {
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
return <ThemeComponents.LayoutCategory {...props} />
const { siteInfo, posts } = props
const { locale } = useGlobal()
if (!posts) {
return <ThemeComponents.Layout404 {...props}/>
}
const meta = {
title: `${props.category} | ${locale.COMMON.CATEGORY} | ${siteInfo?.title || ''}`,
description: siteInfo?.description,
type: 'website'
}
return <ThemeComponents.LayoutCategory {...props} meta={meta} />
}
export async function getStaticProps ({ params }) {
export async function getStaticProps ({ params: { category } }) {
const from = 'category-props'
const category = params.category
const {
allPosts,
categories,
tags,
postCount,
latestPosts,
customNav
} = await getGlobalNotionData({ from })
const filteredPosts = allPosts.filter(
let props = await getGlobalNotionData({ from })
const posts = props.allPosts.filter(
post => post && post.category && post.category.includes(category)
)
props = { ...props, posts, category }
return {
props: {
tags,
posts: filteredPosts,
category,
categories,
postCount,
latestPosts,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -6,22 +6,20 @@ import * as ThemeMap from '@/themes'
export default function Category (props) {
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
return <ThemeComponents.LayoutCategoryIndex {...props}/>
const { locale } = useGlobal()
const { siteInfo } = props
const meta = {
title: `${locale.COMMON.CATEGORY} | ${siteInfo.title}`,
description: siteInfo.description,
type: 'website'
}
return <ThemeComponents.LayoutCategoryIndex {...props} meta={meta}/>
}
export async function getStaticProps () {
const from = 'category-index-props'
const { allPosts, categories, tags, postCount, latestPosts, customNav } = await getGlobalNotionData({ from, categoryCount: 0 })
const props = await getGlobalNotionData({ from: 'category-index-props', categoryCount: 0 })
return {
props: {
tags,
allPosts,
categories,
postCount,
latestPosts,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -11,10 +11,11 @@ const Index = (props) => {
export async function getStaticProps () {
const from = 'index'
const { allPosts, latestPosts, categories, tags, postCount, customNav } = await getGlobalNotionData({ from, pageType: ['Post'] })
const props = await getGlobalNotionData({ from, pageType: ['Post'] })
const { allPosts, siteInfo } = props
const meta = {
title: `${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
title: `${siteInfo.title}`,
description: siteInfo.description,
type: 'website'
}
@@ -38,16 +39,11 @@ export async function getStaticProps () {
}
}
}
props.posts = postsToShow
return {
props: {
posts: postsToShow,
latestPosts,
postCount,
tags,
categories,
meta,
customNav
meta, ...props
},
revalidate: 1
}

View File

@@ -4,13 +4,19 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
const Page = (props) => {
const Page = props => {
const { theme } = useGlobal()
const { siteInfo } = props
const ThemeComponents = ThemeMap[theme]
if (!props?.meta) {
return <ThemeComponents.Layout404 {...props}/>
if (!siteInfo) {
return <></>
}
return <ThemeComponents.LayoutPage {...props} />
const meta = {
title: `${props.page} | Page | ${siteInfo.title}`,
description: siteInfo.description,
type: 'website'
}
return <ThemeComponents.LayoutPage {...props} meta={meta} />
}
export async function getStaticPaths () {
@@ -26,28 +32,16 @@ export async function getStaticPaths () {
export async function getStaticProps ({ params: { page } }) {
const from = `page-${page}`
const {
allPosts,
latestPosts,
categories,
tags,
postCount,
customNav
} = await getGlobalNotionData({ from })
const meta = {
title: `${page} | Page | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
const props = await getGlobalNotionData({ from })
props.page = page
// 处理分页
const postsToShow = allPosts.slice(
props.posts = props.allPosts.slice(
BLOG.POSTS_PER_PAGE * (page - 1),
BLOG.POSTS_PER_PAGE * page
)
if (BLOG.POST_LIST_PREVIEW === 'true') {
for (const i in postsToShow) {
const post = postsToShow[i]
for (const i in props.posts) {
const post = props.posts[i]
const blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES)
if (blockMap) {
post.blockMap = blockMap
@@ -56,16 +50,7 @@ export async function getStaticProps ({ params: { page } }) {
}
return {
props: {
page,
posts: postsToShow,
postCount,
latestPosts,
tags,
categories,
meta,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -1,18 +1,16 @@
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { getDataFromCache } from '@/lib/cache/cache_manager'
import * as ThemeMap from '@/themes'
const Index = (props) => {
const { keyword } = props
const Index = props => {
const { keyword, siteInfo } = props
const { locale } = useGlobal()
const meta = {
title: `${keyword || ''} | ${locale.NAV.SEARCH} | ${BLOG.TITLE} `,
description: BLOG.DESCRIPTION,
title: `${keyword || ''} | ${locale.NAV.SEARCH} | ${siteInfo.title}`,
description: siteInfo.title,
type: 'website'
}
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
return <ThemeComponents.LayoutSearch {...props} meta={meta} currentSearch={keyword} />
@@ -24,26 +22,10 @@ const Index = (props) => {
* @returns
*/
export async function getServerSideProps ({ params: { keyword } }) {
const {
allPosts,
categories,
tags,
postCount,
latestPosts,
customNav
} = await getGlobalNotionData({ from: 'search-props', pageType: ['Post'] })
const filterPosts = await filterByMemCache(allPosts, keyword)
const props = await getGlobalNotionData({ from: 'search-props', pageType: ['Post'] })
props.posts = await filterByMemCache(props.allPosts, keyword)
return {
props: {
posts: filterPosts,
tags,
categories,
postCount,
latestPosts,
customNav,
keyword
}
props
}
}

View File

@@ -1,11 +1,10 @@
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { useRouter } from 'next/router'
import * as ThemeMap from '@/themes'
const Search = (props) => {
const { posts } = props
const Search = props => {
const { posts, siteInfo } = props
let filteredPosts
const searchKey = getSearchKey()
// 静态过滤
@@ -22,31 +21,25 @@ const Search = (props) => {
const { locale } = useGlobal()
const meta = {
title: `${searchKey || ''} | ${locale.NAV.SEARCH} | ${BLOG.TITLE} `,
description: BLOG.DESCRIPTION,
title: `${searchKey || ''} | ${locale.NAV.SEARCH} | ${siteInfo.title}`,
description: siteInfo.description,
type: 'website'
}
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
return <ThemeComponents.LayoutSearch {...props} posts={filteredPosts} meta={meta} currentSearch={searchKey} />
return <ThemeComponents.LayoutSearch {...props} posts={filteredPosts} currentSearch={searchKey} meta={meta} />
}
/**
* 浏览器前端搜索
*/
export async function getStaticProps () {
const { allPosts, categories, tags, postCount, latestPosts, customNav } = await getGlobalNotionData({ from: 'search-props', pageType: ['Post'] })
const props = await getGlobalNotionData({ from: 'search-props', pageType: ['Post'] })
props.posts = props.allPosts
return {
props: {
posts: allPosts,
tags,
categories,
postCount,
latestPosts,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -2,40 +2,31 @@ import { useGlobal } from '@/lib/global'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import * as ThemeMap from '@/themes'
const Tag = (props) => {
const Tag = props => {
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
return <ThemeComponents.LayoutTag {...props} />
const { locale } = useGlobal()
const { tag, siteInfo, posts } = props
if (!posts) {
return <ThemeComponents.Layout404 {...props}/>
}
const meta = {
title: `${tag} | ${locale.COMMON.TAGS} | ${siteInfo?.title}`,
description: siteInfo?.description,
type: 'website'
}
return <ThemeComponents.LayoutTag {...props} meta={meta}/>
}
export async function getStaticProps ({ params }) {
const tag = params.tag
const from = 'tag-props'
const {
allPosts,
categories,
tags,
postCount,
latestPosts,
customNav
} = await getGlobalNotionData({
from,
includePage: false,
tagsCount: 0
})
const filteredPosts = allPosts.filter(
post => post && post.tags && post.tags.includes(tag)
)
export async function getStaticProps ({ params: { tag } }) {
const props = await getGlobalNotionData({ from: 'tag-props', includePage: false, tagsCount: 0 })
const { allPosts } = props
props.posts = allPosts.filter(post => post && post.tags && post.tags.includes(tag))
props.tag = tag
return {
props: {
tags,
posts: filteredPosts,
tag,
categories,
postCount,
latestPosts,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -3,24 +3,24 @@ import React from 'react'
import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
const TagIndex = (props) => {
const TagIndex = props => {
const { theme } = useGlobal()
const ThemeComponents = ThemeMap[theme]
return <ThemeComponents.LayoutTagIndex {...props} />
const { locale } = useGlobal()
const { siteInfo } = props
const meta = {
title: `${locale.COMMON.TAGS} | ${siteInfo.title}`,
description: siteInfo.description,
type: 'website'
}
return <ThemeComponents.LayoutTagIndex {...props} meta={meta} />
}
export async function getStaticProps () {
const from = 'tag-index-props'
const { categories, tags, postCount, latestPosts, customNav } = await getGlobalNotionData({ from, tagsCount: 0 })
const props = await getGlobalNotionData({ from, tagsCount: 0 })
return {
props: {
tags,
categories,
postCount,
latestPosts,
customNav
},
props,
revalidate: 1
}
}

View File

@@ -1,11 +1,9 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import Link from 'next/link'
import LayoutBase from './LayoutBase'
export const LayoutArchive = props => {
const { posts } = props
const { locale } = useGlobal()
const postsSortByDate = Object.create(posts)
postsSortByDate.sort((a, b) => {
@@ -14,12 +12,6 @@ export const LayoutArchive = props => {
return dateB - dateA
})
const meta = {
title: `${locale.NAV.ARCHIVE} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
const archivePosts = {}
postsSortByDate.forEach(post => {
@@ -31,7 +23,7 @@ export const LayoutArchive = props => {
}
})
return (
<LayoutBase {...props} meta={meta}>
<LayoutBase {...props}>
<div className="mb-10 pb-20 md:p-12 p-3 min-h-full">
{Object.keys(archivePosts).map(archiveTitle => (
<div key={archiveTitle}>

View File

@@ -11,7 +11,7 @@ import { useGlobal } from '@/lib/global'
* @constructor
*/
const LayoutBase = props => {
const { children, meta, customNav } = props
const { children, meta, customNav, siteInfo } = props
const { locale } = useGlobal()
const d = new Date()
const currentYear = d.getFullYear()
@@ -35,10 +35,10 @@ const LayoutBase = props => {
<div className="w-full flex justify-center my-2">
<div className=" max-w-6xl justify-between w-full flex">
<section>
<Link title={BLOG.TITLE} href={'/'}>
<Link title={siteInfo.title} href={'/'}>
<a className={'cursor-pointer flex items-center hover:underline'}>
<i className={'fas fa-home mr-1'} />
<div className="text-center">{BLOG.TITLE} </div>
<div className="text-center">{siteInfo.title} </div>
</a>
</Link>
</section>
@@ -126,7 +126,7 @@ const LayoutBase = props => {
<span className="px-1 busuanzi_value_site_uv"> </span>{' '}
</span>
<br />
<h1>{meta?.title || BLOG.TITLE}</h1>
<h1>{meta?.title || siteInfo.title}</h1>
</footer>
</div>
)

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { getPageTableOfContents } from 'notion-utils'
import 'prismjs'
import 'prismjs/components/prism-bash'
@@ -24,13 +23,6 @@ const mapPageUrl = id => {
export const LayoutSlug = props => {
const { post, lock, validPassword } = props
const meta = {
title: `${post.title} | ${BLOG.TITLE}`,
description: post.summary,
type: 'article',
tags: post.tags
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
@@ -55,7 +47,7 @@ export const LayoutSlug = props => {
}
})
return (
<LayoutBase {...props} meta={meta}>
<LayoutBase {...props}>
<div>
<h2>{post?.title}</h2>

View File

@@ -1,5 +1,5 @@
import LayoutBase from './LayoutBase'
export const Layout404 = (props) => {
export const Layout404 = props => {
return <LayoutBase {...props}>404</LayoutBase>
}

View File

@@ -1,11 +1,8 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { useEffect } from 'react'
import BlogArchiveItem from './components/BlogPostArchive'
import LayoutBase from './LayoutBase'
export const LayoutArchive = (props) => {
const { locale } = useGlobal()
const { posts } = props
// 深拷贝
const postsSortByDate = Object.create(posts)
@@ -16,13 +13,6 @@ export const LayoutArchive = (props) => {
const dateB = new Date(b?.date.start_date || b.createdTime)
return dateB - dateA
})
const meta = {
title: `${locale.NAV.ARCHIVE} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
const archivePosts = {}
postsSortByDate.forEach(post => {
@@ -47,7 +37,7 @@ export const LayoutArchive = (props) => {
}
}
}, [])
return <LayoutBase {...props} meta={meta}>
return <LayoutBase {...props}>
<div className="mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-gray-800 shadow-md min-h-full">
{Object.keys(archivePosts).map(archiveTitle => (
<BlogArchiveItem

View File

@@ -1,7 +1,7 @@
import BlogListPage from './components/BlogListPage'
import LayoutBase from './LayoutBase'
export const LayoutCategory = (props) => {
export const LayoutCategory = props => {
return <LayoutBase {...props}>
<BlogListPage page={props.page} posts={props.posts} postCount={props.postCount} />
</LayoutBase>

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import Link from 'next/link'
import LayoutBase from './LayoutBase'
@@ -6,12 +5,7 @@ import LayoutBase from './LayoutBase'
export const LayoutCategoryIndex = (props) => {
const { locale } = useGlobal()
const { categories } = props
const meta = {
title: `${locale.COMMON.CATEGORY} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase {...props} meta={meta}>
return <LayoutBase {...props}>
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
<div className='dark:text-gray-200 mb-5'>
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { getPageTableOfContents } from 'notion-utils'
import 'prismjs'
import 'prismjs/components/prism-bash'
@@ -12,20 +11,13 @@ import { ArticleLock } from './components/ArticleLock'
export const LayoutSlug = (props) => {
const { post, lock, validPassword } = props
const meta = {
title: `${post.title} | ${BLOG.TITLE}`,
description: post.summary,
type: 'article',
tags: post.tags
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
return (
<LayoutBase meta={meta} {...props} >
<LayoutBase {...props} >
{!lock && <ArticleDetail {...props} />}
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
</LayoutBase>

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import TagItem from './components/TagItem'
import LayoutBase from './LayoutBase'
@@ -6,13 +5,7 @@ import LayoutBase from './LayoutBase'
export const LayoutTagIndex = (props) => {
const { locale } = useGlobal()
const { tags } = props
const meta = {
title: `${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase {...props} meta={meta}>
return <LayoutBase {...props} >
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
<div className='dark:text-gray-200 mb-5'><i className='mr-4 fas fa-tag'/>{locale.COMMON.TAGS}:</div>
<div id='tags-list' className='duration-200 flex flex-wrap'>

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import Logo from './Logo'
import GroupCategory from './GroupCategory'
import GroupMenu from './GroupMenu'
@@ -9,10 +8,10 @@ import Catalog from './Catalog'
import { useRouter } from 'next/router'
function AsideLeft (props) {
const { tags, currentTag, categories, currentCategory, post, slot } = props
const { tags, currentTag, categories, currentCategory, post, slot, siteInfo } = props
const router = useRouter()
return <div className='w-72 bg-white dark:bg-gray-800 min-h-screen px-10 py-14 hidden lg:block'>
<Logo />
<Logo {...props}/>
<section className='flex flex-col text-gray-600'>
<hr className='w-12 my-8' />
@@ -26,7 +25,7 @@ function AsideLeft (props) {
<section className='flex flex-col dark:text-gray-300'>
<hr className='w-12 my-8' />
{ BLOG.DESCRIPTION }
{ siteInfo.description }
</section>
{router.asPath !== '/tag' && <section className='flex flex-col'>

View File

@@ -1,10 +1,10 @@
import BLOG from '@/blog.config'
import Link from 'next/link'
function Logo () {
const Logo = props => {
const { siteInfo } = props
return <section className='flex'>
<Link href='/'>
<a className='hover:bg-black hover:text-white border-black border-2 duration-500 px-4 py-2 cursor-pointer dark:text-gray-300 dark:border-gray-300 font-black'>{BLOG.TITLE}</a>
<a className='hover:bg-black hover:text-white border-black border-2 duration-500 px-4 py-2 cursor-pointer dark:text-gray-300 dark:border-gray-300 font-black'>{siteInfo.title}</a>
</Link>
</section>
}

View File

@@ -8,7 +8,7 @@ import Logo from './Logo'
* @param {*} param0
* @returns
*/
const TopNav = (props) => {
const TopNav = props => {
const [isOpen, changeShow] = useState(false)
const toggleMenuOpen = () => {
@@ -27,7 +27,7 @@ const TopNav = (props) => {
<div className='w-full flex justify-between items-center p-4 bg-white'>
{/* 左侧LOGO 标题 */}
<div className='flex flex-none flex-grow-0'>
<Logo/>
<Logo {...props}/>
</div>
<div className='flex'>
</div>

View File

@@ -1,34 +1,15 @@
import BLOG from '@/blog.config'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import LayoutBase from './LayoutBase'
export const Layout404 = props => {
const router = useRouter()
useEffect(() => {
// 延时3秒如果加载失败就返回首页
setTimeout(() => {
if (window) {
const article = document.getElementById('container')
if (!article) {
router.push('/').then(() => {
console.log('找不到页面', router.asPath)
})
}
}
}, 3000)
})
return (
<LayoutBase {...props} meta={{ title: `${BLOG.TITLE} | 页面找不到啦` }}>
<LayoutBase {...props}>
<div className="text-black w-full h-screen text-center justify-center content-center items-center flex flex-col">
<div className="dark:text-gray-200">
<h2 className="inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top">
<i className="mr-2 fas fa-spinner animate-spin" />
404
</h2>
<div className="inline-block text-left h-32 leading-10 items-center">
<h2 className="m-0 p-0">页面无法加载即将返回首页</h2>
<h2 className="m-0 p-0">页面未找到</h2>
</div>
</div>
</div>

View File

@@ -1,5 +1,3 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { useEffect } from 'react'
import BlogPostArchive from './components/BlogPostArchive'
import Card from './components/Card'
@@ -7,7 +5,6 @@ import LayoutBase from './LayoutBase'
export const LayoutArchive = (props) => {
const { posts } = props
const { locale } = useGlobal()
// 深拷贝
const postsSortByDate = Object.create(posts)
@@ -18,12 +15,6 @@ export const LayoutArchive = (props) => {
return dateB - dateA
})
const meta = {
title: `${locale.NAV.ARCHIVE} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
const archivePosts = {}
postsSortByDate.forEach(post => {
@@ -48,7 +39,7 @@ export const LayoutArchive = (props) => {
}
}
}, [])
return <LayoutBase {...props} meta={meta}>
return <LayoutBase {...props} >
<Card className='w-full'>
<div className="mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-gray-800 min-h-full">
{Object.keys(archivePosts).map(archiveTitle => (

View File

@@ -18,7 +18,7 @@ import { useGlobal } from '@/lib/global'
* @constructor
*/
const LayoutBase = (props) => {
const { children, headerSlot, floatSlot, meta } = props
const { children, headerSlot, floatSlot, meta, siteInfo } = props
const [show, switchShow] = useState(false)
// const [percent, changePercent] = useState(0) // 页面阅读百分比
const rightAreaSlot = <Live2D/>
@@ -72,7 +72,7 @@ const LayoutBase = (props) => {
</div>
</div>
<Footer title={meta.title}/>
<Footer title={siteInfo.title}/>
</div>)
}

View File

@@ -1,17 +1,9 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import BlogPostListScroll from './components/BlogPostListScroll'
import LayoutBase from './LayoutBase'
export const LayoutCategory = (props) => {
export const LayoutCategory = props => {
const { tags, posts, category } = props
const { locale } = useGlobal()
const meta = {
title: `${category} | ${locale.COMMON.CATEGORY} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase {...props} meta={meta}>
return <LayoutBase {...props}>
<BlogPostListScroll posts={posts} tags={tags} currentCategory={category}/>
</LayoutBase>
}

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import Link from 'next/link'
import Card from './components/Card'
@@ -7,13 +6,8 @@ import LayoutBase from './LayoutBase'
export const LayoutCategoryIndex = props => {
const { categories } = props
const { locale } = useGlobal()
const meta = {
title: `${locale.COMMON.CATEGORY} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return (
<LayoutBase {...props} meta={meta}>
<LayoutBase {...props}>
<Card className="w-full min-h-screen">
<div className="dark:text-gray-200 mb-5 mx-3">
<i className="mr-4 fas fa-th" />

View File

@@ -4,7 +4,7 @@ import CONFIG_HEXO from './config_hexo'
import LayoutBase from './LayoutBase'
export const LayoutIndex = (props) => {
return <LayoutBase {...props} headerSlot={CONFIG_HEXO.HOME_BANNER_ENABLE && <Header/>}>
return <LayoutBase {...props} headerSlot={CONFIG_HEXO.HOME_BANNER_ENABLE && <Header {...props}/>}>
<BlogPostListPage {...props}/>
</LayoutBase>
}

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { getPageTableOfContents } from 'notion-utils'
import 'prismjs'
import 'prismjs/components/prism-bash'
@@ -18,12 +17,6 @@ import LayoutBase from './LayoutBase'
export const LayoutSlug = props => {
const { post, lock, validPassword } = props
const meta = {
title: `${post.title} | ${BLOG.TITLE}`,
description: post.summary,
type: 'article',
tags: post.tags
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
@@ -48,7 +41,6 @@ export const LayoutSlug = props => {
<LayoutBase
headerSlot={<HeaderArticle post={post}/>}
{...props}
meta={meta}
showCategory={false}
showTag={false}
floatSlot={floatSlot}

View File

@@ -1,19 +1,10 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import BlogPostListScroll from './components/BlogPostListScroll'
import LayoutBase from './LayoutBase'
export const LayoutTag = (props) => {
const { tags, posts, tag } = props
const { locale } = useGlobal()
const meta = {
title: `${tag} | ${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase {...props} meta={meta}>
return <LayoutBase {...props}>
<BlogPostListScroll posts={posts} tags={tags} currentTag={tag}/>
</LayoutBase>
}

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import Card from './components/Card'
import TagItemMini from './components/TagItemMini'
@@ -7,13 +6,8 @@ import LayoutBase from './LayoutBase'
export const LayoutTagIndex = props => {
const { tags } = props
const { locale } = useGlobal()
const meta = {
title: `${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return (
<LayoutBase {...props} meta={meta}>
<LayoutBase {...props}>
<Card className='w-full'>
<div className="dark:text-gray-200 mb-5 ml-4">
<i className="mr-4 fas fa-tag" />

View File

@@ -25,7 +25,7 @@ export default function ArticleRecommend ({ recommendPosts }) {
{recommendPosts.map(post => {
const headerImage = post?.page_cover
? `url("${post.page_cover}")`
: `url("/${CONFIG_HEXO.HOME_BANNER_IMAGE}")`
: `url("/${BLOG.HOME_BANNER_IMAGE}")`
return (
<Link key={post.id} title={post.title} href={`${BLOG.PATH}/article/${post.slug}`} passHref>

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { useEffect, useState } from 'react'
import Typed from 'typed.js'
@@ -12,10 +11,10 @@ let autoScroll = false
*
* @returns 头图
*/
export default function Header () {
const Header = props => {
const [typed, changeType] = useState()
const { isDarkMode } = useGlobal()
const { siteInfo } = props
useEffect(() => {
scrollTrigger()
updateHeaderHeight()
@@ -102,11 +101,11 @@ export default function Header () {
className="duration-500 md:bg-fixed w-full bg-cover bg-center h-screen bg-black text-white"
style={{
backgroundImage:
`linear-gradient(rgba(0, 0, 0, 0.8), rgba(0,0,0,0.2), rgba(0, 0, 0, 0.8) ),url("${CONFIG_HEXO.HOME_BANNER_IMAGE}")`
`linear-gradient(rgba(0, 0, 0, 0.8), rgba(0,0,0,0.2), rgba(0, 0, 0, 0.8) ),url("${siteInfo.pageCover}")`
}}
>
<div className="absolute flex flex-col h-full items-center justify-center w-full font-sans">
<div className='text-4xl md:text-5xl text-white shadow-text'>{BLOG.TITLE}</div>
<div className='text-4xl md:text-5xl text-white shadow-text'>{siteInfo.title}</div>
<div className='mt-2 h-12 items-center text-center shadow-text text-white text-lg'>
<span id='typed'/>
</div>
@@ -122,3 +121,5 @@ export default function Header () {
</header>
)
}
export default Header

View File

@@ -1,11 +1,11 @@
import Link from 'next/link'
import { useGlobal } from '@/lib/global'
import formatDate from '@/lib/formatDate'
import CONFIG_HEXO from '../config_hexo'
import { useEffect } from 'react'
import BLOG from '@/blog.config'
export default function HeaderArticle ({ post }) {
const headerImage = post?.page_cover ? `url("${post.page_cover}")` : `url("/${CONFIG_HEXO.HOME_BANNER_IMAGE}")`
const headerImage = post?.page_cover ? `url("${post.page_cover}")` : `url("/${BLOG.HOME_BANNER_IMAGE}")`
const { isDarkMode } = useGlobal()
const { locale } = useGlobal()

View File

@@ -2,7 +2,6 @@ import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import Link from 'next/link'
import { useRouter } from 'next/router'
import CONFIG_HEXO from '../config_hexo'
/**
* 最新文章列表
@@ -30,7 +29,7 @@ const LatestPostsGroup = ({ posts }) => {
const selected = currentPath === `${BLOG.PATH}/article/${post.slug}`
const headerImage = post?.page_cover
? `url("${post.page_cover}")`
: `url("/${CONFIG_HEXO.HOME_BANNER_IMAGE}")`
: `url("/${BLOG.HOME_BANNER_IMAGE}")`
return (
<Link

View File

@@ -1,11 +1,11 @@
import Link from 'next/link'
import BLOG from '@/blog.config'
import React from 'react'
const Logo = () => {
const Logo = props => {
const { siteInfo } = props
return <Link href='/' passHref>
<div className='flex flex-col justify-center items-center cursor-pointer space-y-3'>
<div className='font-sans text-lg p-1.5 rounded bg-black text-white dark:border-white border-black border'> {BLOG.TITLE}</div>
<div className='font-sans text-lg p-1.5 rounded bg-black text-white dark:border-white border-black border'> {siteInfo.title}</div>
</div>
</Link>
}

View File

@@ -18,7 +18,7 @@ let windowTop = 0
* @param {*} param0
* @returns
*/
const TopNav = (props) => {
const TopNav = props => {
const { tags, currentTag, categories, currentCategory } = props
const { locale } = useGlobal()
const searchDrawer = useRef()
@@ -94,7 +94,7 @@ const TopNav = (props) => {
<div id='sticky-nav' className={`${CONFIG_HEXO.NAV_TYPE !== 'normal' ? 'fixed bg-white' : ' bg-none -mb-10'} animate__animated animate__fadeIn dark:bg-hexo-black-gray dark:text-gray-200 text-black w-full top-0 z-20 transform duration-200 font-san `}>
<div className='w-full flex justify-between items-center px-4 py-2 border dark:border-transparent'>
<div className='flex'>
<Logo/>
<Logo {...props}/>
</div>
{/* 右侧功能 */}

View File

@@ -1,7 +1,6 @@
const CONFIG_HEXO = {
HOME_BANNER_ENABLE: true,
HOME_BANNER_GREETINGS: ['Hi我是一个程序员', 'Hi我是一个打工人', 'Hi我是一个干饭人', '欢迎来到我的博客🎉'], // 首页大图标语文字
HOME_BANNER_IMAGE: './bg_image.jpg', // see /public/bg_image.jpg
// 菜单配置
MENU_CATEGORY: true, // 显示分类

View File

@@ -1,6 +1,6 @@
import LayoutBase from './LayoutBase'
export const Layout404 = (props) => {
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>

View File

@@ -1,11 +1,9 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import Link from 'next/link'
import LayoutBase from './LayoutBase'
export const LayoutArchive = props => {
const { posts } = props
const { locale } = useGlobal()
const postsSortByDate = Object.create(posts)
postsSortByDate.sort((a, b) => {
@@ -14,12 +12,6 @@ export const LayoutArchive = props => {
return dateB - dateA
})
const meta = {
title: `${locale.NAV.ARCHIVE} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
const archivePosts = {}
postsSortByDate.forEach(post => {
@@ -31,7 +23,7 @@ export const LayoutArchive = props => {
}
})
return (
<LayoutBase {...props} meta={meta}>
<LayoutBase {...props}>
<div className="mb-10 pb-20 md:p-12 p-3 min-h-full">
{Object.keys(archivePosts).map(archiveTitle => (
<div key={archiveTitle}>

View File

@@ -1,7 +1,7 @@
import LayoutBase from './LayoutBase'
import BlogPostListScroll from './components/BlogPostListScroll'
export const LayoutCategory = (props) => {
export const LayoutCategory = props => {
const { category } = props
const slotTop = <div className='flex items-center font-sans p-8'><div className='text-xl'><i className='mr-2 fas fa-th'/>分类</div>{category}</div>

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { getPageTableOfContents } from 'notion-utils'
import LayoutBase from './LayoutBase'
@@ -11,12 +10,6 @@ import { ArticleLock } from './components/ArticleLock'
export const LayoutSlug = props => {
const { post, lock, validPassword } = props
const meta = {
title: `${post.title} | ${BLOG.TITLE}`,
description: post.summary,
type: 'article',
tags: post.tags
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
@@ -53,7 +46,6 @@ export const LayoutSlug = props => {
return (
<LayoutBase
{...props}
meta={meta}
showInfoCard={true}
slotRight={slotRight}
>

View File

@@ -1,10 +1,10 @@
import BLOG from '@/blog.config'
import Link from 'next/link'
export default function LogoBar () {
export default function LogoBar (props) {
const { siteInfo } = props
return <div id='top-wrapper' className='w-full flex items-center font-sans'>
<Link href='/'>
<a className='text-md md:text-xl dark:text-gray-200'>{BLOG.TITLE}</a>
<a className='text-md md:text-xl dark:text-gray-200'>{siteInfo.title}</a>
</Link>
</div>
}

View File

@@ -13,7 +13,7 @@ export default function TopNavBar (props) {
return <div id='top-nav' className={'sticky top-0 lg:relative w-full z-40 ' + className}>
<div className='flex w-full h-12 shadow bg-white dark:bg-gray-900 px-5 items-between'>
<LogoBar />
<LogoBar {...props}/>
{/* 顶部菜单 */}
<div className='flex'>

View File

@@ -1,9 +1,8 @@
import { useRouter } from 'next/router'
import LayoutBase from './LayoutBase'
import BLOG from '@/blog.config'
import { useEffect } from 'react'
export const Layout404 = (props) => {
export const Layout404 = props => {
const router = useRouter()
useEffect(() => {
// 延时3秒如果加载失败就返回首页
@@ -19,7 +18,7 @@ export const Layout404 = (props) => {
}, 3000)
})
return <LayoutBase meta={{ title: `${BLOG.TITLE} | 页面找不到啦` }} {...props}>
return <LayoutBase {...props}>
<div
className='md:-mt-20 text-black w-full h-screen text-center justify-center content-center items-center flex flex-col'>
<div className='dark:text-gray-200'>

View File

@@ -1,12 +1,9 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import React, { useEffect } from 'react'
import LayoutBase from './LayoutBase'
import BlogPostArchive from './components/BlogPostArchive'
export const LayoutArchive = (props) => {
const { posts } = props
const { locale } = useGlobal()
// 深拷贝
const postsSortByDate = Object.create(posts)
@@ -17,12 +14,6 @@ export const LayoutArchive = (props) => {
return dateB - dateA
})
const meta = {
title: `${locale.NAV.ARCHIVE} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
const archivePosts = {}
postsSortByDate.forEach(post => {
@@ -49,7 +40,7 @@ export const LayoutArchive = (props) => {
}, [])
return (
<LayoutBase meta={meta} {...props}>
<LayoutBase {...props}>
<div className="mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-gray-800 shadow-md min-h-full">
{Object.keys(archivePosts).map(archiveTitle => (
<BlogPostArchive

View File

@@ -20,7 +20,7 @@ import Live2D from '@/components/Live2D'
* @constructor
*/
const LayoutBase = (props) => {
const { children, headerSlot, meta, sideBarSlot, floatSlot, rightAreaSlot } = props
const { children, headerSlot, meta, sideBarSlot, floatSlot, rightAreaSlot, siteInfo } = props
const { onLoading } = useGlobal()
const targetRef = useRef(null)
const leftAreaSlot = <Live2D/>
@@ -75,7 +75,7 @@ const LayoutBase = (props) => {
</div>
</div>
<Footer title={meta.title}/>
<Footer title={siteInfo?.title}/>
</>
)
}

View File

@@ -1,5 +1,3 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import LayoutBase from './LayoutBase'
import StickyBar from './components/StickyBar'
import CategoryList from './components/CategoryList'
@@ -7,13 +5,7 @@ import BlogPostListScroll from './components/BlogPostListScroll'
export const LayoutCategory = (props) => {
const { tags, posts, category, categories } = props
const { locale } = useGlobal()
const meta = {
title: `${category} | ${locale.COMMON.CATEGORY} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase meta={meta} currentCategory={category} {...props}>
return <LayoutBase currentCategory={category} {...props}>
<StickyBar>
<CategoryList currentCategory={category} categories={categories} />
</StickyBar>

View File

@@ -1,17 +1,11 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import LayoutBase from './LayoutBase'
import Link from 'next/link'
export const LayoutCategoryIndex = (props) => {
const { allPosts, categories } = props
const { locale } = useGlobal()
const meta = {
title: `${locale.COMMON.CATEGORY} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase meta={meta} totalPosts={allPosts} {...props}>
return <LayoutBase totalPosts={allPosts} {...props}>
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow h-full'>
<div className='dark:text-gray-200 mb-5'>
<i className='mr-4 fas faTh' />{locale.COMMON.CATEGORY}:

View File

@@ -1,4 +1,3 @@
import BLOG from '@/blog.config'
import { getPageTableOfContents } from 'notion-utils'
import TocDrawerButton from './components/TocDrawerButton'
import LayoutBase from './LayoutBase'
@@ -12,12 +11,6 @@ import { ArticleLock } from './components/ArticleLock'
export const LayoutSlug = (props) => {
const { post, latestPosts, lock, validPassword } = props
const meta = {
title: `${post.title} | ${BLOG.TITLE}`,
description: post.summary,
type: 'article',
tags: post.tags
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
@@ -35,7 +28,6 @@ export const LayoutSlug = (props) => {
return (
<LayoutBase
{...props}
meta={meta}
floatSlot={floatSlot}
rightAreaSlot={
CONFIG_NEXT.RIGHT_LATEST_POSTS && <Card><LatestPostsGroup posts={latestPosts} /></Card>

View File

@@ -1,5 +1,3 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import LayoutBase from './LayoutBase'
import StickyBar from './components/StickyBar'
import TagList from './components/TagList'
@@ -7,15 +5,8 @@ import BlogPostListScroll from './components/BlogPostListScroll'
export const LayoutTag = (props) => {
const { tags, posts, tag } = props
const { locale } = useGlobal()
const meta = {
title: `${tag} | ${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase meta={meta} currentTag={tag} {...props}>
return <LayoutBase currentTag={tag} {...props}>
<StickyBar>
<TagList tags={tags} currentTag={tag}/>
</StickyBar>

View File

@@ -1,17 +1,11 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import LayoutBase from './LayoutBase'
import TagItem from './components/TagItem'
export const LayoutTagIndex = (props) => {
const { tags } = props
const { locale } = useGlobal()
const meta = {
title: `${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
type: 'website'
}
return <LayoutBase meta={meta} {...props}>
return <LayoutBase {...props}>
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow h-full'>
<div className='dark:text-gray-200 mb-5'><i className='fas fa-tags mr-4'/>{locale.COMMON.TAGS}:</div>
<div id='tags-list' className='duration-200 flex flex-wrap'>

View File

@@ -1,12 +1,12 @@
import Link from 'next/link'
import BLOG from '@/blog.config'
import React from 'react'
const Logo = () => {
const Logo = props => {
const { siteInfo } = props
return <Link href='/' passHref>
<div className='flex flex-col justify-center items-center cursor-pointer bg-black space-y-3 h-32 font-bold'>
<div className='font-serif text-xl text-white'> {BLOG.TITLE}</div>
<div className='text-sm text-gray-300 font-light'> {BLOG.DESCRIPTION}</div>
<div className='font-serif text-xl text-white'> {siteInfo?.title}</div>
<div className='text-sm text-gray-300 font-light'> {siteInfo?.description}</div>
</div>
</Link>
}

View File

@@ -18,7 +18,7 @@ import CONFIG_NEXT from '../config_next'
* @returns {JSX.Element}
* @constructor
*/
const SideAreaLeft = (props) => {
const SideAreaLeft = props => {
const { post, slot, postCount } = props
const { locale } = useGlobal()
const showToc = post && post.toc && post.toc.length > 1
@@ -27,7 +27,7 @@ const SideAreaLeft = (props) => {
<section className='w-60'>
{/* 菜单 */}
<section className='shadow hidden lg:block mb-5 pb-4 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<Logo/>
<Logo {...props}/>
<div className='pt-2 px-2 font-sans'>
<MenuButtonGroup allowCollapse={true} {...props} />
</div>

View File

@@ -98,7 +98,7 @@ const TopNav = (props) => {
</div>
<div className='flex'>
<Logo/>
<Logo {...props}/>
</div>
{/* 右侧功能 */}

View File

@@ -2,7 +2,6 @@ const CONFIG_NEXT = {
HOME_BANNER: false, // 首页是否显示大图及标语 [true,false]
HOME_BANNER_Strings: ['Hi我是一个程序员', 'Hi我是一个打工人', 'Hi我是一个干饭人', '欢迎来到我的博客🎉'], // 首页大图标语文字
HOME_BANNER_IMAGE: './bg_image.jpg', // 背景图地址
NAV_TYPE: 'normal', // ['fixed','autoCollapse','normal'] 分别是固定屏幕顶部、屏幕顶部自动折叠,不固定