+
+
+ {BLOG.COMMENT_CUSDIS_APP_ID && (
+
+
)}
+ {BLOG.COMMENT_GITALK_CLIENT_ID && (
)}
- {BLOG.comment.provider === 'utterances' && (
-
-
- )}
- {BLOG.comment.provider === 'cusdis' && (<>
-
-
-
+ {BLOG.COMMENT_UTTERRANCES_REPO && (
+
- >)}
-
- )
+ )}
+
+
)
}
diff --git a/components/CommonHead.js b/components/CommonHead.js
index 784795a0..6488dbcb 100644
--- a/components/CommonHead.js
+++ b/components/CommonHead.js
@@ -2,32 +2,27 @@ import BLOG from '@/blog.config'
import Head from 'next/head'
const CommonHead = ({ meta }) => {
- let url = BLOG.path.length ? `${BLOG.link}/${BLOG.path}` : BLOG.link
+ let url = BLOG.PATH.length ? `${BLOG.LINK}/${BLOG.PATH}` : BLOG.LINK
if (meta) {
url = `${url}/${meta.slug}`
}
- const title = meta?.title || BLOG.title
- const description = meta?.description || BLOG.description
+ const title = meta?.title || BLOG.TITLE
+ const description = meta?.description || BLOG.DESCRIPTION
const type = meta?.type || 'website'
- const keywords = meta?.tags || BLOG.keywords
+ const keywords = meta?.tags || BLOG.KEYWORDS
return
{title}
-
+
- {BLOG.seo.googleSiteVerification && (
-
- )}
- {keywords && (
-
+ {BLOG.SEO_GOOGLE_SITE_VERIFICATION && (
+
)}
+
-
+
{
- {meta.type === 'article' && (
+ {meta?.type === 'article' && (
<>
-
+
>
)}
diff --git a/components/CommonScript.js b/components/CommonScript.js
index 45682806..c812f920 100644
--- a/components/CommonScript.js
+++ b/components/CommonScript.js
@@ -7,7 +7,7 @@ import BLOG from '@/blog.config'
*/
const CommonScript = () => {
return (<>
- {BLOG.comment?.DaoVoiceId && (<>
+ {BLOG.COMMENT_DAO_VOICE_ID && (<>
{/* DaoVoice 反馈 */}
>)}
{/* 代码统计 */}
- {BLOG.isProd && (<>
+ {/* ackee统计脚本 */}
+ {BLOG.ANALYTICS_ACKEE_TRACKER && (
+
+ )}
- {/* ackee统计脚本 */}
- {BLOG.analytics.provider === 'ackee' && (
-
- )}
- {/* 百度统计 */}
- {BLOG.analytics.baiduAnalytics && (
-
+ )}
+
+ {/* 站长统计 */}
+ {BLOG.ANALYTICS_CNZZ_ID && (
+
+ )}
+
+ {/* 谷歌统计 */}
+ {BLOG.ANALYTICS_GOOGLE_ID && (<>
+
+
- )}
-
- {/* 站长统计 */}
- {BLOG.analytics.cnzzAnalytics && (
-
- )}
-
- {/* 谷歌统计 */}
- {BLOG.analytics.provider === 'ga' && (<>
-
-
- >)}
+ }}
+ />
>)}
>)
}
diff --git a/components/Cusdis.js b/components/Cusdis.js
index cbf31042..a05f14ec 100644
--- a/components/Cusdis.js
+++ b/components/Cusdis.js
@@ -6,8 +6,7 @@ const Cusdis = ({ id, url, title }) => {
const anchor = document.getElementById('comments')
script.setAttribute(
'src',
- BLOG.comment.cusdisConfig.scriptSrc ||
- 'https://cusdis.com/js/cusdis.es.js'
+ BLOG.COMMENT_CUSDIS_SCRIPT_SRC
)
script.setAttribute('async', true)
script.setAttribute('defer', true)
@@ -20,12 +19,12 @@ const Cusdis = ({ id, url, title }) => {
)
}
diff --git a/components/Tabs.js b/components/Tabs.js
new file mode 100644
index 00000000..66012477
--- /dev/null
+++ b/components/Tabs.js
@@ -0,0 +1,53 @@
+import React, { useState } from 'react'
+
+/**
+ * Tabs切换标签
+ * @param {*} param0
+ * @returns
+ */
+const Tabs = ({ children }) => {
+ if (!children) {
+ return <>>
+ }
+
+ let count = children.length
+ children.forEach(e => {
+ if (!e) {
+ count--
+ }
+ })
+
+ if (count === 1) {
+ return
+ }
+
+ const [currentTab, setCurrentTab] = useState(0)
+
+ function tabClickHandle (i) {
+ setCurrentTab(i)
+ }
+
+ return
+
+ {children.map((item, index) => {
+ return - {
+ tabClickHandle(index)
+ }}>
+ {item?.key}
+
+ })}
+
+ {children.map((item, index) => {
+ return
+ })}
+
+}
+
+export default Tabs
diff --git a/components/Utterances.js b/components/Utterances.js
index 028dc072..39d3d826 100644
--- a/components/Utterances.js
+++ b/components/Utterances.js
@@ -11,9 +11,9 @@ import { useEffect } from 'react'
const Utterances = ({ issueTerm, layout }) => {
useEffect(() => {
const theme =
- BLOG.appearance === 'auto'
+ BLOG.APPEARANCE === 'auto'
? 'preferred-color-scheme'
- : BLOG.appearance === 'light'
+ : BLOG.APPEARANCE === 'light'
? 'github-light'
: 'github-dark'
const script = document.createElement('script')
@@ -21,7 +21,7 @@ const Utterances = ({ issueTerm, layout }) => {
script.setAttribute('src', 'https://utteranc.es/client.js')
script.setAttribute('crossorigin', 'anonymous')
script.setAttribute('async', true)
- script.setAttribute('repo', BLOG.comment.utterancesConfig.repo)
+ script.setAttribute('repo', BLOG.COMMENT_UTTERRANCES_REPO)
script.setAttribute('issue-term', issueTerm)
script.setAttribute('theme', theme)
anchor.appendChild(script)
@@ -29,16 +29,9 @@ const Utterances = ({ issueTerm, layout }) => {
anchor.innerHTML = ''
}
})
- return (
- <>
-
- >
- )
+ return
}
export default Utterances
diff --git a/lib/cjk.js b/lib/cjk.js
index b024d72b..478dd005 100644
--- a/lib/cjk.js
+++ b/lib/cjk.js
@@ -1,7 +1,7 @@
const BLOG = require('../blog.config')
module.exports = function () {
- switch (BLOG.lang.toLowerCase()) {
+ switch (BLOG.LANG.toLowerCase()) {
case 'zh-cn':
case 'zh-sg':
return 'SC'
diff --git a/lib/gtag.js b/lib/gtag.js
index a526fb7d..322ab7e6 100644
--- a/lib/gtag.js
+++ b/lib/gtag.js
@@ -1,9 +1,8 @@
import BLOG from '@/blog.config'
-export const GA_TRACKING_ID = BLOG.analytics.gaConfig.measurementId
// https://developers.google.com/analytics/devguides/collection/gtagjs/pages
export const pageview = url => {
- window.gtag('config', GA_TRACKING_ID, {
+ window.gtag('config', BLOG.ANALYTICS_GOOGLE_ID, {
page_path: url
})
}
diff --git a/lib/notion/getAllPosts.js b/lib/notion/getAllPosts.js
index 8cd43e34..d13ff5f2 100644
--- a/lib/notion/getAllPosts.js
+++ b/lib/notion/getAllPosts.js
@@ -60,7 +60,7 @@ export async function getAllPosts ({ notionPageData, from, includePage = false }
})
// Sort by date
- if (BLOG.sortByDate) {
+ if (BLOG.POSTS_SORT_BY === 'date') {
posts.sort((a, b) => {
const dateA = new Date(a?.date?.start_date || a.createdTime)
const dateB = new Date(b?.date?.start_date || b.createdTime)
diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js
index 74f95a7c..bb91a655 100644
--- a/lib/notion/getNotionData.js
+++ b/lib/notion/getNotionData.js
@@ -13,13 +13,13 @@ import { getAllTags } from './getAllTags'
* @param latestPostCount 截取最新文章数量
* @param tagsCount 截取标签数量
* @param includePage 是否包含PAGE类型
- * @returns { allPosts: '文章列表', latestPosts: ’最新文章, categories:‘分类列表’, postCount:'文章总数',tags:'标签列表' }
+ * @returns {}
* allPosts 所有博客
* categories 所有分类
* tags 所有标签
*/
export async function getGlobalNotionData ({
- pageId = BLOG.notionPageId,
+ pageId = BLOG.NOTION_PAGE_ID,
from,
latestPostCount = 5,
tagsCount = 16,
diff --git a/lib/notion/getPostBlocks.js b/lib/notion/getPostBlocks.js
index 2dbe8ce0..ecf42217 100644
--- a/lib/notion/getPostBlocks.js
+++ b/lib/notion/getPostBlocks.js
@@ -9,7 +9,7 @@ export async function getPostBlocks (id, from, slice) {
console.log('[请求缓存]:', `from:${from}`, `id:${id}`)
return filterPostBlocks(id, pageBlock, slice)
}
- const authToken = BLOG.notionAccessToken || null
+ const authToken = BLOG.NOTION_ACCESS_TOKEN || null
const api = new NotionAPI({ authToken })
try {
console.log('[请求API]:', `from:${from}`, `id:${id}`)
@@ -57,7 +57,7 @@ function filterPostBlocks (id, pageBlock, slice) {
}
// 去掉不用的字段
- if (id === BLOG.notionPageId) {
+ if (id === BLOG.NOTION_PAGE_ID) {
return clonePageBlock
}
return clonePageBlock
diff --git a/lib/rss.js b/lib/rss.js
index 62297707..f02a5a0b 100644
--- a/lib/rss.js
+++ b/lib/rss.js
@@ -4,25 +4,25 @@ import BLOG from '@/blog.config'
export function generateRss (posts) {
const year = new Date().getFullYear()
const feed = new Feed({
- title: BLOG.title,
- description: BLOG.description,
- id: `${BLOG.link}/${BLOG.path}`,
- link: `${BLOG.link}/${BLOG.path}`,
- language: BLOG.lang,
- favicon: `${BLOG.link}/favicon.png`,
- copyright: `All rights reserved ${year}, ${BLOG.author}`,
- author: {
- name: BLOG.author,
- email: BLOG.email,
- link: BLOG.link
+ TITLE: BLOG.TITLE,
+ DESCRIPTION: BLOG.DESCRIPTION,
+ id: `${BLOG.LINK}/${BLOG.PATH}`,
+ LINK: `${BLOG.LINK}/${BLOG.PATH}`,
+ language: BLOG.LANG,
+ favicon: `${BLOG.LINK}/favicon.png`,
+ copyright: `All rights reserved ${year}, ${BLOG.AUTHOR}`,
+ AUTHOR: {
+ name: BLOG.AUTHOR,
+ email: BLOG.CONTACT_EMAIL,
+ link: BLOG.LINK
}
})
posts.forEach(post => {
feed.addItem({
- title: post.title,
- id: `${BLOG.link}/article/${post.slug}`,
- link: `${BLOG.link}/article/${post.slug}`,
- description: post.summary,
+ TITLE: post.title,
+ id: `${BLOG.LINK}/article/${post.slug}`,
+ LINK: `${BLOG.LINK}/article/${post.slug}`,
+ DESCRIPTION: post.summary,
date: new Date(post?.date?.start_date || post.createdTime)
})
})
diff --git a/next-sitemap.config.js b/next-sitemap.config.js
index eb913eb9..a094e809 100644
--- a/next-sitemap.config.js
+++ b/next-sitemap.config.js
@@ -1,7 +1,7 @@
const BLOG = require('./blog.config')
module.exports = {
- siteUrl: BLOG.link,
+ siteUrl: BLOG.LINK,
changefreq: 'daily',
priority: 0.7,
generateRobotsTxt: true,
diff --git a/pages/_app.js b/pages/_app.js
index 36615acb..43aeb3f2 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -26,15 +26,10 @@ const GoogleAdsense = dynamic(() => import('@/components/GoogleAdsense'), { ssr:
const MyApp = ({ Component, pageProps }) => {
return (
- {BLOG.isProd && BLOG?.analytics?.provider === 'ackee' && (
-
- )}
- {BLOG.isProd && BLOG?.analytics?.provider === 'ga' && }
- {BLOG.analytics.busuanzi && }
- {BLOG.googleAdsenseId && }
+ {BLOG.ANALYTICS_ACKEE_TRACKER && }
+ {BLOG.ANALYTICS_GOOGLE_ID && }
+ {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && }
+ {BLOG.ADSENSE_GOOGLE_ID && }
)
diff --git a/pages/_document.js b/pages/_document.js
index aac649e5..5a62d753 100644
--- a/pages/_document.js
+++ b/pages/_document.js
@@ -11,14 +11,14 @@ class MyDocument extends Document {
render () {
return (
-
+
-
+
diff --git a/pages/article/[slug].js b/pages/article/[slug].js
index 60ab8f31..7903994f 100644
--- a/pages/article/[slug].js
+++ b/pages/article/[slug].js
@@ -13,7 +13,7 @@ const Slug = (props) => {
if (!props.post) {
return
}
- return
+ return
}
export async function getStaticPaths () {
@@ -24,8 +24,8 @@ export async function getStaticPaths () {
}
}
- const from = '[slug-paths'
- const { allPosts } = await getGlobalNotionData({ from, includePage: false })
+ const from = 'slug-paths'
+ const { allPosts } = await getGlobalNotionData({ from, includePage: true })
return {
paths: allPosts.map(row => ({ params: { slug: row.slug } })),
fallback: true
@@ -35,7 +35,7 @@ export async function getStaticPaths () {
export async function getStaticProps ({ params: { slug } }) {
const from = `slug-props-${slug}`
const { allPosts, categories, tags, postCount, latestPosts } =
- await getGlobalNotionData({ from, includePage: false })
+ await getGlobalNotionData({ from, includePage: true })
const post = allPosts.find(p => p.slug === slug)
@@ -45,10 +45,10 @@ export async function getStaticProps ({ params: { 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 posts = allPosts.filter(post => post?.type?.[0] === 'Post')
+ const index = posts.indexOf(post)
+ const prev = posts.slice(index - 1, index)[0] ?? posts.slice(-1)[0]
+ const next = posts.slice(index + 1, index + 2)[0] ?? posts[0]
const recommendPosts = getRecommendPost(post, allPosts)
@@ -80,7 +80,7 @@ function getRecommendPost (post, allPosts, count = 5) {
if (post.tags && post.tags.length) {
const currentTag = post.tags[0]
filteredPosts = filteredPosts.filter(
- p => p && p.tags && p.tags.includes(currentTag) && p.slug !== post.slug
+ p => p && p.tags && p.tags.includes(currentTag) && p.slug !== post.slug && p.type === 'post'
)
}
shuffleSort(filteredPosts)
diff --git a/pages/feed.js b/pages/feed.js
index 98811da9..3e3ebffa 100644
--- a/pages/feed.js
+++ b/pages/feed.js
@@ -1,13 +1,10 @@
-import { getAllPosts } from '@/lib/notion'
import { generateRss } from '@/lib/rss'
+import { getGlobalNotionData } from '@/lib/notion/getNotionData'
export async function getServerSideProps ({ res }) {
res.setHeader('Content-Type', 'text/xml')
- let posts = await getAllPosts({ from: 'feed' })
- posts = posts
- .filter(post => post.status[0] === 'Published' && post.type[0] === 'Post')
- .slice(0, 10)
- const xmlFeed = generateRss(posts)
+ const globalNotionData = await getGlobalNotionData({ from: 'rss' })
+ const xmlFeed = generateRss(globalNotionData?.allPosts?.slice(0, 10) || [])
res.write(xmlFeed)
res.end()
return {
diff --git a/pages/index.js b/pages/index.js
index 6fbb1073..de821436 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -11,24 +11,24 @@ export async function getStaticProps () {
const from = 'index'
const { allPosts, latestPosts, categories, tags, postCount } = await getGlobalNotionData({ from })
const meta = {
- title: `${BLOG.title}`,
- description: BLOG.description,
+ title: `${BLOG.TITLE}`,
+ description: BLOG.DESCRIPTION,
type: 'website'
}
// 处理分页
const page = 1
let postsToShow
- if (BLOG.postListStyle !== 'page') {
+ if (BLOG.POST_LIST_STYLE !== 'page') {
postsToShow = Array.from(allPosts)
} else {
postsToShow = allPosts.slice(
- BLOG.postsPerPage * (page - 1),
- BLOG.postsPerPage * page
+ BLOG.POSTS_PER_PAGE * (page - 1),
+ BLOG.POSTS_PER_PAGE * page
)
for (const i in postsToShow) {
const post = postsToShow[i]
- const blockMap = await getPostBlocks(post.id, 'slug', BLOG.home.previewLines)
+ const blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES)
if (blockMap) {
post.blockMap = blockMap
}
diff --git a/pages/page/[page].js b/pages/page/[page].js
index 5ed48e0f..2c5cadf0 100644
--- a/pages/page/[page].js
+++ b/pages/page/[page].js
@@ -14,7 +14,7 @@ const Page = (props) => {
export async function getStaticPaths () {
const from = 'page-paths'
const { postCount } = await getGlobalNotionData({ from })
- const totalPages = Math.ceil(postCount / BLOG.postsPerPage)
+ const totalPages = Math.ceil(postCount / BLOG.POSTS_PER_PAGE)
return {
// remove first page, we 're not gonna handle that.
paths: Array.from({ length: totalPages - 1 }, (_, i) => ({ params: { page: '' + (i + 2) } })),
@@ -32,19 +32,20 @@ export async function getStaticProps ({ params: { page } }) {
postCount
} = await getGlobalNotionData({ from })
const meta = {
- title: `${page} | Page | ${BLOG.title}`,
- description: BLOG.description,
+ title: `${page} | Page | ${BLOG.TITLE}`,
+ description: BLOG.DESCRIPTION,
type: 'website'
}
+
// 处理分页
const postsToShow = allPosts.slice(
- BLOG.postsPerPage * (page - 1),
- BLOG.postsPerPage * page
+ BLOG.POSTS_PER_PAGE * (page - 1),
+ BLOG.POSTS_PER_PAGE * page
)
for (const i in postsToShow) {
const post = postsToShow[i]
- const blockMap = await getPostBlocks(post.id, 'slug', BLOG.home.previewLines)
+ const blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES)
if (blockMap) {
post.blockMap = blockMap
}
diff --git a/tailwind.config.js b/tailwind.config.js
index 03b30c8e..c8254a31 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -9,7 +9,7 @@ const fontSerifCJK = !CJK()
: [`"Noto Serif CJK ${CJK()}"`, `"Noto Serif ${CJK()}"`]
module.exports = {
purge: ['./pages/**/*.js', './components/**/*.js', './layouts/**/*.js', './themes/**/*.js'],
- darkMode: BLOG.appearance === 'class' ? 'media' : 'class', // or 'media' or 'class'
+ darkMode: BLOG.APPEARANCE === 'class' ? 'media' : 'class', // or 'media' or 'class'
theme: {
fontFamily: {
sans: ['"IBM Plex Sans"', ...fontFamily.sans, ...fontSansCJK],
@@ -26,10 +26,10 @@ module.exports = {
extend: {
colors: {
day: {
- DEFAULT: BLOG.lightBackground || '#ffffff'
+ DEFAULT: BLOG.BACKGROUND_LIGHT || '#ffffff'
},
night: {
- DEFAULT: BLOG.darkBackground || '#111827'
+ DEFAULT: BLOG.BACKGROUND_DARK || '#111827'
}
}
}
diff --git a/themes/Empty/Layout404.js b/themes/Empty/Layout404.js
new file mode 100644
index 00000000..cd28a607
--- /dev/null
+++ b/themes/Empty/Layout404.js
@@ -0,0 +1,6 @@
+
+export const Layout404 = () => {
+ return
+ 404 Not found.
+
+}
diff --git a/themes/Empty/LayoutArchive.js b/themes/Empty/LayoutArchive.js
new file mode 100644
index 00000000..e46502fc
--- /dev/null
+++ b/themes/Empty/LayoutArchive.js
@@ -0,0 +1,5 @@
+export const LayoutArchive = ({ posts, tags, categories, postCount }) => {
+ return
+ Archive Page
+
+}
diff --git a/themes/Empty/LayoutBase.js b/themes/Empty/LayoutBase.js
new file mode 100644
index 00000000..d302c580
--- /dev/null
+++ b/themes/Empty/LayoutBase.js
@@ -0,0 +1,40 @@
+import CommonHead from '@/components/CommonHead'
+
+/**
+ * 基础布局 采用左右两侧布局,移动端使用顶部导航栏
+ * @param children
+ * @param layout
+ * @param tags
+ * @param meta
+ * @param post
+ * @param currentSearch
+ * @param currentCategory
+ * @param currentTag
+ * @param categories
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const LayoutBase = ({
+ children,
+ headerSlot,
+ tags,
+ meta,
+ post,
+ postCount,
+ sideBarSlot,
+ floatSlot,
+ rightAreaSlot,
+ currentSearch,
+ currentCategory,
+ currentTag,
+ categories
+}) => {
+ return (<>
+
+
+ {children}
+
+ >)
+}
+
+export default LayoutBase
diff --git a/themes/Empty/LayoutCategory.js b/themes/Empty/LayoutCategory.js
new file mode 100644
index 00000000..60e0d11a
--- /dev/null
+++ b/themes/Empty/LayoutCategory.js
@@ -0,0 +1,5 @@
+export const LayoutCategory = ({ tags, posts, category, categories, latestPosts, postCount }) => {
+ return
+ Category - {category}
+
+}
diff --git a/themes/Empty/LayoutCategoryIndex.js b/themes/Empty/LayoutCategoryIndex.js
new file mode 100644
index 00000000..467bde1c
--- /dev/null
+++ b/themes/Empty/LayoutCategoryIndex.js
@@ -0,0 +1,11 @@
+export const LayoutCategoryIndex = ({
+ tags,
+ allPosts,
+ categories,
+ postCount,
+ latestPosts
+}) => {
+ return
+ CategoryIndex
+
+}
diff --git a/themes/Empty/LayoutIndex.js b/themes/Empty/LayoutIndex.js
new file mode 100644
index 00000000..986951c3
--- /dev/null
+++ b/themes/Empty/LayoutIndex.js
@@ -0,0 +1,3 @@
+export const LayoutIndex = ({ posts, tags, meta, categories, postCount, latestPosts }) => {
+ return
Index
+}
diff --git a/themes/Empty/LayoutPage.js b/themes/Empty/LayoutPage.js
new file mode 100644
index 00000000..c025ff3c
--- /dev/null
+++ b/themes/Empty/LayoutPage.js
@@ -0,0 +1,5 @@
+export const LayoutPage = ({ page, posts, tags, meta, categories, postCount, latestPosts }) => {
+ return
+ Page - {page}
+
+}
diff --git a/themes/Empty/LayoutSearch.js b/themes/Empty/LayoutSearch.js
new file mode 100644
index 00000000..76e4867c
--- /dev/null
+++ b/themes/Empty/LayoutSearch.js
@@ -0,0 +1,34 @@
+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
+ }
+
+ console.log(filteredPosts)
+
+ return
+ Search {searchKey}
+
+}
+
+function getSearchKey () {
+ const router = useRouter()
+ if (router.query && router.query.s) {
+ return router.query.s
+ }
+ return null
+}
diff --git a/themes/Empty/LayoutSlug.js b/themes/Empty/LayoutSlug.js
new file mode 100644
index 00000000..9335af67
--- /dev/null
+++ b/themes/Empty/LayoutSlug.js
@@ -0,0 +1,21 @@
+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'
+
+export const LayoutSlug = ({
+ post,
+ tags,
+ prev,
+ next,
+ recommendPosts,
+ categories,
+ postCount,
+ latestPosts
+}) => {
+ return
+ Slug
+
+}
diff --git a/themes/Empty/LayoutTag.js b/themes/Empty/LayoutTag.js
new file mode 100644
index 00000000..cae36f38
--- /dev/null
+++ b/themes/Empty/LayoutTag.js
@@ -0,0 +1,5 @@
+export const LayoutTag = ({ tags, posts, tag, categories, postCount, latestPosts }) => {
+ return
+ Tag - {tag}
+
+}
diff --git a/themes/Empty/LayoutTagIndex.js b/themes/Empty/LayoutTagIndex.js
new file mode 100644
index 00000000..deb76f8e
--- /dev/null
+++ b/themes/Empty/LayoutTagIndex.js
@@ -0,0 +1,5 @@
+export const LayoutTagIndex = ({ tags, categories, postCount, latestPosts }) => {
+ return
+ TagIndex
+
+}
diff --git a/themes/Empty/config_empty.js b/themes/Empty/config_empty.js
new file mode 100644
index 00000000..e69de29b
diff --git a/themes/Empty/index.js b/themes/Empty/index.js
new file mode 100644
index 00000000..aabed077
--- /dev/null
+++ b/themes/Empty/index.js
@@ -0,0 +1,10 @@
+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'
diff --git a/themes/Fukasawa/Layout404.js b/themes/Fukasawa/Layout404.js
new file mode 100644
index 00000000..bb21c100
--- /dev/null
+++ b/themes/Fukasawa/Layout404.js
@@ -0,0 +1,5 @@
+import LayoutBase from './LayoutBase'
+
+export const Layout404 = (props) => {
+ return
404
+}
diff --git a/themes/Fukasawa/LayoutArchive.js b/themes/Fukasawa/LayoutArchive.js
new file mode 100644
index 00000000..9b32f7af
--- /dev/null
+++ b/themes/Fukasawa/LayoutArchive.js
@@ -0,0 +1,61 @@
+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)
+
+ // 时间排序
+ 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/themes/Fukasawa/LayoutBase.js b/themes/Fukasawa/LayoutBase.js
new file mode 100644
index 00000000..1d3f3a57
--- /dev/null
+++ b/themes/Fukasawa/LayoutBase.js
@@ -0,0 +1,45 @@
+import CommonHead from '@/components/CommonHead'
+import TopNav from './components/TopNav'
+import AsideLeft from './components/AsideLeft'
+
+/**
+ * 基础布局 采用左右两侧布局,移动端使用顶部导航栏
+ * @param children
+ * @param layout
+ * @param tags
+ * @param meta
+ * @param post
+ * @param currentSearch
+ * @param currentCategory
+ * @param currentTag
+ * @param categories
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const LayoutBase = (props) => {
+ const {
+ children,
+ headerSlot,
+ tags,
+ meta,
+ currentCategory,
+ currentTag,
+ categories
+ } = props
+ return (<>
+
+
+
+
+
+
+
{headerSlot}
+
{children}
+
+
+
+
+ >)
+}
+
+export default LayoutBase
diff --git a/themes/Fukasawa/LayoutCategory.js b/themes/Fukasawa/LayoutCategory.js
new file mode 100644
index 00000000..03dae870
--- /dev/null
+++ b/themes/Fukasawa/LayoutCategory.js
@@ -0,0 +1,8 @@
+import BlogListPage from './components/BlogListPage'
+import LayoutBase from './LayoutBase'
+
+export const LayoutCategory = (props) => {
+ return
+
+
+}
diff --git a/themes/Fukasawa/LayoutCategoryIndex.js b/themes/Fukasawa/LayoutCategoryIndex.js
new file mode 100644
index 00000000..0def1581
--- /dev/null
+++ b/themes/Fukasawa/LayoutCategoryIndex.js
@@ -0,0 +1,32 @@
+import BLOG from '@/blog.config'
+import { useGlobal } from '@/lib/global'
+import { faFolder, faTh } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import Link from 'next/link'
+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
+
+
+ {locale.COMMON.CATEGORY}:
+
+
+ {Object.keys(categories).map(category => {
+ return
+
+ {category}({categories[category]})
+
+
+ })}
+
+
+}
diff --git a/themes/Fukasawa/LayoutIndex.js b/themes/Fukasawa/LayoutIndex.js
new file mode 100644
index 00000000..5a1209c5
--- /dev/null
+++ b/themes/Fukasawa/LayoutIndex.js
@@ -0,0 +1,10 @@
+import BlogListPage from './components/BlogListPage'
+import LayoutBase from './LayoutBase'
+
+export const LayoutIndex = (props) => {
+ return
+
+
+
+
+}
diff --git a/themes/Fukasawa/LayoutPage.js b/themes/Fukasawa/LayoutPage.js
new file mode 100644
index 00000000..a3c39788
--- /dev/null
+++ b/themes/Fukasawa/LayoutPage.js
@@ -0,0 +1,10 @@
+import BlogListPage from './components/BlogListPage'
+import LayoutBase from './LayoutBase'
+
+export const LayoutPage = (props) => {
+ return
+
+
+
+
+}
diff --git a/themes/Fukasawa/LayoutSearch.js b/themes/Fukasawa/LayoutSearch.js
new file mode 100644
index 00000000..1d77bf69
--- /dev/null
+++ b/themes/Fukasawa/LayoutSearch.js
@@ -0,0 +1,30 @@
+import { useRouter } from 'next/router'
+import LayoutBase from './LayoutBase'
+
+export const LayoutSearch = (props) => {
+ let filteredPosts
+ const searchKey = getSearchKey()
+ if (searchKey) {
+ filteredPosts = props.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 = props.posts
+ }
+
+ console.log(filteredPosts)
+
+ return
+ Search {searchKey}
+
+}
+
+function getSearchKey () {
+ const router = useRouter()
+ if (router.query && router.query.s) {
+ return router.query.s
+ }
+ return null
+}
diff --git a/themes/Fukasawa/LayoutSlug.js b/themes/Fukasawa/LayoutSlug.js
new file mode 100644
index 00000000..afa8f278
--- /dev/null
+++ b/themes/Fukasawa/LayoutSlug.js
@@ -0,0 +1,25 @@
+import BLOG from '@/blog.config'
+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 ArticleDetail from './components/ArticleDetail'
+import LayoutBase from './LayoutBase'
+
+export const LayoutSlug = (props) => {
+ const { post } = props
+ const meta = {
+ title: `${post.title} | ${BLOG.TITLE}`,
+ description: post.summary,
+ type: 'article',
+ tags: post.tags
+ }
+
+ return (
+
+
+
+ )
+}
diff --git a/themes/Fukasawa/LayoutTag.js b/themes/Fukasawa/LayoutTag.js
new file mode 100644
index 00000000..8593783e
--- /dev/null
+++ b/themes/Fukasawa/LayoutTag.js
@@ -0,0 +1,8 @@
+import BlogListPage from './components/BlogListPage'
+import LayoutBase from './LayoutBase'
+
+export const LayoutTag = (props) => {
+ return
+
+
+}
diff --git a/themes/Fukasawa/LayoutTagIndex.js b/themes/Fukasawa/LayoutTagIndex.js
new file mode 100644
index 00000000..1d93708d
--- /dev/null
+++ b/themes/Fukasawa/LayoutTagIndex.js
@@ -0,0 +1,27 @@
+import BLOG from '@/blog.config'
+import { useGlobal } from '@/lib/global'
+import { faTag } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import TagItem from './components/TagItem'
+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
+
+
{locale.COMMON.TAGS}:
+
+
+
+}
diff --git a/themes/Fukasawa/components/ArticleAround.js b/themes/Fukasawa/components/ArticleAround.js
new file mode 100644
index 00000000..7f42e575
--- /dev/null
+++ b/themes/Fukasawa/components/ArticleAround.js
@@ -0,0 +1,26 @@
+import Link from 'next/link'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faAngleDoubleLeft, faAngleDoubleRight } from '@fortawesome/free-solid-svg-icons'
+
+/**
+ * 上一篇,下一篇文章
+ * @param {prev,next} param0
+ * @returns
+ */
+export default function ArticleAround ({ prev, next }) {
+ if (!prev || !next) {
+ return <>>
+ }
+ return
+}
diff --git a/themes/Fukasawa/components/ArticleDetail.js b/themes/Fukasawa/components/ArticleDetail.js
new file mode 100644
index 00000000..cdc46ff7
--- /dev/null
+++ b/themes/Fukasawa/components/ArticleDetail.js
@@ -0,0 +1,156 @@
+import Comment from '@/components/Comment'
+import formatDate from '@/lib/formatDate'
+import { useGlobal } from '@/lib/global'
+import { faEye, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import mediumZoom from 'medium-zoom'
+import Link from 'next/link'
+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 { useEffect, useRef } from 'react'
+import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
+import ArticleAround from './ArticleAround'
+
+/**
+ *
+ * @param {*} param0
+ * @returns
+ */
+export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
+ const { locale } = useGlobal()
+ const date = formatDate(post?.date?.start_date || post.createdTime, locale.LOCALE)
+
+ const zoom = typeof window !== 'undefined' && mediumZoom({
+ container: '.notion-viewport',
+ background: 'rgba(0, 0, 0, 0.2)',
+ margin: getMediumZoomMargin()
+ })
+ const zoomRef = useRef(zoom ? zoom.clone() : null)
+
+ useEffect(() => {
+ // 将所有container下的所有图片添加medium-zoom
+ const container = document.getElementById('container')
+ const imgList = container.getElementsByTagName('img')
+ if (imgList && zoomRef.current) {
+ for (let i = 0; i < imgList.length; i++) {
+ (zoomRef.current).attach(imgList[i])
+ }
+ }
+ })
+
+ return (
+ {post.type && !post.type.includes('Page') && post?.page_cover && (
+
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+

+
+ )}
+
+
+
+
+ {/* 文章Title */}
+
+ {post.title}
+
+
+
+
+
+
+ {/* Notion文章主体 */}
+
+ {post.blockMap && (
+
+ )}
+
+
+
+
+
+
+
+
+ {/* 评论互动 */}
+
+ )
+}
+
+const mapPageUrl = id => {
+ return 'https://www.notion.so/' + id.replace(/-/g, '')
+}
+
+function getMediumZoomMargin () {
+ const width = window.innerWidth
+
+ if (width < 500) {
+ return 8
+ } else if (width < 800) {
+ return 20
+ } else if (width < 1280) {
+ return 30
+ } else if (width < 1600) {
+ return 40
+ } else if (width < 1920) {
+ return 48
+ } else {
+ return 72
+ }
+}
diff --git a/themes/Fukasawa/components/AsideLeft.js b/themes/Fukasawa/components/AsideLeft.js
new file mode 100644
index 00000000..79aaed1c
--- /dev/null
+++ b/themes/Fukasawa/components/AsideLeft.js
@@ -0,0 +1,47 @@
+import BLOG from '@/blog.config'
+import Logo from './Logo'
+import GroupCategory from './GroupCategory'
+import GroupMenu from './GroupMenu'
+import GroupTag from './GroupTag'
+import SearchInput from './SearchInput'
+import SiteInfo from './SiteInfo'
+
+function AsideLeft ({ tags, currentTag, categories, currentCategory }) {
+ return
+
+
+
+
+
+
+
+
+
+ { BLOG.DESCRIPTION }
+
+
+
+
+
+
+
+
+
+}
+
+export default AsideLeft
diff --git a/themes/Fukasawa/components/BlogCard.js b/themes/Fukasawa/components/BlogCard.js
new file mode 100644
index 00000000..e153e414
--- /dev/null
+++ b/themes/Fukasawa/components/BlogCard.js
@@ -0,0 +1,39 @@
+import BLOG from '@/blog.config'
+import Image from 'next/image'
+import Link from 'next/link'
+import React from 'react'
+import CONFIG_FUKA from '../config_fuka'
+import Card from './Card'
+
+const BlogCard = ({ post, showSummary }) => {
+ const showPreview = CONFIG_FUKA.POST_LIST_PREVIEW && post.blockMap
+ return (
+
+
+
+
+
+
+ {post.title}
+
+
+
+ {(!showPreview || showSummary) &&
+ {post.summary}
+
}
+
+
+ {CONFIG_FUKA.POST_LIST_COVER && post?.page_cover && (
+
+
+
+
+
+ )}
+
+
+
+ )
+}
+
+export default BlogCard
diff --git a/themes/Fukasawa/components/BlogListEmpty.js b/themes/Fukasawa/components/BlogListEmpty.js
new file mode 100644
index 00000000..41b42e73
--- /dev/null
+++ b/themes/Fukasawa/components/BlogListEmpty.js
@@ -0,0 +1,12 @@
+
+/**
+ * 空白博客 列表
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const BlogListEmpty = ({ currentSearch }) => {
+ return
+
没有找到文章 {(currentSearch &&
{currentSearch}
)}
+
+}
+export default BlogListEmpty
diff --git a/themes/Fukasawa/components/BlogListPage.js b/themes/Fukasawa/components/BlogListPage.js
new file mode 100644
index 00000000..4c6fc823
--- /dev/null
+++ b/themes/Fukasawa/components/BlogListPage.js
@@ -0,0 +1,55 @@
+import BLOG from '@/blog.config'
+import { useEffect, useState } from 'react'
+import BlogCard from './BlogCard'
+import BlogPostListEmpty from './BlogListEmpty'
+import PaginationSimple from './PaginationSimple'
+
+/**
+ * 文章列表分页表格
+ * @param page 当前页
+ * @param posts 所有文章
+ * @param tags 所有标签
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const BlogListPage = ({ page = 1, posts = [], postCount }) => {
+ const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE)
+ const showNext = page < totalPage && posts.length < postCount
+ const [colCount, changeCol] = useState(3)
+
+ function updateCol () {
+ if (window.outerWidth > 1200) {
+ changeCol(3)
+ } else {
+ changeCol(1)
+ }
+ }
+
+ useEffect(() => {
+ updateCol()
+ window.addEventListener('resize', updateCol)
+ return () => {
+ window.removeEventListener('resize', updateCol)
+ }
+ })
+
+ if (!posts || posts.length === 0) {
+ return
+ } else {
+ return (
+
+ {/* 文章列表 */}
+
+ {posts.map(post => (
+
+
+
+ ))}
+
+
+
+ )
+ }
+}
+
+export default BlogListPage
diff --git a/themes/Fukasawa/components/BlogPostArchive.js b/themes/Fukasawa/components/BlogPostArchive.js
new file mode 100644
index 00000000..02b3a1bc
--- /dev/null
+++ b/themes/Fukasawa/components/BlogPostArchive.js
@@ -0,0 +1,32 @@
+import React from 'react'
+import Link from 'next/link'
+import BLOG from '@/blog.config'
+/**
+ * 博客归档
+ * @param posts 所有文章
+ * @param archiveTitle 归档标题
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
+ if (!posts || posts.length === 0) {
+ return <>>
+ } else {
+ return
+
{archiveTitle}
+
+ {posts.map(post => (
+ -
+
{post.date.start_date}
+
+
{post.title}
+
+
+
+ ))}
+
+
+ }
+}
+
+export default BlogArchiveItem
diff --git a/themes/Fukasawa/components/Card.js b/themes/Fukasawa/components/Card.js
new file mode 100644
index 00000000..890aadf9
--- /dev/null
+++ b/themes/Fukasawa/components/Card.js
@@ -0,0 +1,9 @@
+const Card = ({ children, headerSlot, className }) => {
+ return
+ <>{headerSlot}>
+
+
+}
+export default Card
diff --git a/themes/Fukasawa/components/Collapse.js b/themes/Fukasawa/components/Collapse.js
new file mode 100644
index 00000000..7607b732
--- /dev/null
+++ b/themes/Fukasawa/components/Collapse.js
@@ -0,0 +1,38 @@
+import React, { useEffect, useRef } from 'react'
+
+const Collapse = props => {
+ const collapseRef = useRef(null)
+ const collapseSection = element => {
+ const sectionHeight = element.scrollHeight
+ requestAnimationFrame(function () {
+ element.style.height = sectionHeight + 'px'
+ requestAnimationFrame(function () {
+ element.style.height = 0 + 'px'
+ })
+ })
+ }
+ const expandSection = element => {
+ const sectionHeight = element.scrollHeight
+ element.style.height = sectionHeight + 'px'
+ const clearTime = setTimeout(() => {
+ element.style.height = 'auto'
+ }, 400)
+ clearTimeout(clearTime)
+ }
+ useEffect(() => {
+ const element = collapseRef.current
+ if (props.isOpen) {
+ expandSection(element)
+ } else {
+ collapseSection(element)
+ }
+ }, [props.isOpen])
+ return (
+
+ {props.children}
+
+ )
+}
+Collapse.defaultProps = { isOpen: false }
+
+export default Collapse
diff --git a/themes/Fukasawa/components/GroupCategory.js b/themes/Fukasawa/components/GroupCategory.js
new file mode 100644
index 00000000..8e17fd5e
--- /dev/null
+++ b/themes/Fukasawa/components/GroupCategory.js
@@ -0,0 +1,28 @@
+import { faFolder, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import Link from 'next/link'
+import React from 'react'
+
+function GroupCategory ({ currentCategory, categories }) {
+ if (!categories) {
+ return <>>
+ }
+
+ return <>
+
+ >
+}
+
+export default GroupCategory
diff --git a/themes/Fukasawa/components/GroupMenu.js b/themes/Fukasawa/components/GroupMenu.js
new file mode 100644
index 00000000..4b97583d
--- /dev/null
+++ b/themes/Fukasawa/components/GroupMenu.js
@@ -0,0 +1,38 @@
+import React from 'react'
+import Link from 'next/link'
+import { useRouter } from 'next/router'
+import { useGlobal } from '@/lib/global'
+import CONFIG_FUKA from '../config_fuka'
+
+function GroupMenu () {
+ const { locale } = useGlobal()
+ const router = useRouter()
+
+ const links = [
+ { id: 0, name: locale.NAV.INDEX, to: '/' || '/', show: true },
+ { id: 1, name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_FUKA.MENU_CATEGORY },
+ { id: 2, name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_FUKA.MENU_TAG },
+ { id: 3, name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG_FUKA.MENU_ARCHIVE },
+ { id: 4, name: locale.NAV.ABOUT, to: '/about', show: CONFIG_FUKA.MENU_ABOUT }
+ ]
+ return
+}
+
+export default GroupMenu
diff --git a/themes/Fukasawa/components/GroupTag.js b/themes/Fukasawa/components/GroupTag.js
new file mode 100644
index 00000000..16bf01a3
--- /dev/null
+++ b/themes/Fukasawa/components/GroupTag.js
@@ -0,0 +1,24 @@
+import TagItemMini from './TagItemMini'
+
+/**
+ * 标签组
+ * @param tags
+ * @param currentTag
+ * @returns {JSX.Element}
+ * @constructor
+ */
+function GroupTag ({ tags, currentTag }) {
+ if (!tags) return <>>
+ return (
+
+ {
+ tags.map(tag => {
+ const selected = tag.name === currentTag
+ return
+ })
+ }
+
+ )
+}
+
+export default GroupTag
diff --git a/themes/Fukasawa/components/Logo.js b/themes/Fukasawa/components/Logo.js
new file mode 100644
index 00000000..c1fa0451
--- /dev/null
+++ b/themes/Fukasawa/components/Logo.js
@@ -0,0 +1,12 @@
+import BLOG from '@/blog.config'
+import Link from 'next/link'
+
+function Logo () {
+ return
+}
+
+export default Logo
diff --git a/themes/Fukasawa/components/PaginationSimple.js b/themes/Fukasawa/components/PaginationSimple.js
new file mode 100644
index 00000000..5eb30af8
--- /dev/null
+++ b/themes/Fukasawa/components/PaginationSimple.js
@@ -0,0 +1,42 @@
+import BLOG from '@/blog.config'
+import Link from 'next/link'
+import { useRouter } from 'next/router'
+import { useGlobal } from '@/lib/global'
+
+/**
+ * 简易翻页插件
+ * @param page 当前页码
+ * @param showNext 是否有下一页
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const PaginationSimple = ({ page, showNext }) => {
+ const { locale } = useGlobal()
+ const router = useRouter()
+ const currentPage = +page
+ return (
+
+ )
+}
+
+export default PaginationSimple
diff --git a/themes/Fukasawa/components/SearchInput.js b/themes/Fukasawa/components/SearchInput.js
new file mode 100644
index 00000000..a91cd46a
--- /dev/null
+++ b/themes/Fukasawa/components/SearchInput.js
@@ -0,0 +1,68 @@
+import { useRouter } from 'next/router'
+import { useImperativeHandle, useRef, useState } from 'react'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons'
+
+const SearchInput = ({ currentTag, currentSearch, cRef }) => {
+ const [searchKey, setSearchKey] = useState(currentSearch || '')
+ const [onLoading, setLoadingState] = useState(false)
+ const router = useRouter()
+ const searchInputRef = useRef()
+ useImperativeHandle(cRef, () => {
+ return {
+ focus: () => {
+ searchInputRef?.current?.focus()
+ }
+ }
+ })
+ const handleSearch = (key) => {
+ if (key && key !== '') {
+ setLoadingState(true)
+ router.push({ pathname: '/search', query: { s: key } }).then(r => {
+ setLoadingState(false)
+ })
+ } else {
+ router.push({ pathname: '/' }).then(r => {
+ })
+ }
+ }
+ const handleKeyUp = (e) => {
+ if (e.keyCode === 13) { // 回车
+ handleSearch(searchInputRef.current.value)
+ } else if (e.keyCode === 27) { // ESC
+ cleanSearch()
+ }
+ }
+ const cleanSearch = () => {
+ searchInputRef.current.value = ''
+ setSearchKey('')
+ }
+
+ const updateSearchKey = (val) => {
+ setSearchKey(val)
+ }
+
+ return
+
updateSearchKey(e.target.value)}
+ defaultValue={searchKey}
+ />
+
+
{ handleSearch(searchKey) }}>
+
+
+
+ {(searchKey && searchKey.length &&
+
+
+
+ )}
+
+}
+
+export default SearchInput
diff --git a/themes/Fukasawa/components/SiteInfo.js b/themes/Fukasawa/components/SiteInfo.js
new file mode 100644
index 00000000..9b4990e2
--- /dev/null
+++ b/themes/Fukasawa/components/SiteInfo.js
@@ -0,0 +1,26 @@
+import BLOG from '@/blog.config'
+import { faEye, faShieldAlt, faUsers } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+
+function SiteInfo ({ title }) {
+ const d = new Date()
+ const currentYear = d.getFullYear()
+ const startYear = BLOG.SINCE && BLOG.SINCE !== currentYear && BLOG.SINCE + '-'
+ return (
+
+ )
+}
+export default SiteInfo
diff --git a/themes/Fukasawa/components/TagItem.js b/themes/Fukasawa/components/TagItem.js
new file mode 100644
index 00000000..d972e0cd
--- /dev/null
+++ b/themes/Fukasawa/components/TagItem.js
@@ -0,0 +1,26 @@
+import { faTag } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import Link from 'next/link'
+import React from 'react'
+import { useGlobal } from '@/lib/global'
+
+const TagItem = ({ tag, selected }) => {
+ const { locale } = useGlobal()
+ if (!tag) {
+
{ locale.COMMON.NOTAG }
+ }
+ return (
+
+
+
+ {selected && } {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
+
+
+
+ )
+}
+
+export default TagItem
diff --git a/themes/Fukasawa/components/TagItemMini.js b/themes/Fukasawa/components/TagItemMini.js
new file mode 100644
index 00000000..9fec9e35
--- /dev/null
+++ b/themes/Fukasawa/components/TagItemMini.js
@@ -0,0 +1,17 @@
+import { faTag } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import Link from 'next/link'
+
+const TagItemMini = ({ tag, selected = false }) => {
+ return
+
+ {selected && } {tag.name + (tag.count ? `(${tag.count})` : '')}
+
+
+}
+
+export default TagItemMini
diff --git a/themes/Fukasawa/components/TopNav.js b/themes/Fukasawa/components/TopNav.js
new file mode 100644
index 00000000..f3e196aa
--- /dev/null
+++ b/themes/Fukasawa/components/TopNav.js
@@ -0,0 +1,51 @@
+import { faBars, faTimes } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { useState } from 'react'
+import Collapse from './Collapse'
+import GroupMenu from './GroupMenu'
+import Logo from './Logo'
+
+/**
+ * 顶部导航
+ * @param {*} param0
+ * @returns
+ */
+const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) => {
+ const [isOpen, changeShow] = useState(false)
+
+ const toggleMenuOpen = () => {
+ changeShow(!isOpen)
+ }
+
+ return (
+
+ {/* 导航栏 */}
+
+
+
+
+
+
+
+ {/* 左侧LOGO 标题 */}
+
+
+
+
+
+
+
+
+ {/* 右侧功能 */}
+
+
+ 菜单 { isOpen ? : }
+
+
+
+
+
+
)
+}
+
+export default TopNav
diff --git a/themes/Fukasawa/config_fuka.js b/themes/Fukasawa/config_fuka.js
new file mode 100644
index 00000000..b34851e8
--- /dev/null
+++ b/themes/Fukasawa/config_fuka.js
@@ -0,0 +1,12 @@
+const FUKA_CONFIG = {
+
+ POST_LIST_COVER: true, // 文章列表显示图片封面
+
+ // 菜单
+ MENU_ABOUT: true, // 显示关于
+ MENU_CATEGORY: true, // 显示分类
+ MENU_TAG: true, // 显示标签
+ MENU_ARCHIVE: true, // 显示归档
+ MENU_SEARCH: true // 显示搜索
+}
+export default FUKA_CONFIG
diff --git a/themes/Fukasawa/index.js b/themes/Fukasawa/index.js
new file mode 100644
index 00000000..aabed077
--- /dev/null
+++ b/themes/Fukasawa/index.js
@@ -0,0 +1,10 @@
+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'
diff --git a/themes/NEXT/Layout404.js b/themes/NEXT/Layout404.js
index 50d9d5ce..ff9c8927 100644
--- a/themes/NEXT/Layout404.js
+++ b/themes/NEXT/Layout404.js
@@ -21,7 +21,7 @@ export const Layout404 = () => {
}, 30000000)
})
- return
+ return
diff --git a/themes/NEXT/LayoutArchive.js b/themes/NEXT/LayoutArchive.js
index 9daca461..dfe77318 100644
--- a/themes/NEXT/LayoutArchive.js
+++ b/themes/NEXT/LayoutArchive.js
@@ -18,8 +18,8 @@ export const LayoutArchive = ({ posts, tags, categories, postCount }) => {
})
const meta = {
- title: `${locale.NAV.ARCHIVE} | ${BLOG.title}`,
- description: BLOG.description,
+ title: `${locale.NAV.ARCHIVE} | ${BLOG.TITLE}`,
+ description: BLOG.DESCRIPTION,
type: 'website'
}
diff --git a/themes/NEXT/LayoutBase.js b/themes/NEXT/LayoutBase.js
index 4e963b47..d93def9a 100644
--- a/themes/NEXT/LayoutBase.js
+++ b/themes/NEXT/LayoutBase.js
@@ -1,4 +1,3 @@
-import BLOG from '@/blog.config'
import CommonHead from '@/components/CommonHead'
import FloatDarkModeButton from './components/FloatDarkModeButton'
import Footer from './components/Footer'
@@ -12,6 +11,7 @@ import { useGlobal } from '@/lib/global'
import PropTypes from 'prop-types'
import React, { useEffect, useRef, useState } from 'react'
import smoothscroll from 'smoothscroll-polyfill'
+import CONFIG_NEXT from './config_next'
/**
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
@@ -79,7 +79,7 @@ const LayoutBase = ({
-
+
{onLoading
?
: <>
@@ -91,7 +91,7 @@ const LayoutBase = ({
{/* 右下角悬浮 */}
-
+
diff --git a/themes/NEXT/LayoutCategory.js b/themes/NEXT/LayoutCategory.js
index 25d6e58e..a86a79d6 100644
--- a/themes/NEXT/LayoutCategory.js
+++ b/themes/NEXT/LayoutCategory.js
@@ -1,6 +1,6 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
-import LayoutBase from '@/themes/NEXT/LayoutBase'
+import LayoutBase from './LayoutBase'
import StickyBar from './components/StickyBar'
import CategoryList from './components/CategoryList'
import BlogPostListScroll from './components/BlogPostListScroll'
@@ -8,8 +8,8 @@ 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,
+ 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
index 8140ed4a..b890f32b 100644
--- a/themes/NEXT/LayoutCategoryIndex.js
+++ b/themes/NEXT/LayoutCategoryIndex.js
@@ -14,8 +14,8 @@ export const LayoutCategoryIndex = ({
}) => {
const { locale } = useGlobal()
const meta = {
- title: `${locale.COMMON.CATEGORY} | ${BLOG.title}`,
- description: BLOG.description,
+ title: `${locale.COMMON.CATEGORY} | ${BLOG.TITLE}`,
+ description: BLOG.DESCRIPTION,
type: 'website'
}
return
diff --git a/themes/NEXT/LayoutIndex.js b/themes/NEXT/LayoutIndex.js
index dfa6590b..19993b20 100644
--- a/themes/NEXT/LayoutIndex.js
+++ b/themes/NEXT/LayoutIndex.js
@@ -4,7 +4,7 @@ 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'
+import CONFIG_NEXT from './config_next'
export const LayoutIndex = ({ posts, tags, meta, categories, postCount, latestPosts }) => {
return
- {CONFIG_NEXT.POSTS_LIST_TYPE !== 'page'
+ {CONFIG_NEXT.POST_LIST_TYPE !== 'page'
? (
)
diff --git a/themes/NEXT/LayoutPage.js b/themes/NEXT/LayoutPage.js
index 965ffc03..5680c9b9 100644
--- a/themes/NEXT/LayoutPage.js
+++ b/themes/NEXT/LayoutPage.js
@@ -1,7 +1,7 @@
import LayoutBase from './LayoutBase'
import LatestPostsGroup from './components/LatestPostsGroup'
import BlogPostListPage from './components/BlogPostListPage'
-import { CONFIG_NEXT } from './index'
+import CONFIG_NEXT from './config_next'
export const LayoutPage = ({ page, posts, tags, meta, categories, postCount, latestPosts }) => {
return (
diff --git a/themes/NEXT/LayoutSearch.js b/themes/NEXT/LayoutSearch.js
index 5204b371..4e845942 100644
--- a/themes/NEXT/LayoutSearch.js
+++ b/themes/NEXT/LayoutSearch.js
@@ -22,8 +22,8 @@ export const LayoutSearch = ({ posts, tags, categories, postCount }) => {
const { locale } = useGlobal()
const meta = {
- title: `${searchKey || ''} | ${locale.NAV.SEARCH} | ${BLOG.title} `,
- description: BLOG.description,
+ title: `${searchKey || ''} | ${locale.NAV.SEARCH} | ${BLOG.TITLE} `,
+ description: BLOG.DESCRIPTION,
type: 'website'
}
return (
diff --git a/themes/NEXT/LayoutSlug.js b/themes/NEXT/LayoutSlug.js
index fc7b7f01..ec1ad070 100644
--- a/themes/NEXT/LayoutSlug.js
+++ b/themes/NEXT/LayoutSlug.js
@@ -8,13 +8,7 @@ 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'
+import CONFIG_NEXT from './config_next'
export const LayoutSlug = ({
post,
@@ -27,7 +21,7 @@ export const LayoutSlug = ({
latestPosts
}) => {
const meta = {
- title: `${post.title} | ${BLOG.title}`,
+ title: `${post.title} | ${BLOG.TITLE}`,
description: post.summary,
type: 'article',
tags: post.tags
@@ -35,8 +29,10 @@ export const LayoutSlug = ({
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)
+ if (post?.blockMap?.block) {
+ post.content = Object.keys(post.blockMap.block)
+ post.toc = getPageTableOfContents(post, post.blockMap)
+ }
const floatSlot = post?.toc?.length > 1
? {
drawerRight?.current?.handleSwitchVisible()
diff --git a/themes/NEXT/LayoutTag.js b/themes/NEXT/LayoutTag.js
index 944a1cf5..bebc4cb2 100644
--- a/themes/NEXT/LayoutTag.js
+++ b/themes/NEXT/LayoutTag.js
@@ -9,8 +9,8 @@ export const LayoutTag = ({ tags, posts, tag, categories, postCount, latestPosts
const { locale } = useGlobal()
const meta = {
- title: `${tag} | ${locale.COMMON.TAGS} | ${BLOG.title}`,
- description: BLOG.description,
+ title: `${tag} | ${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
+ description: BLOG.DESCRIPTION,
type: 'website'
}
diff --git a/themes/NEXT/LayoutTagIndex.js b/themes/NEXT/LayoutTagIndex.js
index 6400d9e1..3abdfd25 100644
--- a/themes/NEXT/LayoutTagIndex.js
+++ b/themes/NEXT/LayoutTagIndex.js
@@ -8,8 +8,8 @@ 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,
+ title: `${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
+ description: BLOG.DESCRIPTION,
type: 'website'
}
return
diff --git a/themes/NEXT/components/ArticleCopyright.js b/themes/NEXT/components/ArticleCopyright.js
index 61f8f6d9..7ae6a349 100644
--- a/themes/NEXT/components/ArticleCopyright.js
+++ b/themes/NEXT/components/ArticleCopyright.js
@@ -1,9 +1,9 @@
-import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import Link from 'next/link'
+import CONFIG_NEXT from '../config_next'
export default function ArticleCopyright ({ author, url }) {
- if (!BLOG.widget?.showCopyRight) {
+ if (!CONFIG_NEXT.ARTICLE_COPYRIGHT) {
return <>>
}
const { locale } = useGlobal()
@@ -11,7 +11,7 @@ export default function ArticleCopyright ({ author, url }) {
-
{locale.COMMON.AUTHOR}:
-
+
{author}
diff --git a/themes/NEXT/components/ArticleDetail.js b/themes/NEXT/components/ArticleDetail.js
index ad29e8f6..dd56feef 100644
--- a/themes/NEXT/components/ArticleDetail.js
+++ b/themes/NEXT/components/ArticleDetail.js
@@ -1,9 +1,9 @@
import BLOG from '@/blog.config'
-import BlogAround from '@/themes/NEXT/components/BlogAround'
+import BlogAround from './BlogAround'
import Comment from '@/components/Comment'
-import RecommendPosts from '@/themes/NEXT/components/RecommendPosts'
-import ShareBar from '@/themes/NEXT/components/ShareBar'
-import TagItem from '@/themes/NEXT/components/TagItem'
+import RecommendPosts from './RecommendPosts'
+import ShareBar from './ShareBar'
+import TagItem from './TagItem'
import formatDate from '@/lib/formatDate'
import { useGlobal } from '@/lib/global'
import { faEye, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
@@ -13,7 +13,8 @@ import Link from 'next/link'
import { useRouter } from 'next/router'
import 'prismjs'
import 'prismjs/components/prism-bash'
-import 'prismjs/components/prism-javascript'
+import 'prismjs/components/prism-c'
+import 'prismjs/components/prism-java'
import 'prismjs/components/prism-markup'
import 'prismjs/components/prism-python'
import 'prismjs/components/prism-typescript'
@@ -28,7 +29,7 @@ import WordCount from './WordCount'
* @returns
*/
export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
- const url = BLOG.link + useRouter().asPath
+ const url = BLOG.LINK + useRouter().asPath
const { locale } = useGlobal()
const date = formatDate(post?.date?.start_date || post.createdTime, locale.LOCALE)
@@ -102,8 +103,7 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
-
+
|
@@ -141,11 +141,11 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
data-ad-layout="in-article"
data-ad-format="fluid"
data-ad-client="ca-pub-2708419466378217"
- data-ad-slot="3806269138">
+ data-ad-slot="3806269138"/>
{/* 版权声明 */}
-
+
{/* 推荐文章 */}
diff --git a/themes/NEXT/components/BlogAround.js b/themes/NEXT/components/BlogAround.js
index 96f2a504..f69d4d78 100644
--- a/themes/NEXT/components/BlogAround.js
+++ b/themes/NEXT/components/BlogAround.js
@@ -12,15 +12,15 @@ export default function BlogAround ({ prev, next }) {
return <>>
}
return
}
diff --git a/themes/NEXT/components/BlogPostArchive.js b/themes/NEXT/components/BlogPostArchive.js
index 4f2457b1..5c3bc169 100644
--- a/themes/NEXT/components/BlogPostArchive.js
+++ b/themes/NEXT/components/BlogPostArchive.js
@@ -1,4 +1,4 @@
-import React, { useRef } from 'react'
+import React from 'react'
import Link from 'next/link'
import BLOG from '@/blog.config'
/**
@@ -9,17 +9,16 @@ import BLOG from '@/blog.config'
* @constructor
*/
const BlogPostArchive = ({ posts = [], archiveTitle }) => {
- const targetRef = useRef(null)
if (!posts || posts.length === 0) {
return <>>
} else {
- return
+ return
{archiveTitle}
{posts.map(post => (
-
-
{post.date.start_date}
-
+
{post.date.start_date}
+
{post.title}
diff --git a/themes/NEXT/components/BlogPostCard.js b/themes/NEXT/components/BlogPostCard.js
index 9ef97a0b..e4db02ec 100644
--- a/themes/NEXT/components/BlogPostCard.js
+++ b/themes/NEXT/components/BlogPostCard.js
@@ -8,16 +8,17 @@ import React from 'react'
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
import Card from './Card'
import TagItemMini from './TagItemMini'
+import CONFIG_NEXT from '../config_next'
const BlogPostCard = ({ post, showSummary }) => {
const { locale } = useGlobal()
- const showPreview = BLOG.home?.showPreview && post.blockMap
+ const showPreview = CONFIG_NEXT.POST_LIST_PREVIEW && post.blockMap
return (
-
+
{post.title}
@@ -59,7 +60,7 @@ const BlogPostCard = ({ post, showSummary }) => {
}
- {BLOG.home?.showPostCover && post?.page_cover && (
-
+ {CONFIG_NEXT.POST_LIST_COVER && post?.page_cover && (
+
diff --git a/themes/NEXT/components/BlogPostListPage.js b/themes/NEXT/components/BlogPostListPage.js
index 1f1b89b5..ac252d8e 100644
--- a/themes/NEXT/components/BlogPostListPage.js
+++ b/themes/NEXT/components/BlogPostListPage.js
@@ -1,7 +1,7 @@
-import BlogPostCard from '@/themes/NEXT/components/BlogPostCard'
+import BlogPostCard from './BlogPostCard'
import PaginationNumber from './PaginationNumber'
import BLOG from '@/blog.config'
-import BlogPostListEmpty from '@/themes/NEXT/components/BlogPostListEmpty'
+import BlogPostListEmpty from './BlogPostListEmpty'
/**
* 文章列表分页表格
@@ -12,7 +12,7 @@ import BlogPostListEmpty from '@/themes/NEXT/components/BlogPostListEmpty'
* @constructor
*/
const BlogPostListPage = ({ page = 1, posts = [], postCount }) => {
- const totalPage = Math.ceil(postCount / BLOG.postsPerPage)
+ const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE)
if (!posts || posts.length === 0) {
return
diff --git a/themes/NEXT/components/BlogPostListScroll.js b/themes/NEXT/components/BlogPostListScroll.js
index b46250ed..8e520392 100644
--- a/themes/NEXT/components/BlogPostListScroll.js
+++ b/themes/NEXT/components/BlogPostListScroll.js
@@ -1,20 +1,20 @@
import BLOG from '@/blog.config'
-import BlogPostCard from '@/themes/NEXT/components/BlogPostCard'
-import BlogPostListEmpty from '@/themes/NEXT/components/BlogPostListEmpty'
+import BlogPostCard from './BlogPostCard'
+import BlogPostListEmpty from './BlogPostListEmpty'
import { useGlobal } from '@/lib/global'
import throttle from 'lodash.throttle'
import React, { useCallback, useEffect, useRef, useState } from 'react'
+import CONFIG_NEXT from '../config_next'
/**
* 博客列表滚动分页
* @param posts 所有文章
* @param tags 所有标签
- * @param targetRef 指向父容器,用于计算下拉滚动的高度
* @returns {JSX.Element}
* @constructor
*/
-const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = BLOG.home.showSummary }) => {
- const postsPerPage = BLOG.postsPerPage
+const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_NEXT.POST_LIST_SUMMARY }) => {
+ const postsPerPage = BLOG.POSTS_PER_PAGE
const [page, updatePage] = useState(1)
const postsToShow = getPostByPage(page, posts, postsPerPage)
diff --git a/themes/NEXT/components/DarkModeButton.js b/themes/NEXT/components/DarkModeButton.js
index ae344cf1..145b9358 100644
--- a/themes/NEXT/components/DarkModeButton.js
+++ b/themes/NEXT/components/DarkModeButton.js
@@ -1,6 +1,7 @@
-import { loadUserThemeFromCookies, saveTheme, useGlobal } from '@/lib/global'
+import { useGlobal } from '@/lib/global'
import { faMoon, faSun } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { loadUserThemeFromCookies, saveTheme } from '@/lib/theme'
const DarkModeButton = () => {
const { changeTheme } = useGlobal()
diff --git a/themes/NEXT/components/FloatDarkModeButton.js b/themes/NEXT/components/FloatDarkModeButton.js
index 6a286fcd..74257bf0 100644
--- a/themes/NEXT/components/FloatDarkModeButton.js
+++ b/themes/NEXT/components/FloatDarkModeButton.js
@@ -1,11 +1,11 @@
-import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { loadUserThemeFromCookies, saveTheme } from '@/lib/theme'
import { faMoon, faSun } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import CONFIG_NEXT from '../config_next'
export default function FloatDarkModeButton () {
- if (!BLOG.widget?.showDarkMode) {
+ if (!CONFIG_NEXT.WIDGET_DARK_MODE) {
return <>>
}
diff --git a/themes/NEXT/components/Footer.js b/themes/NEXT/components/Footer.js
index 60e64af8..57ad7797 100644
--- a/themes/NEXT/components/Footer.js
+++ b/themes/NEXT/components/Footer.js
@@ -6,18 +6,17 @@ import BLOG from '@/blog.config'
const Footer = ({ title }) => {
const d = new Date()
const currentYear = d.getFullYear()
- const startYear = BLOG.since && BLOG.since !== currentYear && BLOG.since + '-'
+ const startYear = BLOG.SINCE && BLOG.SINCE !== currentYear && BLOG.SINCE + '-'
return (