diff --git a/components/Analytics.js b/components/Analytics.js
deleted file mode 100644
index c7655654..00000000
--- a/components/Analytics.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { useGlobal } from '@/lib/global'
-
-/**
- * 统计网站信息
- * @param {*} param0
- * @returns
- */
-export default function Analytics ({ postCount }) {
- const { locale } = useGlobal()
-
- return <>
- {/*
{locale.COMMON.ANALYTICS}
*/}
-
-
- {postCount} {locale.COMMON.POSTS}
-
- | {locale.COMMON.VISITORS}
- {/*
- | {locale.COMMON.VIEWS} */}
-
->
-}
diff --git a/components/ThirdPartyScript.js b/components/CommonScript.js
similarity index 98%
rename from components/ThirdPartyScript.js
rename to components/CommonScript.js
index c06c3722..45682806 100644
--- a/components/ThirdPartyScript.js
+++ b/components/CommonScript.js
@@ -5,7 +5,7 @@ import BLOG from '@/blog.config'
* @returns {JSX.Element}
* @constructor
*/
-const ThirdPartyScript = () => {
+const CommonScript = () => {
return (<>
{BLOG.comment?.DaoVoiceId && (<>
{/* DaoVoice 反馈 */}
@@ -109,4 +109,4 @@ const ThirdPartyScript = () => {
>)
}
-export default ThirdPartyScript
+export default CommonScript
diff --git a/jsconfig.json b/jsconfig.json
index 54e65f4b..9802ad57 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -5,7 +5,7 @@
"@/*": ["./*"],
"@/components/*": ["components/*"],
"@/data/*": ["data/*"],
- "@/layouts/*": ["layouts/*"],
+ "@/layouts/*": ["theme/*"],
"@/lib/*": ["lib/*"],
"@/styles/*": ["styles/*"]
}
diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js
index 1fc4f5f7..74f95a7c 100644
--- a/lib/notion/getNotionData.js
+++ b/lib/notion/getNotionData.js
@@ -10,7 +10,10 @@ import { getAllTags } from './getAllTags'
* 获取博客数据
* @param {*} pageId
* @param {*} from
- * @returns
+ * @param latestPostCount 截取最新文章数量
+ * @param tagsCount 截取标签数量
+ * @param includePage 是否包含PAGE类型
+ * @returns { allPosts: '文章列表', latestPosts: ’最新文章, categories:‘分类列表’, postCount:'文章总数',tags:'标签列表' }
* allPosts 所有博客
* categories 所有分类
* tags 所有标签
diff --git a/pages/404.js b/pages/404.js
index df0f6ce7..7fd48806 100644
--- a/pages/404.js
+++ b/pages/404.js
@@ -1,38 +1,11 @@
+import { Layout404 } from '@/themes'
+
/**
* 自定义404界面
* @returns {JSX.Element}
* @constructor
*/
-import { useEffect } from 'react'
-import BaseLayout from '@/layouts/BaseLayout'
-import BLOG from '@/blog.config'
-import { useRouter } from 'next/router'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faSpinner } from '@fortawesome/free-solid-svg-icons'
export default function Custom404 () {
- const router = useRouter()
- useEffect(() => {
- // 延时3秒如果加载失败就返回首页
- setTimeout(() => {
- if (window) {
- const article = document.getElementById('container')
- if (!article) {
- router.push('/')
- }
- }
- }, 30000000)
- })
-
- return
-
-
-
404
-
-
页面无法加载,即将返回首页
-
-
-
-
+ return
}
diff --git a/pages/_document.js b/pages/_document.js
index e947e64c..aac649e5 100644
--- a/pages/_document.js
+++ b/pages/_document.js
@@ -1,7 +1,7 @@
// eslint-disable-next-line @next/next/no-document-import-in-page
import Document, { Html, Head, Main, NextScript } from 'next/document'
import BLOG from '@/blog.config'
-import ThirdPartyScript from '@/components/ThirdPartyScript'
+import CommonScript from '@/components/CommonScript'
class MyDocument extends Document {
static async getInitialProps (ctx) {
@@ -15,7 +15,7 @@ class MyDocument extends Document {
-
+
diff --git a/pages/about.js b/pages/about.js
index eb97dcbb..af382f68 100644
--- a/pages/about.js
+++ b/pages/about.js
@@ -1,58 +1,40 @@
-import BLOG from '@/blog.config'
-import ArticleDetail from '@/components/ArticleDetail'
-import BaseLayout from '@/layouts/BaseLayout'
-import { useGlobal } from '@/lib/global'
-import {
- getPostBlocks
-} from '@/lib/notion'
+import { getPostBlocks } from '@/lib/notion'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import Custom404 from '@/pages/404'
-import 'prismjs'
-import 'prismjs/components/prism-bash'
-import 'prismjs/components/prism-javascript'
-import 'prismjs/components/prism-markup'
-import 'prismjs/components/prism-python'
-import 'prismjs/components/prism-typescript'
import React from 'react'
+import { LayoutSlug } from '@/themes'
/**
* 关于页面,默认取notion中slug为about的文章
- * @param {*} param0
+ * @param {*} props
* @returns
*/
-const About = ({ post, tags, prev, next, postCount, categories }) => {
- if (!post) {
+const About = (props) => {
+ if (!props.post) {
return
}
- const { locale } = useGlobal()
- post.title = locale.NAV.ABOUT
- const meta = {
- title: `${locale.NAV.ABOUT} | ${BLOG.title} `,
- description: post.summary,
- type: 'post',
- tags: []
- }
-
- return (
-
-
-
- )
+ return
}
export async function getStaticProps () {
const from = 'about-props'
- const { allPosts, categories, tags, postCount, latestPosts } = await getGlobalNotionData({ from, includePage: true })
+ const {
+ allPosts,
+ categories,
+ tags,
+ postCount,
+ latestPosts
+ } = await getGlobalNotionData({
+ from,
+ includePage: true
+ })
const post = allPosts.find(p => p.slug === 'about')
if (!post) {
- return { props: {}, revalidate: 1 }
+ return {
+ props: {},
+ revalidate: 1
+ }
}
post.blockMap = await getPostBlocks(post.id, 'slug')
@@ -62,7 +44,15 @@ export async function getStaticProps () {
const next = allPosts.slice(index + 1, index + 2)[0] ?? allPosts[0]
return {
- props: { post, tags, prev, next, categories, postCount, latestPosts },
+ props: {
+ post,
+ tags,
+ prev,
+ next,
+ categories,
+ postCount,
+ latestPosts
+ },
revalidate: 1
}
}
diff --git a/pages/archive/index.js b/pages/archive/index.js
index 429d06d4..3e4a4f52 100644
--- a/pages/archive/index.js
+++ b/pages/archive/index.js
@@ -1,15 +1,10 @@
-import BLOG from '@/blog.config'
-import BlogPostArchive from '@/components/BlogPostArchive'
-import Live2D from '@/components/Live2D'
-import BaseLayout from '@/layouts/BaseLayout'
-import { useGlobal } from '@/lib/global'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
-import React, { useEffect } from 'react'
+import React from 'react'
+import { LayoutArchive } from '@/themes'
export async function getStaticProps () {
- const from = 'index'
const { allPosts, categories, tags, postCount } =
- await getGlobalNotionData({ from })
+ await getGlobalNotionData({ from: 'archive-index' })
return {
props: {
@@ -22,63 +17,8 @@ export async function getStaticProps () {
}
}
-const Index = ({ posts, tags, categories, postCount }) => {
- const { locale } = useGlobal()
- // 深拷贝
- const postsSortByDate = Object.create(posts)
-
- // 时间排序
- postsSortByDate.sort((a, b) => {
- const dateA = new Date(a?.date.start_date || a.createdTime)
- 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 => {
- const date = post.date.start_date.slice(0, 7)
- if (archivePosts[date]) {
- archivePosts[date].push(post)
- } else {
- archivePosts[date] = [post]
- }
- })
-
- useEffect(() => {
- if (window) {
- const anchor = window.location.hash
- if (anchor) {
- setTimeout(() => {
- const anchorElement = document.getElementById(anchor.substring(1))
- if (anchorElement) {
- anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' })
- }
- }, 300)
- }
- }
- }, [])
-
- return (
-
-
- {Object.keys(archivePosts).map(archiveTitle => (
-
- ))}
-
-
-
- )
+const ArchiveIndex = (props) => {
+ return
}
-export default Index
+export default ArchiveIndex
diff --git a/pages/article/[slug].js b/pages/article/[slug].js
index b0fa34af..60ab8f31 100644
--- a/pages/article/[slug].js
+++ b/pages/article/[slug].js
@@ -1,78 +1,19 @@
import BLOG from '@/blog.config'
-import ArticleDetail from '@/components/ArticleDetail'
-import Card from '@/components/Card'
-import LatestPostsGroup from '@/components/LatestPostsGroup'
-import Live2D from '@/components/Live2D'
-import TocDrawer from '@/components/TocDrawer'
-import TocDrawerButton from '@/components/TocDrawerButton'
-import BaseLayout from '@/layouts/BaseLayout'
import { getPostBlocks } from '@/lib/notion'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
+import { LayoutSlug } from '@/themes'
import Custom404 from '@/pages/404'
-import { getPageTableOfContents } from 'notion-utils'
-import { useRef } from 'react'
/**
* 根据notion的slug访问页面
- * @param {*} param0
+ * @param {*} props
* @returns
*/
-const Slug = ({
- post,
- tags,
- prev,
- next,
- recommendPosts,
- categories,
- postCount,
- latestPosts
-}) => {
- if (!post) {
+const Slug = (props) => {
+ if (!props.post) {
return
}
- const meta = {
- title: `${post.title} | ${BLOG.title}`,
- description: post.summary,
- type: 'article',
- tags: post.tags
- }
-
- const drawerRight = useRef(null)
- const targetRef = typeof window !== 'undefined' ? document.getElementById('container') : null
- post.content = Object.keys(post?.blockMap?.block)
- post.toc = getPageTableOfContents(post, post.blockMap)
- const floatSlot = post?.toc?.length > 1 ? { drawerRight?.current?.handleSwitchVisible() }} />
: null
-
- return (
-
- }
- >
-
-
- {/* 悬浮目录按钮 */}
-
-
-
-
- {/* 宠物 */}
-
-
-
- )
+ return
}
export async function getStaticPaths () {
@@ -128,7 +69,7 @@ export async function getStaticProps ({ params: { slug } }) {
/**
*
- * @param {获取文章推荐文章} post
+ * @param post
* @param {*} allPosts
* @param {*} count
* @returns
diff --git a/pages/category/[category].js b/pages/category/[category].js
index 5adfea81..a2ecff19 100644
--- a/pages/category/[category].js
+++ b/pages/category/[category].js
@@ -1,33 +1,21 @@
-import BLOG from '@/blog.config'
-import BlogPostListScroll from '@/components/BlogPostListScroll'
-import CategoryList from '@/components/CategoryList'
-import StickyBar from '@/components/StickyBar'
-import BaseLayout from '@/layouts/BaseLayout'
-import { useGlobal } from '@/lib/global'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import React from 'react'
+import { LayoutCategory } from '@/themes'
-export default function Category ({ tags, posts, category, categories, latestPosts, postCount }) {
- const { locale } = useGlobal()
- const meta = {
- title: `${category} | ${locale.COMMON.CATEGORY} | ${BLOG.title}`,
- description: BLOG.description,
- type: 'website'
- }
- return
-
-
-
-
-
-
-
+export default function Category (props) {
+ return
}
export async function getStaticProps ({ params }) {
const from = 'category-props'
const category = params.category
- const { allPosts, categories, tags, postCount, latestPosts } = await getGlobalNotionData({ from })
+ const {
+ allPosts,
+ categories,
+ tags,
+ postCount,
+ latestPosts
+ } = await getGlobalNotionData({ from })
const filteredPosts = allPosts.filter(
post => post && post.category && post.category.includes(category)
)
diff --git a/pages/category/index.js b/pages/category/index.js
index a3d1f7c7..c295f452 100644
--- a/pages/category/index.js
+++ b/pages/category/index.js
@@ -1,32 +1,9 @@
-import BLOG from '@/blog.config'
-import BaseLayout from '@/layouts/BaseLayout'
-import { useGlobal } from '@/lib/global'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
-import { faFolder, faThList } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import Link from 'next/link'
import React from 'react'
+import { LayoutCategoryIndex } from '@/themes'
-export default function Category ({ tags, allPosts, categories, postCount, latestPosts }) {
- const { locale } = useGlobal()
- const meta = {
- title: `${locale.COMMON.CATEGORY} | ${BLOG.title}`,
- description: BLOG.description,
- type: 'website'
- }
- return
-
-
{locale.COMMON.CATEGORY}:
-
- {Object.keys(categories).map(category => {
- return
-
- {category}({categories[category]})
-
- })}
-
-
-
+export default function Category (props) {
+ return
}
export async function getStaticProps () {
diff --git a/pages/index.js b/pages/index.js
index c5d8177a..6fbb1073 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,12 +1,11 @@
import BLOG from '@/blog.config'
-import BlogPostListPage from '@/components/BlogPostListPage'
-import BlogPostListScroll from '@/components/BlogPostListScroll'
-import Card from '@/components/Card'
-import Header from '@/components/Header'
-import LatestPostsGroup from '@/components/LatestPostsGroup'
-import BaseLayout from '@/layouts/BaseLayout'
import { getPostBlocks } from '@/lib/notion'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
+import { LayoutIndex } from '@/themes'
+
+const Index = (props) => {
+ return
+}
export async function getStaticProps () {
const from = 'index'
@@ -19,7 +18,7 @@ export async function getStaticProps () {
// 处理分页
const page = 1
- let postsToShow = []
+ let postsToShow
if (BLOG.postListStyle !== 'page') {
postsToShow = Array.from(allPosts)
} else {
@@ -49,28 +48,4 @@ export async function getStaticProps () {
}
}
-const Index = ({ posts, tags, meta, categories, postCount, latestPosts }) => {
- return (
- }
- meta={meta}
- tags={tags}
- sideBarSlot={ }
- rightAreaSlot={
- BLOG.widget?.showLatestPost &&
- }
- postCount={postCount}
- categories={categories}
- >
- {BLOG.postListStyle !== 'page'
- ? (
-
- )
- : (
-
- )}
-
- )
-}
-
export default Index
diff --git a/pages/page/[page].js b/pages/page/[page].js
index a91e80a2..5ed48e0f 100644
--- a/pages/page/[page].js
+++ b/pages/page/[page].js
@@ -1,30 +1,14 @@
import BLOG from '@/blog.config'
-import BlogPostListPage from '@/components/BlogPostListPage'
-import Header from '@/components/Header'
-import LatestPostsGroup from '@/components/LatestPostsGroup'
-import BaseLayout from '@/layouts/BaseLayout'
import { getPostBlocks } from '@/lib/notion'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
-import Custom404 from '../404'
+import { LayoutPage } from '@/themes'
+import Custom404 from '@/pages/404'
-const Page = ({ page, posts, tags, meta, categories, postCount, latestPosts }) => {
- if (!meta || BLOG.postListStyle !== 'page') {
- return
+const Page = (props) => {
+ if (!props?.meta) {
+ return
}
-
- return (
- }
- meta={meta}
- tags={tags}
- sideBarSlot={ }
- rightAreaSlot={BLOG.widget?.showLatestPost && }
- postCount={postCount}
- categories={categories}
- >
-
-
- )
+ return
}
export async function getStaticPaths () {
@@ -40,7 +24,13 @@ export async function getStaticPaths () {
export async function getStaticProps ({ params: { page } }) {
const from = `page-${page}`
- const { allPosts, latestPosts, categories, tags, postCount } = await getGlobalNotionData({ from })
+ const {
+ allPosts,
+ latestPosts,
+ categories,
+ tags,
+ postCount
+ } = await getGlobalNotionData({ from })
const meta = {
title: `${page} | Page | ${BLOG.title}`,
description: BLOG.description,
diff --git a/pages/search.js b/pages/search.js
index f342072c..79854860 100644
--- a/pages/search.js
+++ b/pages/search.js
@@ -1,18 +1,14 @@
-import BLOG from '@/blog.config'
-import BlogPostListScroll from '@/components/BlogPostListScroll'
-import StickyBar from '@/components/StickyBar'
-import BaseLayout from '@/layouts/BaseLayout'
-import { useGlobal } from '@/lib/global'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
-import { faSearch } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { useRouter } from 'next/router'
+import { LayoutSearch } from '@/themes'
export async function getStaticProps () {
- const from = 'search-props'
- const { allPosts, categories, tags, postCount, latestPosts } =
- await getGlobalNotionData({ from })
-
+ const {
+ allPosts,
+ categories,
+ tags,
+ postCount,
+ latestPosts
+ } = await getGlobalNotionData({ from: 'search-props' })
return {
props: {
posts: allPosts,
@@ -25,51 +21,8 @@ export async function getStaticProps () {
}
}
-const Search = ({ posts, tags, categories, postCount }) => {
- let filteredPosts = []
- 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())
- })
- } else {
- filteredPosts = posts
- }
-
- const { locale } = useGlobal()
- const meta = {
- title: `${searchKey || ''} | ${locale.NAV.SEARCH} | ${BLOG.title} `,
- description: BLOG.description,
- type: 'website'
- }
- return (
-
-
-
- {' '}
- {filteredPosts.length} {locale.COMMON.RESULT_OF_SEARCH}
-
-
-
-
-
-
- )
+const Search = (props) => {
+ return
}
-export function getSearchKey () {
- const router = useRouter()
- if (router.query && router.query.s) {
- return router.query.s
- }
- return null
-}
export default Search
diff --git a/pages/tag/[tag].js b/pages/tag/[tag].js
index 06a8160d..908c329d 100644
--- a/pages/tag/[tag].js
+++ b/pages/tag/[tag].js
@@ -1,39 +1,24 @@
-import BLOG from '@/blog.config'
-import BlogPostListScroll from '@/components/BlogPostListScroll'
-import StickyBar from '@/components/StickyBar'
-import TagList from '@/components/TagList'
-import BaseLayout from '@/layouts/BaseLayout'
-import { useGlobal } from '@/lib/global'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
+import { LayoutTag } from '@/themes'
-export default function Tag ({ tags, posts, tag, categories, postCount, latestPosts }) {
- const { locale } = useGlobal()
-
- const meta = {
- title: `${tag} | ${locale.COMMON.TAGS} | ${BLOG.title}`,
- description: BLOG.description,
- type: 'website'
- }
-
- // 将当前选中的标签置顶🔝
- if (!tags) tags = []
- const currentTag = tags?.find(r => r?.name === tag)
- const newTags = currentTag ? [currentTag].concat(tags.filter(r => r?.name !== tag)) : tags.filter(r => r?.name !== tag)
-
- return
-
-
-
-
-
-
-
+const Tag = (props) => {
+ return
}
export async function getStaticProps ({ params }) {
const tag = params.tag
const from = 'tag-props'
- const { allPosts, categories, tags, postCount, latestPosts } = await getGlobalNotionData({ from, includePage: true, tagsCount: 0 })
+ const {
+ allPosts,
+ categories,
+ tags,
+ postCount,
+ latestPosts
+ } = await getGlobalNotionData({
+ from,
+ includePage: true,
+ tagsCount: 0
+ })
const filteredPosts = allPosts.filter(
post => post && post.tags && post.tags.includes(tag)
)
@@ -52,8 +37,8 @@ export async function getStaticProps ({ params }) {
/**
* 获取所有的标签
- * @param {*}} allPosts
* @returns
+ * @param tags
*/
function getTagNames (tags) {
const tagNames = []
@@ -65,7 +50,10 @@ function getTagNames (tags) {
export async function getStaticPaths () {
const from = 'tag-static-path'
- const { tags } = await getGlobalNotionData({ from, tagsCount: 0 })
+ const { tags } = await getGlobalNotionData({
+ from,
+ tagsCount: 0
+ })
const tagNames = getTagNames(tags)
return {
@@ -73,3 +61,5 @@ export async function getStaticPaths () {
fallback: true
}
}
+
+export default Tag
diff --git a/pages/tag/index.js b/pages/tag/index.js
index 6977f37d..5260a5ca 100644
--- a/pages/tag/index.js
+++ b/pages/tag/index.js
@@ -1,34 +1,23 @@
-import BLOG from '@/blog.config'
-import TagItem from '@/components/TagItem'
-import BaseLayout from '@/layouts/BaseLayout'
-import { useGlobal } from '@/lib/global'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
-import { faTags } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
+import { LayoutTagIndex } from '@/themes'
-export default function Tag ({ tags, categories, postCount, latestPosts }) {
- const { locale } = useGlobal()
- const meta = {
- title: `${locale.COMMON.TAGS} | ${BLOG.title}`,
- description: BLOG.description,
- type: 'website'
- }
- return
-
-
{locale.COMMON.TAGS}:
-
-
-
+const TagIndex = (props) => {
+ return
}
export async function getStaticProps () {
const from = 'tag-index-props'
- const { categories, tags, postCount, latestPosts } = await getGlobalNotionData({ from, includePage: true, tagsCount: 0 })
+ const {
+ categories,
+ tags,
+ postCount,
+ latestPosts
+ } = await getGlobalNotionData({
+ from,
+ includePage: true,
+ tagsCount: 0
+ })
return {
props: {
@@ -40,3 +29,5 @@ export async function getStaticProps () {
revalidate: 1
}
}
+
+export default TagIndex
diff --git a/tailwind.config.js b/tailwind.config.js
index 565b54cc..03b30c8e 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -8,7 +8,7 @@ const fontSerifCJK = !CJK()
? []
: [`"Noto Serif CJK ${CJK()}"`, `"Noto Serif ${CJK()}"`]
module.exports = {
- purge: ['./pages/**/*.js', './components/**/*.js', './layouts/**/*.js'],
+ purge: ['./pages/**/*.js', './components/**/*.js', './layouts/**/*.js', './themes/**/*.js'],
darkMode: BLOG.appearance === 'class' ? 'media' : 'class', // or 'media' or 'class'
theme: {
fontFamily: {
diff --git a/themes/NEXT/Layout404.js b/themes/NEXT/Layout404.js
new file mode 100644
index 00000000..50d9d5ce
--- /dev/null
+++ b/themes/NEXT/Layout404.js
@@ -0,0 +1,35 @@
+import { useRouter } from 'next/router'
+import LayoutBase from './LayoutBase'
+import BLOG from '@/blog.config'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faSpinner } from '@fortawesome/free-solid-svg-icons'
+import { useEffect } from 'react'
+
+export const Layout404 = () => {
+ const router = useRouter()
+ useEffect(() => {
+ // 延时3秒如果加载失败就返回首页
+ setTimeout(() => {
+ if (window) {
+ const article = document.getElementById('container')
+ if (!article) {
+ router.push('/').then(() => {
+ console.log('找不到页面', router.asPath)
+ })
+ }
+ }
+ }, 30000000)
+ })
+
+ return
+
+
+
404
+
+
页面无法加载,即将返回首页
+
+
+
+
+}
diff --git a/themes/NEXT/LayoutArchive.js b/themes/NEXT/LayoutArchive.js
new file mode 100644
index 00000000..9daca461
--- /dev/null
+++ b/themes/NEXT/LayoutArchive.js
@@ -0,0 +1,65 @@
+import { useGlobal } from '@/lib/global'
+import BLOG from '@/blog.config'
+import React, { useEffect } from 'react'
+import LayoutBase from './LayoutBase'
+import BlogPostArchive from './components/BlogPostArchive'
+import Live2D from './components/Live2D'
+
+export const LayoutArchive = ({ posts, tags, categories, postCount }) => {
+ const { locale } = useGlobal()
+ // 深拷贝
+ const postsSortByDate = Object.create(posts)
+
+ // 时间排序
+ postsSortByDate.sort((a, b) => {
+ const dateA = new Date(a?.date.start_date || a.createdTime)
+ 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 => {
+ const date = post.date.start_date.slice(0, 7)
+ if (archivePosts[date]) {
+ archivePosts[date].push(post)
+ } else {
+ archivePosts[date] = [post]
+ }
+ })
+
+ useEffect(() => {
+ if (window) {
+ const anchor = window.location.hash
+ if (anchor) {
+ setTimeout(() => {
+ const anchorElement = document.getElementById(anchor.substring(1))
+ if (anchorElement) {
+ anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' })
+ }
+ }, 300)
+ }
+ }
+ }, [])
+
+ return (
+
+
+ {Object.keys(archivePosts).map(archiveTitle => (
+
+ ))}
+
+
+
+ )
+}
diff --git a/layouts/BaseLayout.js b/themes/NEXT/LayoutBase.js
similarity index 83%
rename from layouts/BaseLayout.js
rename to themes/NEXT/LayoutBase.js
index a516fced..4e963b47 100644
--- a/layouts/BaseLayout.js
+++ b/themes/NEXT/LayoutBase.js
@@ -1,13 +1,13 @@
import BLOG from '@/blog.config'
import CommonHead from '@/components/CommonHead'
-import FloatDarkModeButton from '@/components/FloatDarkModeButton'
-import Footer from '@/components/Footer'
-import JumpToBottomButton from '@/components/JumpToBottomButton'
-import JumpToTopButton from '@/components/JumpToTopButton'
-import LoadingCover from '@/components/LoadingCover'
-import SideAreaLeft from '@/components/SideAreaLeft'
-import SideAreaRight from '@/components/SideAreaRight'
-import TopNav from '@/components/TopNav'
+import FloatDarkModeButton from './components/FloatDarkModeButton'
+import Footer from './components/Footer'
+import JumpToBottomButton from './components/JumpToBottomButton'
+import JumpToTopButton from './components/JumpToTopButton'
+import LoadingCover from './components/LoadingCover'
+import SideAreaLeft from './components/SideAreaLeft'
+import SideAreaRight from './components/SideAreaRight'
+import TopNav from './components/TopNav'
import { useGlobal } from '@/lib/global'
import PropTypes from 'prop-types'
import React, { useEffect, useRef, useState } from 'react'
@@ -17,23 +17,18 @@ import smoothscroll from 'smoothscroll-polyfill'
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
* @param children
* @param layout
- * @param fullWidth
* @param tags
* @param meta
* @param post
- * @param totalPosts
* @param currentSearch
* @param currentCategory
* @param currentTag
* @param categories
- * @param customMeta
* @returns {JSX.Element}
* @constructor
*/
-const BaseLayout = ({
+const LayoutBase = ({
children,
- layout,
- fullWidth,
headerSlot,
tags,
meta,
@@ -45,8 +40,7 @@ const BaseLayout = ({
currentSearch,
currentCategory,
currentTag,
- categories,
- ...customMeta
+ categories
}) => {
const { onLoading } = useGlobal()
const targetRef = useRef(null)
@@ -81,7 +75,7 @@ const BaseLayout = ({
<>{headerSlot}>
-
+
@@ -111,8 +105,8 @@ const BaseLayout = ({
)
}
-BaseLayout.propTypes = {
+LayoutBase.propTypes = {
children: PropTypes.node
}
-export default BaseLayout
+export default LayoutBase
diff --git a/themes/NEXT/LayoutCategory.js b/themes/NEXT/LayoutCategory.js
new file mode 100644
index 00000000..25d6e58e
--- /dev/null
+++ b/themes/NEXT/LayoutCategory.js
@@ -0,0 +1,23 @@
+import { useGlobal } from '@/lib/global'
+import BLOG from '@/blog.config'
+import LayoutBase from '@/themes/NEXT/LayoutBase'
+import StickyBar from './components/StickyBar'
+import CategoryList from './components/CategoryList'
+import BlogPostListScroll from './components/BlogPostListScroll'
+
+export const LayoutCategory = ({ tags, posts, category, categories, latestPosts, postCount }) => {
+ const { locale } = useGlobal()
+ const meta = {
+ title: `${category} | ${locale.COMMON.CATEGORY} | ${BLOG.title}`,
+ description: BLOG.description,
+ type: 'website'
+ }
+ return
+
+
+
+
+
+
+
+}
diff --git a/themes/NEXT/LayoutCategoryIndex.js b/themes/NEXT/LayoutCategoryIndex.js
new file mode 100644
index 00000000..8140ed4a
--- /dev/null
+++ b/themes/NEXT/LayoutCategoryIndex.js
@@ -0,0 +1,38 @@
+import { useGlobal } from '@/lib/global'
+import BLOG from '@/blog.config'
+import LayoutBase from './LayoutBase'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faFolder, faThList } from '@fortawesome/free-solid-svg-icons'
+import Link from 'next/link'
+
+export const LayoutCategoryIndex = ({
+ tags,
+ allPosts,
+ categories,
+ postCount,
+ latestPosts
+}) => {
+ const { locale } = useGlobal()
+ const meta = {
+ title: `${locale.COMMON.CATEGORY} | ${BLOG.title}`,
+ description: BLOG.description,
+ type: 'website'
+ }
+ return
+
+
+ {locale.COMMON.CATEGORY}:
+
+
+ {Object.keys(categories).map(category => {
+ return
+
+ {category}({categories[category]})
+
+
+ })}
+
+
+
+}
diff --git a/themes/NEXT/LayoutIndex.js b/themes/NEXT/LayoutIndex.js
new file mode 100644
index 00000000..dfa6590b
--- /dev/null
+++ b/themes/NEXT/LayoutIndex.js
@@ -0,0 +1,29 @@
+import LayoutBase from './LayoutBase'
+import Header from './components/Header'
+import LatestPostsGroup from './components/LatestPostsGroup'
+import Card from './components/Card'
+import BlogPostListScroll from './components/BlogPostListScroll'
+import BlogPostListPage from './components/BlogPostListPage'
+import { CONFIG_NEXT } from './index'
+
+export const LayoutIndex = ({ posts, tags, meta, categories, postCount, latestPosts }) => {
+ return }
+ meta={meta}
+ tags={tags}
+ sideBarSlot={ }
+ rightAreaSlot={
+ CONFIG_NEXT.RIGHT_LATEST_POSTS &&
+ }
+ postCount={postCount}
+ categories={categories}
+ >
+ {CONFIG_NEXT.POSTS_LIST_TYPE !== 'page'
+ ? (
+
+ )
+ : (
+
+ )}
+
+}
diff --git a/themes/NEXT/LayoutPage.js b/themes/NEXT/LayoutPage.js
new file mode 100644
index 00000000..965ffc03
--- /dev/null
+++ b/themes/NEXT/LayoutPage.js
@@ -0,0 +1,19 @@
+import LayoutBase from './LayoutBase'
+import LatestPostsGroup from './components/LatestPostsGroup'
+import BlogPostListPage from './components/BlogPostListPage'
+import { CONFIG_NEXT } from './index'
+
+export const LayoutPage = ({ page, posts, tags, meta, categories, postCount, latestPosts }) => {
+ return (
+ }
+ rightAreaSlot={CONFIG_NEXT.RIGHT_LATEST_POSTS && }
+ postCount={postCount}
+ categories={categories}
+ >
+
+
+ )
+}
diff --git a/themes/NEXT/LayoutSearch.js b/themes/NEXT/LayoutSearch.js
new file mode 100644
index 00000000..5204b371
--- /dev/null
+++ b/themes/NEXT/LayoutSearch.js
@@ -0,0 +1,56 @@
+import LayoutBase from './LayoutBase'
+import StickyBar from './components/StickyBar'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faSearch } from '@fortawesome/free-solid-svg-icons'
+import BlogPostListScroll from './components/BlogPostListScroll'
+import { useGlobal } from '@/lib/global'
+import BLOG from '@/blog.config'
+import { useRouter } from 'next/router'
+
+export const LayoutSearch = ({ posts, tags, categories, postCount }) => {
+ let filteredPosts
+ 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())
+ })
+ } else {
+ filteredPosts = posts
+ }
+
+ const { locale } = useGlobal()
+ const meta = {
+ title: `${searchKey || ''} | ${locale.NAV.SEARCH} | ${BLOG.title} `,
+ description: BLOG.description,
+ type: 'website'
+ }
+ return (
+
+
+
+ {' '}
+ {filteredPosts.length} {locale.COMMON.RESULT_OF_SEARCH}
+
+
+
+
+
+
+ )
+}
+
+function getSearchKey () {
+ const router = useRouter()
+ if (router.query && router.query.s) {
+ return router.query.s
+ }
+ return null
+}
diff --git a/themes/NEXT/LayoutSlug.js b/themes/NEXT/LayoutSlug.js
new file mode 100644
index 00000000..fc7b7f01
--- /dev/null
+++ b/themes/NEXT/LayoutSlug.js
@@ -0,0 +1,76 @@
+import BLOG from '@/blog.config'
+import { getPageTableOfContents } from 'notion-utils'
+import TocDrawerButton from './components/TocDrawerButton'
+import LayoutBase from './LayoutBase'
+import Card from './components/Card'
+import LatestPostsGroup from './components/LatestPostsGroup'
+import ArticleDetail from './components/ArticleDetail'
+import TocDrawer from './components/TocDrawer'
+import Live2D from './components/Live2D'
+import { useRef } from 'react'
+import 'prismjs'
+import 'prismjs/components/prism-bash'
+import 'prismjs/components/prism-javascript'
+import 'prismjs/components/prism-markup'
+import 'prismjs/components/prism-python'
+import 'prismjs/components/prism-typescript'
+import { CONFIG_NEXT } from './index'
+
+export const LayoutSlug = ({
+ post,
+ tags,
+ prev,
+ next,
+ recommendPosts,
+ categories,
+ postCount,
+ latestPosts
+}) => {
+ const meta = {
+ title: `${post.title} | ${BLOG.title}`,
+ description: post.summary,
+ type: 'article',
+ tags: post.tags
+ }
+
+ const drawerRight = useRef(null)
+ const targetRef = typeof window !== 'undefined' ? document.getElementById('container') : null
+ post.content = Object.keys(post?.blockMap?.block)
+ post.toc = getPageTableOfContents(post, post.blockMap)
+ const floatSlot = post?.toc?.length > 1
+ ? {
+ drawerRight?.current?.handleSwitchVisible()
+ }} />
+ : null
+
+ return (
+
+ }
+ >
+
+
+ {/* 悬浮目录按钮 */}
+
+
+
+
+ {/* 宠物 */}
+
+
+
+ )
+}
diff --git a/themes/NEXT/LayoutTag.js b/themes/NEXT/LayoutTag.js
new file mode 100644
index 00000000..944a1cf5
--- /dev/null
+++ b/themes/NEXT/LayoutTag.js
@@ -0,0 +1,30 @@
+import { useGlobal } from '@/lib/global'
+import BLOG from '@/blog.config'
+import LayoutBase from './LayoutBase'
+import StickyBar from './components/StickyBar'
+import TagList from './components/TagList'
+import BlogPostListScroll from './components/BlogPostListScroll'
+
+export const LayoutTag = ({ tags, posts, tag, categories, postCount, latestPosts }) => {
+ const { locale } = useGlobal()
+
+ const meta = {
+ title: `${tag} | ${locale.COMMON.TAGS} | ${BLOG.title}`,
+ description: BLOG.description,
+ type: 'website'
+ }
+
+ // 将当前选中的标签置顶🔝
+ if (!tags) tags = []
+ const currentTag = tags?.find(r => r?.name === tag)
+ const newTags = currentTag ? [currentTag].concat(tags.filter(r => r?.name !== tag)) : tags.filter(r => r?.name !== tag)
+
+ return
+
+
+
+
+
+
+
+}
diff --git a/themes/NEXT/LayoutTagIndex.js b/themes/NEXT/LayoutTagIndex.js
new file mode 100644
index 00000000..6400d9e1
--- /dev/null
+++ b/themes/NEXT/LayoutTagIndex.js
@@ -0,0 +1,25 @@
+import { useGlobal } from '@/lib/global'
+import BLOG from '@/blog.config'
+import LayoutBase from './LayoutBase'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faTags } from '@fortawesome/free-solid-svg-icons'
+import TagItem from './components/TagItem'
+
+export const LayoutTagIndex = ({ tags, categories, postCount, latestPosts }) => {
+ const { locale } = useGlobal()
+ const meta = {
+ title: `${locale.COMMON.TAGS} | ${BLOG.title}`,
+ description: BLOG.description,
+ type: 'website'
+ }
+ return
+
+
{locale.COMMON.TAGS}:
+
+
+
+}
diff --git a/components/ArticleCopyright.js b/themes/NEXT/components/ArticleCopyright.js
similarity index 100%
rename from components/ArticleCopyright.js
rename to themes/NEXT/components/ArticleCopyright.js
diff --git a/components/ArticleDetail.js b/themes/NEXT/components/ArticleDetail.js
similarity index 96%
rename from components/ArticleDetail.js
rename to themes/NEXT/components/ArticleDetail.js
index e099dc48..ad29e8f6 100644
--- a/components/ArticleDetail.js
+++ b/themes/NEXT/components/ArticleDetail.js
@@ -1,9 +1,9 @@
import BLOG from '@/blog.config'
-import BlogAround from '@/components/BlogAround'
+import BlogAround from '@/themes/NEXT/components/BlogAround'
import Comment from '@/components/Comment'
-import RecommendPosts from '@/components/RecommendPosts'
-import ShareBar from '@/components/ShareBar'
-import TagItem from '@/components/TagItem'
+import RecommendPosts from '@/themes/NEXT/components/RecommendPosts'
+import ShareBar from '@/themes/NEXT/components/ShareBar'
+import TagItem from '@/themes/NEXT/components/TagItem'
import formatDate from '@/lib/formatDate'
import { useGlobal } from '@/lib/global'
import { faEye, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
diff --git a/components/BlogAround.js b/themes/NEXT/components/BlogAround.js
similarity index 100%
rename from components/BlogAround.js
rename to themes/NEXT/components/BlogAround.js
diff --git a/components/BlogPostArchive.js b/themes/NEXT/components/BlogPostArchive.js
similarity index 100%
rename from components/BlogPostArchive.js
rename to themes/NEXT/components/BlogPostArchive.js
diff --git a/components/BlogPostCard.js b/themes/NEXT/components/BlogPostCard.js
similarity index 100%
rename from components/BlogPostCard.js
rename to themes/NEXT/components/BlogPostCard.js
diff --git a/components/BlogPostListEmpty.js b/themes/NEXT/components/BlogPostListEmpty.js
similarity index 100%
rename from components/BlogPostListEmpty.js
rename to themes/NEXT/components/BlogPostListEmpty.js
diff --git a/components/BlogPostListPage.js b/themes/NEXT/components/BlogPostListPage.js
similarity index 85%
rename from components/BlogPostListPage.js
rename to themes/NEXT/components/BlogPostListPage.js
index 4305f986..1f1b89b5 100644
--- a/components/BlogPostListPage.js
+++ b/themes/NEXT/components/BlogPostListPage.js
@@ -1,7 +1,7 @@
-import BlogPostCard from '@/components/BlogPostCard'
+import BlogPostCard from '@/themes/NEXT/components/BlogPostCard'
import PaginationNumber from './PaginationNumber'
import BLOG from '@/blog.config'
-import BlogPostListEmpty from '@/components/BlogPostListEmpty'
+import BlogPostListEmpty from '@/themes/NEXT/components/BlogPostListEmpty'
/**
* 文章列表分页表格
diff --git a/components/BlogPostListScroll.js b/themes/NEXT/components/BlogPostListScroll.js
similarity index 94%
rename from components/BlogPostListScroll.js
rename to themes/NEXT/components/BlogPostListScroll.js
index 1c378bfa..b46250ed 100644
--- a/components/BlogPostListScroll.js
+++ b/themes/NEXT/components/BlogPostListScroll.js
@@ -1,6 +1,6 @@
import BLOG from '@/blog.config'
-import BlogPostCard from '@/components/BlogPostCard'
-import BlogPostListEmpty from '@/components/BlogPostListEmpty'
+import BlogPostCard from '@/themes/NEXT/components/BlogPostCard'
+import BlogPostListEmpty from '@/themes/NEXT/components/BlogPostListEmpty'
import { useGlobal } from '@/lib/global'
import throttle from 'lodash.throttle'
import React, { useCallback, useEffect, useRef, useState } from 'react'
diff --git a/components/Card.js b/themes/NEXT/components/Card.js
similarity index 100%
rename from components/Card.js
rename to themes/NEXT/components/Card.js
diff --git a/components/CategoryGroup.js b/themes/NEXT/components/CategoryGroup.js
similarity index 100%
rename from components/CategoryGroup.js
rename to themes/NEXT/components/CategoryGroup.js
diff --git a/components/CategoryList.js b/themes/NEXT/components/CategoryList.js
similarity index 100%
rename from components/CategoryList.js
rename to themes/NEXT/components/CategoryList.js
diff --git a/components/Collapse.js b/themes/NEXT/components/Collapse.js
similarity index 100%
rename from components/Collapse.js
rename to themes/NEXT/components/Collapse.js
diff --git a/components/ContactButton.js b/themes/NEXT/components/ContactButton.js
similarity index 100%
rename from components/ContactButton.js
rename to themes/NEXT/components/ContactButton.js
diff --git a/components/DarkModeButton.js b/themes/NEXT/components/DarkModeButton.js
similarity index 100%
rename from components/DarkModeButton.js
rename to themes/NEXT/components/DarkModeButton.js
diff --git a/components/FloatDarkModeButton.js b/themes/NEXT/components/FloatDarkModeButton.js
similarity index 100%
rename from components/FloatDarkModeButton.js
rename to themes/NEXT/components/FloatDarkModeButton.js
diff --git a/components/Footer.js b/themes/NEXT/components/Footer.js
similarity index 100%
rename from components/Footer.js
rename to themes/NEXT/components/Footer.js
diff --git a/components/Header.js b/themes/NEXT/components/Header.js
similarity index 100%
rename from components/Header.js
rename to themes/NEXT/components/Header.js
diff --git a/components/InfoCard.js b/themes/NEXT/components/InfoCard.js
similarity index 100%
rename from components/InfoCard.js
rename to themes/NEXT/components/InfoCard.js
diff --git a/components/JumpToBottomButton.js b/themes/NEXT/components/JumpToBottomButton.js
similarity index 100%
rename from components/JumpToBottomButton.js
rename to themes/NEXT/components/JumpToBottomButton.js
diff --git a/components/JumpToTopButton.js b/themes/NEXT/components/JumpToTopButton.js
similarity index 100%
rename from components/JumpToTopButton.js
rename to themes/NEXT/components/JumpToTopButton.js
diff --git a/components/LatestPostsGroup.js b/themes/NEXT/components/LatestPostsGroup.js
similarity index 100%
rename from components/LatestPostsGroup.js
rename to themes/NEXT/components/LatestPostsGroup.js
diff --git a/components/LeftFloatButton.js b/themes/NEXT/components/LeftFloatButton.js
similarity index 95%
rename from components/LeftFloatButton.js
rename to themes/NEXT/components/LeftFloatButton.js
index 5d339da0..86f343ba 100644
--- a/components/LeftFloatButton.js
+++ b/themes/NEXT/components/LeftFloatButton.js
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react'
import throttle from 'lodash.throttle'
-import DarkModeButton from '@/components/DarkModeButton'
+import DarkModeButton from '@/themes/NEXT/components/DarkModeButton'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faBars } from '@fortawesome/free-solid-svg-icons'
diff --git a/components/Live2D.js b/themes/NEXT/components/Live2D.js
similarity index 100%
rename from components/Live2D.js
rename to themes/NEXT/components/Live2D.js
diff --git a/components/Live2DWaifu.js b/themes/NEXT/components/Live2DWaifu.js
similarity index 100%
rename from components/Live2DWaifu.js
rename to themes/NEXT/components/Live2DWaifu.js
diff --git a/components/LoadingCover.js b/themes/NEXT/components/LoadingCover.js
similarity index 100%
rename from components/LoadingCover.js
rename to themes/NEXT/components/LoadingCover.js
diff --git a/components/Logo.js b/themes/NEXT/components/Logo.js
similarity index 100%
rename from components/Logo.js
rename to themes/NEXT/components/Logo.js
diff --git a/components/MenuButtonGroup.js b/themes/NEXT/components/MenuButtonGroup.js
similarity index 100%
rename from components/MenuButtonGroup.js
rename to themes/NEXT/components/MenuButtonGroup.js
diff --git a/components/NavBar.js b/themes/NEXT/components/NavBar.js
similarity index 100%
rename from components/NavBar.js
rename to themes/NEXT/components/NavBar.js
diff --git a/components/PaginationNumber.js b/themes/NEXT/components/PaginationNumber.js
similarity index 100%
rename from components/PaginationNumber.js
rename to themes/NEXT/components/PaginationNumber.js
diff --git a/components/PaginationSimple.js b/themes/NEXT/components/PaginationSimple.js
similarity index 100%
rename from components/PaginationSimple.js
rename to themes/NEXT/components/PaginationSimple.js
diff --git a/components/Progress.js b/themes/NEXT/components/Progress.js
similarity index 100%
rename from components/Progress.js
rename to themes/NEXT/components/Progress.js
diff --git a/components/RecommendPosts.js b/themes/NEXT/components/RecommendPosts.js
similarity index 100%
rename from components/RecommendPosts.js
rename to themes/NEXT/components/RecommendPosts.js
diff --git a/components/RewardButton.js b/themes/NEXT/components/RewardButton.js
similarity index 100%
rename from components/RewardButton.js
rename to themes/NEXT/components/RewardButton.js
diff --git a/components/SearchDrawer.js b/themes/NEXT/components/SearchDrawer.js
similarity index 100%
rename from components/SearchDrawer.js
rename to themes/NEXT/components/SearchDrawer.js
diff --git a/components/SearchInput.js b/themes/NEXT/components/SearchInput.js
similarity index 100%
rename from components/SearchInput.js
rename to themes/NEXT/components/SearchInput.js
diff --git a/components/ShareBar.js b/themes/NEXT/components/ShareBar.js
similarity index 100%
rename from components/ShareBar.js
rename to themes/NEXT/components/ShareBar.js
diff --git a/components/ShareButton.js b/themes/NEXT/components/ShareButton.js
similarity index 95%
rename from components/ShareButton.js
rename to themes/NEXT/components/ShareButton.js
index d3201828..64955fb9 100644
--- a/components/ShareButton.js
+++ b/themes/NEXT/components/ShareButton.js
@@ -1,5 +1,5 @@
import React from 'react'
-import ShareBar from '@/components/ShareBar'
+import ShareBar from '@/themes/NEXT/components/ShareBar'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faShareAltSquare } from '@fortawesome/free-solid-svg-icons'
diff --git a/components/SideAreaLeft.js b/themes/NEXT/components/SideAreaLeft.js
similarity index 58%
rename from components/SideAreaLeft.js
rename to themes/NEXT/components/SideAreaLeft.js
index 7e406901..989adefe 100644
--- a/components/SideAreaLeft.js
+++ b/themes/NEXT/components/SideAreaLeft.js
@@ -1,11 +1,10 @@
-import InfoCard from '@/components/InfoCard'
-import MenuButtonGroup from '@/components/MenuButtonGroup'
-import SearchInput from '@/components/SearchInput'
-import Toc from '@/components/Toc'
+import InfoCard from '@/themes/NEXT/components/InfoCard'
+import MenuButtonGroup from '@/themes/NEXT/components/MenuButtonGroup'
+import SearchInput from '@/themes/NEXT/components/SearchInput'
+import Toc from '@/themes/NEXT/components/Toc'
import { useGlobal } from '@/lib/global'
import React from 'react'
-import Analytics from './Analytics'
-import Tabs from '@/components/Tabs'
+import Tabs from '@/themes/NEXT/components/Tabs'
import BLOG from '@/blog.config'
import Logo from './Logo'
import Card from './Card'
@@ -50,7 +49,17 @@ const SideAreaLeft = ({ title, tags, currentTag, post, postCount, categories, cu
-
+ <>
+ {/* {locale.COMMON.ANALYTICS}
*/}
+
+
+ {postCount} {locale.COMMON.POSTS}
+
+ | {locale.COMMON.VISITORS}
+ {/*
+ | {locale.COMMON.VIEWS} */}
+
+ >
diff --git a/components/SideAreaRight.js b/themes/NEXT/components/SideAreaRight.js
similarity index 100%
rename from components/SideAreaRight.js
rename to themes/NEXT/components/SideAreaRight.js
diff --git a/components/SideBar.js b/themes/NEXT/components/SideBar.js
similarity index 93%
rename from components/SideBar.js
rename to themes/NEXT/components/SideBar.js
index 31f798d5..4989d5c4 100644
--- a/components/SideBar.js
+++ b/themes/NEXT/components/SideBar.js
@@ -1,6 +1,6 @@
-import CategoryGroup from '@/components/CategoryGroup'
-import InfoCard from '@/components/InfoCard'
-import TagGroups from '@/components/TagGroups'
+import CategoryGroup from '@/themes/NEXT/components/CategoryGroup'
+import InfoCard from '@/themes/NEXT/components/InfoCard'
+import TagGroups from '@/themes/NEXT/components/TagGroups'
import { useGlobal } from '@/lib/global'
import { faAngleDoubleRight, faTag, faThList } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
diff --git a/components/SideBarDrawer.js b/themes/NEXT/components/SideBarDrawer.js
similarity index 97%
rename from components/SideBarDrawer.js
rename to themes/NEXT/components/SideBarDrawer.js
index 87b731d4..9b76f431 100644
--- a/components/SideBarDrawer.js
+++ b/themes/NEXT/components/SideBarDrawer.js
@@ -1,4 +1,4 @@
-import SideBar from '@/components/SideBar'
+import SideBar from '@/themes/NEXT/components/SideBar'
import { useRouter } from 'next/router'
import React, { useEffect, useImperativeHandle } from 'react'
diff --git a/components/SocialButton.js b/themes/NEXT/components/SocialButton.js
similarity index 100%
rename from components/SocialButton.js
rename to themes/NEXT/components/SocialButton.js
diff --git a/components/StickyBar.js b/themes/NEXT/components/StickyBar.js
similarity index 100%
rename from components/StickyBar.js
rename to themes/NEXT/components/StickyBar.js
diff --git a/components/Tabs.js b/themes/NEXT/components/Tabs.js
similarity index 100%
rename from components/Tabs.js
rename to themes/NEXT/components/Tabs.js
diff --git a/components/TagGroups.js b/themes/NEXT/components/TagGroups.js
similarity index 88%
rename from components/TagGroups.js
rename to themes/NEXT/components/TagGroups.js
index 76778851..b9ca5fc9 100644
--- a/components/TagGroups.js
+++ b/themes/NEXT/components/TagGroups.js
@@ -1,4 +1,4 @@
-import TagItemMini from '@/components/TagItemMini'
+import TagItemMini from '@/themes/NEXT/components/TagItemMini'
/**
* 标签组
diff --git a/components/TagItem.js b/themes/NEXT/components/TagItem.js
similarity index 100%
rename from components/TagItem.js
rename to themes/NEXT/components/TagItem.js
diff --git a/components/TagItemMini.js b/themes/NEXT/components/TagItemMini.js
similarity index 100%
rename from components/TagItemMini.js
rename to themes/NEXT/components/TagItemMini.js
diff --git a/components/TagList.js b/themes/NEXT/components/TagList.js
similarity index 90%
rename from components/TagList.js
rename to themes/NEXT/components/TagList.js
index c892f0f7..31c741fc 100644
--- a/components/TagList.js
+++ b/themes/NEXT/components/TagList.js
@@ -1,5 +1,5 @@
import React from 'react'
-import TagItem from '@/components/TagItem'
+import TagItem from '@/themes/NEXT/components/TagItem'
/**
* 横向的标签列表
* @param tags
diff --git a/components/Toc.js b/themes/NEXT/components/Toc.js
similarity index 100%
rename from components/Toc.js
rename to themes/NEXT/components/Toc.js
diff --git a/components/TocDrawer.js b/themes/NEXT/components/TocDrawer.js
similarity index 97%
rename from components/TocDrawer.js
rename to themes/NEXT/components/TocDrawer.js
index 80f9e6c8..20e41ff5 100644
--- a/components/TocDrawer.js
+++ b/themes/NEXT/components/TocDrawer.js
@@ -1,4 +1,4 @@
-import Toc from '@/components/Toc'
+import Toc from '@/themes/NEXT/components/Toc'
import React, { useImperativeHandle, useState } from 'react'
import { useGlobal } from '@/lib/global'
diff --git a/components/TocDrawerButton.js b/themes/NEXT/components/TocDrawerButton.js
similarity index 100%
rename from components/TocDrawerButton.js
rename to themes/NEXT/components/TocDrawerButton.js
diff --git a/components/TopNav.js b/themes/NEXT/components/TopNav.js
similarity index 100%
rename from components/TopNav.js
rename to themes/NEXT/components/TopNav.js
diff --git a/components/WordCount.js b/themes/NEXT/components/WordCount.js
similarity index 100%
rename from components/WordCount.js
rename to themes/NEXT/components/WordCount.js
diff --git a/themes/NEXT/index.js b/themes/NEXT/index.js
new file mode 100644
index 00000000..654baa1e
--- /dev/null
+++ b/themes/NEXT/index.js
@@ -0,0 +1,87 @@
+export { LayoutIndex } from './LayoutIndex'
+export { LayoutSearch } from './LayoutSearch'
+export { LayoutArchive } from './LayoutArchive'
+export { LayoutSlug } from './LayoutSlug'
+export { Layout404 } from './Layout404'
+export { LayoutCategory } from './LayoutCategory'
+export { LayoutCategoryIndex } from './LayoutCategoryIndex'
+export { LayoutPage } from './LayoutPage'
+export { LayoutTag } from './LayoutTag'
+export { LayoutTagIndex } from './LayoutTagIndex'
+
+export const CONFIG_NEXT = {
+ // 首页相关配置
+ HOME_BANNER: false, // 首页是否显示大图及标语 [true,false]
+ POSTS_LIST_TYPE: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
+ // 右侧组件
+ RIGHT_LATEST_POSTS: false,
+
+ home: { // 首页
+ showHomeBanner: false,
+ homeBannerStrings: ['Hi,我是一个程序员', 'Hi,我是一个打工人', 'Hi,我是一个干饭人', '欢迎来到我的博客🎉'], // 首页大图标语文字
+ homeBannerImage: './bg_image.jpg', // 背景图地址
+ showPostCover: false, // 文章列表显示封面图
+ showPreview: true, // 列表展示文章预览
+ previewLines: 12, // 预览文章的篇幅
+ showSummary: false // 显示用户自定义摘要
+ },
+ appearance: 'auto', // ['light', 'dark', 'auto'],
+ font: 'font-serif tracking-wider subpixel-antialiased', // 文章字体 ['font-sans', 'font-serif', 'font-mono'] @see https://www.tailwindcss.cn/docs/font-family
+ lightBackground: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc
+ darkBackground: '#111827', // use hex value, don't forget '#'
+ path: '', // leave this empty unless you want to deploy in a folder
+ since: 2020, // if leave this empty, current year will be used.
+ postListStyle: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
+ postsPerPage: 6, // post counts per page
+ sortByDate: false,
+ topNavType: 'normal', // ['fixed','autoCollapse','normal'] 分别是固定顶部、固定底部滑动时自动折叠,不固定
+ menu: { // 菜单栏设置
+ showAbout: false, // 显示关于
+ showCategory: true, // 显示分类
+ showTag: true, // 显示标签
+ showArchive: true, // 显示归档
+ showSearch: true // 显示搜索
+ },
+ widget: { // 挂件及组件设置
+ showPet: false, // 是否显示宠物挂件
+ petLink: 'https://cdn.jsdelivr.net/npm/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json', // 挂件模型地址 @see https://github.com/xiazeyu/live2d-widget-models
+ showToTop: true, // 是否显示回顶
+ showToBottom: false, // 显示回底
+ showDarkMode: false, // 显示日间/夜间模式切换
+ showToc: true, // 移动端显示悬浮目录
+ showShareBar: false, // 文章分享功能
+ showRelatePosts: true, // 相关文章推荐
+ showCopyRight: true, // 文章版权声明
+ showLatestPost: false, // 右侧边栏显示最近更新
+ showCategoryList: false, // 右侧边栏显示文章分类列表
+ showTagList: false // 右侧边栏显示标签分类列表
+ },
+ socialLink: { // 社交链接,如不需要展示可以留空白,例如 weibo:''
+ weibo: 'https://weibo.com/tangly1024',
+ twitter: 'https://twitter.com/troy1024_1',
+ github: 'https://github.com/tangly1024',
+ telegram: 'https://t.me/tangly_1024'
+ },
+ comment: { // 评论插件,支持 gitalk, utterances, cusdis
+ provider: 'gitalk', // 不需要则留空白
+ gitalkConfig: {
+ repo: 'NotionNext', // The repository of store comments
+ owner: 'tangly1024',
+ admin: ['tangly1024'],
+ clientID: process.env.GITALK_ID || 'be7864a16b693e256f8f',
+ clientSecret: process.env.GITALK_SECRET || 'dbd0f6d9ceea8940f6ed20936b415274b8fe66a2',
+ distractionFreeMode: false
+ },
+ cusdisConfig: {
+ appId: '445ba48e-f751-487f-b22f-cdbe3310d28f', // data-app-id
+ host: 'https://cusdis.com', // data-host, change this if you're using self-hosted version
+ scriptSrc: 'https://cusdis.com/js/cusdis.es.js' // change this if you're using self-hosted version
+ },
+ utterancesConfig: {
+ repo: 'tangly1024/NotionNext'
+ },
+ gitter: '', // gitter聊天室
+ DaoVoiceId: '', // DaoVoice http://dashboard.daovoice.io/get-started
+ TidioId: '' // https://www.tidio.com/
+ }
+}
diff --git a/themes/index.js b/themes/index.js
new file mode 100644
index 00000000..7a6abb4b
--- /dev/null
+++ b/themes/index.js
@@ -0,0 +1 @@
+export * from './NEXT' // 切换主题