mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
Merge pull request #1175 from tangly1024/feat/theme-switch
Feat/theme switch
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { saveDarkModeToCookies } from '@/lib/theme'
|
||||
import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
|
||||
const DarkModeButton = (props) => {
|
||||
const { isDarkMode, updateDarkMode } = useGlobal()
|
||||
|
||||
@@ -2,7 +2,8 @@ import BLOG from '@/blog.config'
|
||||
import { useEffect, useState } from 'react'
|
||||
import Select from './Select'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { ALL_THEME } from '@/lib/theme'
|
||||
import { ALL_THEME } from '@/themes/theme'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -10,16 +11,14 @@ import { ALL_THEME } from '@/lib/theme'
|
||||
*/
|
||||
const DebugPanel = () => {
|
||||
const [show, setShow] = useState(false)
|
||||
const { changeTheme, switchTheme, locale } = useGlobal()
|
||||
const { theme, switchTheme, locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const [siteConfig, updateSiteConfig] = useState({})
|
||||
// const [themeConfig, updateThemeConfig] = useState({})
|
||||
const [debugTheme, updateDebugTheme] = useState(BLOG.THEME)
|
||||
|
||||
// 主题下拉框
|
||||
const themeOptions = ALL_THEME.map(t => ({ value: t, text: t }))
|
||||
|
||||
useEffect(() => {
|
||||
changeTheme(BLOG.THEME)
|
||||
updateSiteConfig(Object.assign({}, BLOG))
|
||||
// updateThemeConfig(Object.assign({}, ThemeMap[BLOG.THEME].THEME_CONFIG))
|
||||
}, [])
|
||||
@@ -29,15 +28,13 @@ const DebugPanel = () => {
|
||||
}
|
||||
|
||||
function handleChangeDebugTheme() {
|
||||
const newTheme = switchTheme()
|
||||
// updateThemeConfig(Object.assign({}, ThemeMap[newTheme].THEME_CONFIG))
|
||||
updateDebugTheme(newTheme)
|
||||
switchTheme()
|
||||
}
|
||||
|
||||
function handleUpdateDebugTheme(e) {
|
||||
changeTheme(e)
|
||||
// updateThemeConfig(Object.assign({}, ThemeMap[theme].THEME_CONFIG))
|
||||
updateDebugTheme(e)
|
||||
function handleUpdateDebugTheme(newTheme) {
|
||||
console.log('切换主题', newTheme)
|
||||
const query = { ...router.query, theme: newTheme }
|
||||
router.push({ pathname: router.pathname, query })
|
||||
}
|
||||
|
||||
function filterResult(text) {
|
||||
@@ -75,7 +72,7 @@ const DebugPanel = () => {
|
||||
<div className='flex'>
|
||||
<Select
|
||||
label={locale.COMMON.THEME_SWITCH}
|
||||
value={debugTheme}
|
||||
value={theme}
|
||||
options={themeOptions}
|
||||
onChange={handleUpdateDebugTheme}
|
||||
/>
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import React from 'react'
|
||||
import { Draggable } from './Draggable'
|
||||
import { ALL_THEME } from '@/lib/theme'
|
||||
import { ALL_THEME } from '@/themes/theme'
|
||||
import { useRouter } from 'next/router'
|
||||
/**
|
||||
*
|
||||
* @returns 主题切换
|
||||
*/
|
||||
const ThemeSwitch = () => {
|
||||
const { theme, changeTheme } = useGlobal()
|
||||
const { theme } = useGlobal()
|
||||
const router = useRouter()
|
||||
|
||||
// 修改当前路径url中的 theme 参数
|
||||
// 例如 http://localhost?theme=hexo 跳转到 http://localhost?theme=newTheme
|
||||
const onSelectChange = (e) => {
|
||||
changeTheme(e.target.value)
|
||||
const newTheme = e.target.value
|
||||
const query = router.query
|
||||
query.theme = newTheme
|
||||
router.push({ pathname: router.pathname, query })
|
||||
}
|
||||
|
||||
return (<>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { generateLocaleDict, initLocale } from './lang'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import Router, { useRouter } from 'next/router'
|
||||
import { useRouter } from 'next/router'
|
||||
import BLOG from '@/blog.config'
|
||||
import { ALL_THEME, initDarkMode, initTheme, saveThemeToCookies } from '@/lib/theme'
|
||||
import { ALL_THEME, initDarkMode } from '@/themes/theme'
|
||||
import NProgress from 'nprogress'
|
||||
import LoadingCover from '@/components/LoadingCover'
|
||||
import { isBrowser } from './utils'
|
||||
import { getQueryVariable, isBrowser } from './utils'
|
||||
|
||||
const GlobalContext = createContext()
|
||||
|
||||
@@ -16,18 +16,17 @@ const GlobalContext = createContext()
|
||||
* @constructor
|
||||
*/
|
||||
export function GlobalContextProvider({ children }) {
|
||||
const router = useRouter()
|
||||
const [lang, updateLang] = useState(BLOG.LANG) // 默认语言
|
||||
const [locale, updateLocale] = useState(generateLocaleDict(BLOG.LANG)) // 默认语言
|
||||
const [theme, setTheme] = useState(BLOG.THEME) // 默认博客主题
|
||||
const [isDarkMode, updateDarkMode] = useState(BLOG.APPEARANCE === 'dark') // 默认深色模式
|
||||
const [onLoading, setOnLoading] = useState(false) // 抓取文章数据
|
||||
const [onReading, setOnReading] = useState(false) // 网页资源加载
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
initLocale(lang, locale, updateLang, updateLocale)
|
||||
initDarkMode(isDarkMode, updateDarkMode)
|
||||
initTheme(theme, changeTheme)
|
||||
if (isBrowser()) {
|
||||
// 监听用户刷新页面
|
||||
const handleBeforeUnload = (event) => {
|
||||
@@ -45,6 +44,11 @@ export function GlobalContextProvider({ children }) {
|
||||
useEffect(() => {
|
||||
const handleStart = (url) => {
|
||||
NProgress.start()
|
||||
const { theme } = router.query
|
||||
if (theme && !url.includes(`theme=${theme}`)) {
|
||||
const newUrl = `${url}${url.includes('?') ? '&' : '?'}theme=${theme}`
|
||||
router.push(newUrl)
|
||||
}
|
||||
setOnLoading(true)
|
||||
}
|
||||
const handleStop = () => {
|
||||
@@ -52,6 +56,9 @@ export function GlobalContextProvider({ children }) {
|
||||
setOnLoading(false)
|
||||
}
|
||||
|
||||
const queryTheme = getQueryVariable('theme') || BLOG.THEME
|
||||
setTheme(queryTheme)
|
||||
|
||||
router.events.on('routeChangeStart', handleStart)
|
||||
router.events.on('routeChangeError', handleStop)
|
||||
router.events.on('routeChangeComplete', handleStop)
|
||||
@@ -62,24 +69,16 @@ export function GlobalContextProvider({ children }) {
|
||||
}
|
||||
}, [router])
|
||||
|
||||
// 切换主题
|
||||
function switchTheme() {
|
||||
const currentIndex = ALL_THEME.indexOf(theme)
|
||||
const newIndex = currentIndex < ALL_THEME.length - 1 ? currentIndex + 1 : 0
|
||||
const newTheme = ALL_THEME[newIndex]
|
||||
changeTheme(newTheme)
|
||||
const query = { ...router.query, theme: newTheme }
|
||||
router.push({ pathname: router.pathname, query })
|
||||
return newTheme
|
||||
}
|
||||
|
||||
function changeTheme(theme) {
|
||||
Router.query.theme = ''
|
||||
if (ALL_THEME.indexOf(theme) > -1) {
|
||||
setTheme(theme)
|
||||
} else {
|
||||
setTheme(BLOG.THEME)
|
||||
}
|
||||
saveThemeToCookies(theme)
|
||||
}
|
||||
|
||||
return (
|
||||
<GlobalContext.Provider value={{
|
||||
onLoading,
|
||||
@@ -91,7 +90,6 @@ export function GlobalContextProvider({ children }) {
|
||||
theme,
|
||||
setTheme,
|
||||
switchTheme,
|
||||
changeTheme,
|
||||
setOnReading
|
||||
}}>
|
||||
<LoadingCover onReading={onReading} setOnReading={setOnReading}/>
|
||||
|
||||
@@ -65,7 +65,7 @@ export async function getNotionPageData({ pageId, from }) {
|
||||
const cacheKey = 'page_block_' + pageId
|
||||
const data = await getDataFromCache(cacheKey)
|
||||
if (data && data.pageIds?.length > 0) {
|
||||
console.log('[缓存]:', `from:${from}`, `root-page-id:${pageId}`, data)
|
||||
console.log('[缓存]:', `from:${from}`, `root-page-id:${pageId}`)
|
||||
return data
|
||||
}
|
||||
const pageRecordMap = await getDataBaseInfoByNotionAPI({ pageId, from })
|
||||
|
||||
15
lib/utils.js
15
lib/utils.js
@@ -51,16 +51,27 @@ export function loadExternalResource(url, type) {
|
||||
* @param {}} variable
|
||||
* @returns
|
||||
*/
|
||||
export function getQueryVariable(variable) {
|
||||
export function getQueryVariable(key) {
|
||||
const query = isBrowser() ? window.location.search.substring(1) : ''
|
||||
const vars = query.split('&')
|
||||
for (let i = 0; i < vars.length; i++) {
|
||||
const pair = vars[i].split('=')
|
||||
if (pair[0] === variable) { return pair[1] }
|
||||
if (pair[0] === key) { return pair[1] }
|
||||
}
|
||||
return (false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 URL 中指定参数的值
|
||||
* @param {string} url
|
||||
* @param {string} param
|
||||
* @returns {string|null}
|
||||
*/
|
||||
export function getQueryParam(url, param) {
|
||||
const searchParams = new URLSearchParams(url.split('?')[1])
|
||||
return searchParams.get(param)
|
||||
}
|
||||
|
||||
/**
|
||||
* 深度合并两个对象
|
||||
* @param target
|
||||
|
||||
@@ -2,6 +2,9 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
enabled: process.env.ANALYZE === 'true'
|
||||
})
|
||||
|
||||
const { THEME } = require('./blog.config')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = withBundleAnalyzer({
|
||||
images: {
|
||||
// 图片压缩
|
||||
@@ -64,6 +67,10 @@ module.exports = withBundleAnalyzer({
|
||||
// 'react-dom': 'preact/compat'
|
||||
// })
|
||||
// }
|
||||
|
||||
// 动态主题:添加 resolve.alias 配置,将动态路径映射到实际路径
|
||||
config.resolve.alias['@theme-components'] = path.resolve(__dirname, 'themes', THEME)
|
||||
|
||||
return config
|
||||
}
|
||||
})
|
||||
|
||||
29
pages/404.js
29
pages/404.js
@@ -1,15 +1,7 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Loading from '@/components/Loading'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import BLOG from '@/blog.config'
|
||||
|
||||
const layout = 'Layout404'
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 404
|
||||
@@ -17,22 +9,15 @@ const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`),
|
||||
* @returns
|
||||
*/
|
||||
const NoFound = props => {
|
||||
const { theme, siteInfo } = useGlobal()
|
||||
const { siteInfo } = useGlobal()
|
||||
const meta = { title: `${props?.siteInfo?.title} | 页面找不到啦`, image: siteInfo?.pageCover }
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps () {
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { getPostBlocks } from '@/lib/notion'
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { idToUuid } from 'notion-utils'
|
||||
import { useRouter } from 'next/router'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { getNotion } from '@/lib/notion/getNotion'
|
||||
import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents'
|
||||
import md5 from 'js-md5'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutSlug'
|
||||
|
||||
/**
|
||||
* 懒加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 根据notion的slug访问页面
|
||||
@@ -25,19 +16,11 @@ const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`),
|
||||
* @returns
|
||||
*/
|
||||
const Slug = props => {
|
||||
const { theme, setOnLoading } = useGlobal()
|
||||
const { post, siteInfo } = props
|
||||
const router = useRouter()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
// 文章锁🔐
|
||||
const [lock, setLock] = useState(post?.password && post?.password !== '')
|
||||
@@ -57,7 +40,6 @@ const Slug = props => {
|
||||
|
||||
// 文章加载
|
||||
useEffect(() => {
|
||||
setOnLoading(false)
|
||||
// 404
|
||||
if (!post) {
|
||||
setTimeout(() => {
|
||||
@@ -98,9 +80,7 @@ const Slug = props => {
|
||||
}
|
||||
props = { ...props, lock, meta, setLock, validPassword }
|
||||
|
||||
return <Suspense fallback={<Loading />}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
|
||||
@@ -33,9 +33,9 @@ const MyApp = ({ Component, pageProps }) => {
|
||||
|
||||
return (
|
||||
<GlobalContextProvider>
|
||||
<Component {...pageProps} />
|
||||
<ExternalPlugins {...pageProps}/>
|
||||
<ExternalScript/>
|
||||
<Component {...pageProps}/>
|
||||
<ExternalPlugins {...pageProps} />
|
||||
<ExternalScript />
|
||||
</GlobalContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
import BLOG from '@/blog.config'
|
||||
import CommonScript from '@/components/CommonScript'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx) {
|
||||
@@ -22,7 +21,6 @@ class MyDocument extends Document {
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
<Loading />
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,29 +1,16 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import React, { Suspense, useEffect, useState } from 'react'
|
||||
import React from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import dynamic from 'next/dynamic'
|
||||
import BLOG from '@/blog.config'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutArchive'
|
||||
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
const ArchiveIndex = props => {
|
||||
const { siteInfo } = props
|
||||
const { theme, locale } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
const { locale } = useGlobal()
|
||||
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${locale.NAV.ARCHIVE} | ${siteInfo?.title}`,
|
||||
@@ -35,9 +22,7 @@ const ArchiveIndex = props => {
|
||||
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import React, { Suspense, useEffect, useState } from 'react'
|
||||
import React from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import dynamic from 'next/dynamic'
|
||||
import BLOG from '@/blog.config'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutCategory'
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 分类页
|
||||
@@ -18,17 +12,10 @@ const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`),
|
||||
*/
|
||||
export default function Category(props) {
|
||||
const { siteInfo } = props
|
||||
const { locale, theme } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
const { locale } = useGlobal()
|
||||
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${props.category} | ${locale.COMMON.CATEGORY} | ${
|
||||
@@ -42,9 +29,7 @@ export default function Category(props) {
|
||||
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps({ params: { category } }) {
|
||||
|
||||
@@ -1,35 +1,21 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import React, { Suspense, useEffect, useState } from 'react'
|
||||
import React from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import dynamic from 'next/dynamic'
|
||||
import BLOG from '@/blog.config'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutCategory'
|
||||
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 分类页
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
|
||||
export default function Category(props) {
|
||||
const { theme } = useGlobal()
|
||||
const { siteInfo } = props
|
||||
const { locale } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${props.category} | ${locale.COMMON.CATEGORY} | ${
|
||||
@@ -43,9 +29,7 @@ export default function Category(props) {
|
||||
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps({ params: { category, page } }) {
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import React, { Suspense, useEffect, useState } from 'react'
|
||||
import React from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import dynamic from 'next/dynamic'
|
||||
import BLOG from '@/blog.config'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutCategoryIndex'
|
||||
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 分类首页
|
||||
@@ -18,19 +11,11 @@ const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`),
|
||||
* @returns
|
||||
*/
|
||||
export default function Category(props) {
|
||||
const { theme } = useGlobal()
|
||||
const { locale } = useGlobal()
|
||||
const { siteInfo } = props
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${locale.COMMON.CATEGORY} | ${siteInfo?.title}`,
|
||||
@@ -41,9 +26,7 @@ export default function Category(props) {
|
||||
}
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
|
||||
@@ -1,41 +1,21 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { getPostBlocks } from '@/lib/notion'
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { generateRss } from '@/lib/rss'
|
||||
import { generateRobotsTxt } from '@/lib/robots.txt'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutIndex'
|
||||
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
/**
|
||||
* 首页布局
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const Index = props => {
|
||||
// 动态切换主题
|
||||
const { theme } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
|
||||
return <Suspense fallback={<Loading />}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
const Index = props => {
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { getPostBlocks } from '@/lib/notion'
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutPage'
|
||||
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 文章列表分页
|
||||
@@ -19,17 +10,10 @@ const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`),
|
||||
* @returns
|
||||
*/
|
||||
const Page = props => {
|
||||
const { theme } = useGlobal()
|
||||
const { siteInfo } = props
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${props?.page} | Page | ${siteInfo?.title}`,
|
||||
@@ -41,9 +25,7 @@ const Page = props => {
|
||||
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading />}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
|
||||
@@ -2,28 +2,15 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { getDataFromCache } from '@/lib/cache/cache_manager'
|
||||
import BLOG from '@/blog.config'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutSearch'
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
const Index = props => {
|
||||
const { keyword, siteInfo } = props
|
||||
const { locale, theme } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
const { locale } = useGlobal()
|
||||
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteInfo?.title}`,
|
||||
@@ -35,9 +22,7 @@ const Index = props => {
|
||||
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,29 +1,16 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { getDataFromCache } from '@/lib/cache/cache_manager'
|
||||
import dynamic from 'next/dynamic'
|
||||
import BLOG from '@/blog.config'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutSearch'
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
const Index = props => {
|
||||
const { keyword, siteInfo } = props
|
||||
const { locale, theme } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
const { locale } = useGlobal()
|
||||
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${keyword || ''}${keyword ? ' | ' : ''}${locale.NAV.SEARCH} | ${siteInfo?.title}`,
|
||||
@@ -35,9 +22,7 @@ const Index = props => {
|
||||
|
||||
props = { ...props, meta, currentSearch: keyword }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,31 +2,18 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { useRouter } from 'next/router'
|
||||
import BLOG from '@/blog.config'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import Loading from '@/components/Loading'
|
||||
const layout = 'LayoutSearch'
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
const Search = props => {
|
||||
const { posts, siteInfo } = props
|
||||
const { theme, locale } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
const { locale } = useGlobal()
|
||||
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const router = useRouter()
|
||||
const keyword = getSearchKey(router)
|
||||
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
|
||||
let filteredPosts
|
||||
// 静态过滤
|
||||
if (keyword) {
|
||||
@@ -51,9 +38,7 @@ const Search = props => {
|
||||
|
||||
props = { ...props, meta, posts: filteredPosts }
|
||||
|
||||
return <Suspense fallback={<Loading />}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,29 +1,20 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import BLOG from '@/blog.config'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import Loading from '@/components/Loading'
|
||||
const layout = 'LayoutTag'
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 标签下的文章列表
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const Tag = props => {
|
||||
const { theme } = useGlobal()
|
||||
const { locale } = useGlobal()
|
||||
const { tag, siteInfo } = props
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${tag} | ${locale.COMMON.TAGS} | ${siteInfo?.title}`,
|
||||
@@ -34,9 +25,7 @@ const Tag = props => {
|
||||
}
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps({ params: { tag } }) {
|
||||
|
||||
@@ -1,29 +1,15 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import BLOG from '@/blog.config'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import Loading from '@/components/Loading'
|
||||
|
||||
const layout = 'LayoutTag'
|
||||
/**
|
||||
* 加载默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
const Tag = props => {
|
||||
const { theme } = useGlobal()
|
||||
const { locale } = useGlobal()
|
||||
const { tag, siteInfo } = props
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${tag} | ${locale.COMMON.TAGS} | ${siteInfo?.title}`,
|
||||
@@ -34,9 +20,7 @@ const Tag = props => {
|
||||
}
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps({ params: { tag, page } }) {
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
|
||||
import { Suspense, useEffect, useState } from 'react'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import BLOG from '@/blog.config'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Loading from '@/components/Loading'
|
||||
const layout = 'LayoutTagIndex'
|
||||
/**
|
||||
* 默认主题
|
||||
*/
|
||||
const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`), { ssr: true })
|
||||
import { useRouter } from 'next/router'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
|
||||
/**
|
||||
* 标签首页
|
||||
@@ -18,16 +12,9 @@ const DefaultLayout = dynamic(() => import(`@/themes/${BLOG.THEME}/${layout}`),
|
||||
const TagIndex = props => {
|
||||
const { locale } = useGlobal()
|
||||
const { siteInfo } = props
|
||||
const { theme } = useGlobal()
|
||||
const [Layout, setLayout] = useState(DefaultLayout)
|
||||
// 切换主题
|
||||
useEffect(() => {
|
||||
const loadLayout = async () => {
|
||||
const newLayout = await dynamic(() => import(`@/themes/${theme}/${layout}`))
|
||||
setLayout(newLayout)
|
||||
}
|
||||
loadLayout()
|
||||
}, [theme])
|
||||
|
||||
// 根据页面路径加载不同Layout文件
|
||||
const Layout = getLayoutByTheme(useRouter())
|
||||
|
||||
const meta = {
|
||||
title: `${locale.COMMON.TAGS} | ${siteInfo?.title}`,
|
||||
@@ -38,9 +25,7 @@ const TagIndex = props => {
|
||||
}
|
||||
props = { ...props, meta }
|
||||
|
||||
return <Suspense fallback={<Loading/>}>
|
||||
<Layout {...props} />
|
||||
</Suspense>
|
||||
return <Layout {...props} />
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
|
||||
@@ -1,326 +0,0 @@
|
||||
// 注: process.env.XX是Vercel的环境变量,配置方式见:https://docs.tangly1024.com/zh/features/personality
|
||||
const BLOG = {
|
||||
// Important page_id!!!Duplicate Template from https://www.notion.so/tanghh/02ab3b8678004aa69e9e415905ef32a5
|
||||
NOTION_PAGE_ID:
|
||||
process.env.NOTION_PAGE_ID || '02ab3b8678004aa69e9e415905ef32a5',
|
||||
PSEUDO_STATIC: false, // 伪静态路径,开启后所有文章URL都以 .html 结尾。
|
||||
NEXT_REVALIDATE_SECOND: process.env.NEXT_PUBLIC_REVALIDATE_SECOND || 5, // 更新内容缓存间隔 单位(秒);即每个页面有5秒的纯静态期、此期间无论多少次访问都不会抓取notion数据;调大该值有助于节省Vercel资源、同时提升访问速率,但也会使文章更新有延迟。
|
||||
THEME: process.env.NEXT_PUBLIC_THEME || 'hexo', // 主题, 支持 ['next','hexo',"fukasawa','medium','example'] @see https://preview.tangly1024.com
|
||||
THEME_SWITCH: process.env.NEXT_PUBLIC_THEME_SWITCH || false, // 是否显示切换主题按钮
|
||||
LANG: process.env.NEXT_PUBLIC_LANG || 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more.
|
||||
SINCE: 2021, // e.g if leave this empty, current year will be used.
|
||||
APPEARANCE: process.env.NEXT_PUBLIC_APPEARANCE || 'light', // ['light', 'dark', 'auto'], // light 日间模式 , dark夜间模式, auto根据时间和主题自动夜间模式
|
||||
APPEARANCE_DARK_TIME: process.env.NEXT_PUBLIC_APPEARANCE_DARK_TIME || [18, 6], // 夜间模式起至时间,false时关闭根据时间自动切换夜间模式
|
||||
|
||||
CUSTOM_MENU: process.env.NEXT_PUBLIC_CUSTOM_MENU || false, // 支持Menu 类型,从3.12.0版本起,各主题将逐步支持灵活的二级菜单配置,替代了原来的Page类型,此配置是试验功能、默认关闭。
|
||||
|
||||
AUTHOR: process.env.NEXT_PUBLIC_AUTHOR || 'NotionNext', // 您的昵称 例如 tangly1024
|
||||
BIO: process.env.NEXT_PUBLIC_BIO || '一个普通的干饭人🍚', // 作者简介
|
||||
LINK: process.env.NEXT_PUBLIC_LINK || 'https://tangly1024.com', // 网站地址
|
||||
KEYWORDS: process.env.NEXT_PUBLIC_KEYWORD || 'Notion, 博客', // 网站关键词 英文逗号隔开
|
||||
// 社交链接,不需要可留空白,例如 CONTACT_WEIBO:''
|
||||
CONTACT_EMAIL: process.env.NEXT_PUBLIC_CONTACT_EMAIL || '', // 邮箱地址 例如mail@tangly1024.com
|
||||
CONTACT_WEIBO: process.env.NEXT_PUBLIC_CONTACT_WEIBO || '', // 你的微博个人主页
|
||||
CONTACT_TWITTER: process.env.NEXT_PUBLIC_CONTACT_TWITTER || '', // 你的twitter个人主页
|
||||
CONTACT_GITHUB: process.env.NEXT_PUBLIC_CONTACT_GITHUB || '', // 你的github个人主页 例如 https://github.com/tangly1024
|
||||
CONTACT_TELEGRAM: process.env.NEXT_PUBLIC_CONTACT_TELEGRAM || '', // 你的telegram 地址 例如 https://t.me/tangly_1024
|
||||
CONTACT_LINKEDIN: process.env.NEXT_PUBLIC_CONTACT_LINKEDIN || '', // 你的linkedIn 首页
|
||||
|
||||
// 网站字体
|
||||
FONT_STYLE: process.env.NEXT_PUBLIC_FONT_STYLE || 'font-serif', // ['font-serif','font-sans'] 两种可选,分别是衬线和无衬线: 参考 https://www.jianshu.com/p/55e410bd2115
|
||||
FONT_URL: [
|
||||
// 字体CSS 例如 https://npm.elemecdn.com/lxgw-wenkai-webfont@1.6.0/style.css
|
||||
'https://fonts.googleapis.com/css?family=Bitter&display=swap',
|
||||
'https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300&display=swap',
|
||||
'https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@300&display=swap'
|
||||
],
|
||||
FONT_SANS: [
|
||||
// 无衬线字体 例如'LXGW WenKai'
|
||||
'Bitter',
|
||||
'"PingFang SC"',
|
||||
'-apple-system',
|
||||
'BlinkMacSystemFont',
|
||||
'"Hiragino Sans GB"',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"',
|
||||
'"Segoe UI"',
|
||||
'"Noto Sans SC"',
|
||||
'HarmonyOS_Regular',
|
||||
'"Microsoft YaHei"',
|
||||
'"Helvetica Neue"',
|
||||
'Helvetica',
|
||||
'"Source Han Sans SC"',
|
||||
'Arial',
|
||||
'sans-serif',
|
||||
'"Apple Color Emoji"'
|
||||
],
|
||||
FONT_SERIF: [
|
||||
// 衬线字体 例如'LXGW WenKai'
|
||||
'Bitter',
|
||||
'"Noto Serif SC"',
|
||||
'SimSun',
|
||||
'"Times New Roman"',
|
||||
'Times',
|
||||
'serif',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"',
|
||||
'"Apple Color Emoji"'
|
||||
],
|
||||
FONT_AWESOME: '/css/all.min.css', // font-awesome 字体图标地址
|
||||
|
||||
// 自定义外部脚本,外部样式
|
||||
CUSTOM_EXTERNAL_JS: [''], // e.g. ['http://xx.com/script.js','http://xx.com/script.js']
|
||||
CUSTOM_EXTERNAL_CSS: [''], // e.g. ['http://xx.com/style.css','http://xx.com/style.css']
|
||||
|
||||
// 侧栏布局 是否反转(左变右,右变左) 已支持主题: hexo next medium fukasawa example
|
||||
LAYOUT_SIDEBAR_REVERSE: false,
|
||||
|
||||
// 一个小插件展示你的facebook fan page~ @see https://tw.andys.pro/article/add-facebook-fanpage-notionnext
|
||||
FACEBOOK_PAGE_TITLE: process.env.NEXT_PUBLIC_FACEBOOK_PAGE_TITLE || null, // 邊欄 Facebook Page widget 的標題欄,填''則無標題欄 e.g FACEBOOK 粉絲團'
|
||||
FACEBOOK_PAGE: process.env.NEXT_PUBLIC_FACEBOOK_PAGE || null, // Facebook Page 的連結 e.g https://www.facebook.com/tw.andys.pro
|
||||
FACEBOOK_PAGE_ID: process.env.NEXT_PUBLIC_FACEBOOK_PAGE_ID || '', // Facebook Page ID 來啟用 messenger 聊天功能
|
||||
FACEBOOK_APP_ID: process.env.NEXT_PUBLIC_FACEBOOK_APP_ID || '', // Facebook App ID 來啟用 messenger 聊天功能 获取: https://developers.facebook.com/
|
||||
|
||||
BEI_AN: process.env.NEXT_PUBLIC_BEI_AN || '', // 备案号 闽ICP备XXXXXXX
|
||||
|
||||
// PrismJs 代码相关
|
||||
PRISM_JS_AUTO_LOADER:
|
||||
'https://npm.elemecdn.com/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js',
|
||||
PRISM_JS_PATH: 'https://npm.elemecdn.com/prismjs@1.29.0/components/',
|
||||
PRISM_THEME_PATH:
|
||||
'https://npm.elemecdn.com/prism-themes/themes/prism-a11y-dark.min.css', // 代码样式主题 更多参考 https://github.com/PrismJS/prism-themes
|
||||
CODE_MAC_BAR: true, // 代码左上角显示mac的红黄绿图标
|
||||
CODE_LINE_NUMBERS: process.env.NEXT_PUBLIC_CODE_LINE_NUMBERS || 'false', // 是否显示行号
|
||||
|
||||
BACKGROUND_LIGHT: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc
|
||||
BACKGROUND_DARK: '#000000', // use hex value, don't forget '#'
|
||||
SUB_PATH: '', // leave this empty unless you want to deploy in a folder
|
||||
|
||||
POST_URL_PREFIX: process.env.NEXT_PUBLIC_POST_URL_PREFIX || 'article',
|
||||
// POST类型文章的默认路径前缀,例如默认POST类型的路径是 /article/[slug]
|
||||
// 如果此项配置为 '' 空, 则文章将没有前缀路径,使用场景: 希望文章前缀路径为 /post 的情况 支持多级
|
||||
// 支援類似 WP 可自訂文章連結格式的功能:https://wordpress.org/documentation/article/customize-permalinks/,目前只先實作 %year%/%month%/%day%
|
||||
// 例:如想連結改成前綴 article + 時間戳記,可變更為: 'article/%year%/%month%/%day%'
|
||||
|
||||
POST_LIST_STYLE: process.env.NEXT_PUBLIC_PPOST_LIST_STYLE || 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
|
||||
POST_LIST_PREVIEW: process.env.NEXT_PUBLIC_POST_PREVIEW || 'false', // 是否在列表加载文章预览
|
||||
POST_PREVIEW_LINES: 12, // 预览博客行数
|
||||
POST_RECOMMEND_COUNT: 6, // 推荐文章数量
|
||||
POSTS_PER_PAGE: 12, // post counts per page
|
||||
POSTS_SORT_BY: process.env.NEXT_PUBLIC_POST_SORT_BY || 'notion', // 排序方式 'date'按时间,'notion'由notion控制
|
||||
|
||||
PREVIEW_CATEGORY_COUNT: 16, // 首页最多展示的分类数量,0为不限制
|
||||
PREVIEW_TAG_COUNT: 16, // 首页最多展示的标签数量,0为不限制
|
||||
|
||||
// 鼠标点击烟花特效
|
||||
FIREWORKS: process.env.NEXT_PUBLIC_FIREWORKS || false, // 开关
|
||||
// 烟花色彩,感谢 https://github.com/Vixcity 提交的色彩
|
||||
FIREWORKS_COLOR: [
|
||||
'255, 20, 97',
|
||||
'24, 255, 146',
|
||||
'90, 135, 255',
|
||||
'251, 243, 140'
|
||||
],
|
||||
|
||||
// 樱花飘落特效
|
||||
SAKURA: process.env.NEXT_PUBLIC_SAKURA || false, // 开关
|
||||
|
||||
// 漂浮线段特效
|
||||
NEST: process.env.NEXT_PUBLIC_NEST || false, // 开关
|
||||
|
||||
// 动态彩带特效
|
||||
FLUTTERINGRIBBON: process.env.NEXT_PUBLIC_FLUTTERINGRIBBON || false, // 开关
|
||||
// 静态彩带特效
|
||||
RIBBON: process.env.NEXT_PUBLIC_RIBBON || false, // 开关
|
||||
|
||||
// 星空雨特效 黑夜模式才会生效
|
||||
STARRY_SKY: process.env.NEXT_PUBLIC_STARRY_SKY || false, // 开关
|
||||
|
||||
// 悬浮挂件
|
||||
WIDGET_PET: process.env.NEXT_PUBLIC_WIDGET_PET || true, // 是否显示宠物挂件
|
||||
WIDGET_PET_LINK:
|
||||
process.env.NEXT_PUBLIC_WIDGET_PET_LINK ||
|
||||
'https://cdn.jsdelivr.net/npm/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json', // 挂件模型地址 @see https://github.com/xiazeyu/live2d-widget-models
|
||||
WIDGET_PET_SWITCH_THEME: true, // 点击宠物挂件切换博客主题
|
||||
|
||||
// 音乐播放插件
|
||||
MUSIC_PLAYER: process.env.NEXT_PUBLIC_MUSIC_PLAYER || false, // 是否使用音乐播放插件
|
||||
MUSIC_PLAYER_VISIBLE: process.env.NEXT_PUBLIC_MUSIC_PLAYER_VISIBLE || true, // 是否在左下角显示播放和切换,如果使用播放器,打开自动播放再隐藏,就会以类似背景音乐的方式播放,无法取消和暂停
|
||||
MUSIC_PLAYER_AUTO_PLAY:
|
||||
process.env.NEXT_PUBLIC_MUSIC_PLAYER_AUTO_PLAY || true, // 是否自动播放,不过自动播放时常不生效(移动设备不支持自动播放)
|
||||
MUSIC_PLAYER_LRC_TYPE: process.env.NEXT_PUBLIC_MUSIC_PLAYER_LRC_TYPE || '0', // 歌词显示类型,可选值: 3 | 1 | 0(0:禁用 lrc 歌词,1:lrc 格式的字符串,3:lrc 文件 url)(前提是有配置歌词路径,对 meting 无效)
|
||||
MUSIC_PLAYER_CDN_URL:
|
||||
process.env.NEXT_PUBLIC_MUSIC_PLAYER_CDN_URL ||
|
||||
'https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.js',
|
||||
MUSIC_PLAYER_ORDER: process.env.NEXT_PUBLIC_MUSIC_PLAYER_ORDER || 'list', // 默认播放方式,顺序 list,随机 random
|
||||
MUSIC_PLAYER_AUDIO_LIST: [
|
||||
// 示例音乐列表。除了以下配置外,还可配置歌词,具体配置项看此文档 https://aplayer.js.org/#/zh-Hans/
|
||||
{
|
||||
name: '风を共に舞う気持ち',
|
||||
artist: 'Falcom Sound Team jdk',
|
||||
url: 'https://music.163.com/song/media/outer/url?id=731419.mp3',
|
||||
cover:
|
||||
'https://p2.music.126.net/kn6ugISTonvqJh3LHLaPtQ==/599233837187278.jpg'
|
||||
},
|
||||
{
|
||||
name: '王都グランセル',
|
||||
artist: 'Falcom Sound Team jdk',
|
||||
url: 'https://music.163.com/song/media/outer/url?id=731355.mp3',
|
||||
cover:
|
||||
'https://p1.music.126.net/kn6ugISTonvqJh3LHLaPtQ==/599233837187278.jpg'
|
||||
}
|
||||
],
|
||||
MUSIC_PLAYER_METING: process.env.NEXT_PUBLIC_MUSIC_PLAYER_METING || false, // 是否要开启 MetingJS,从平台获取歌单。会覆盖自定义的 MUSIC_PLAYER_AUDIO_LIST,更多配置信息:https://github.com/metowolf/MetingJS
|
||||
MUSIC_PLAYER_METING_SERVER:
|
||||
process.env.NEXT_PUBLIC_MUSIC_PLAYER_METING_SERVER || 'netease', // 音乐平台,[netease, tencent, kugou, xiami, baidu]
|
||||
MUSIC_PLAYER_METING_ID:
|
||||
process.env.NEXT_PUBLIC_MUSIC_PLAYER_METING_ID || '60198', // 对应歌单的 id
|
||||
MUSIC_PLAYER_METING_LRC_TYPE:
|
||||
process.env.NEXT_PUBLIC_MUSIC_PLAYER_METING_LRC_TYPE || '1', // 可选值: 3 | 1 | 0(0:禁用 lrc 歌词,1:lrc 格式的字符串,3:lrc 文件 url)
|
||||
|
||||
// ----> 评论互动 可同时开启多个支持 WALINE VALINE GISCUS CUSDIS UTTERRANCES GITALK
|
||||
|
||||
// twikoo
|
||||
COMMENT_TWIKOO_ENV_ID: process.env.NEXT_PUBLIC_COMMENT_ENV_ID || '', // TWIKOO地址 腾讯云环境填 envId;Vercel 环境域名地址(https://xxx.vercel.app)
|
||||
|
||||
// utterance
|
||||
COMMENT_UTTERRANCES_REPO:
|
||||
process.env.NEXT_PUBLIC_COMMENT_UTTERRANCES_REPO || '', // 你的代码仓库名, 例如我是 'tangly1024/NotionNext'; 更多文档参考 https://utteranc.es/
|
||||
|
||||
// giscus @see https://giscus.app/
|
||||
COMMENT_GISCUS_REPO: process.env.NEXT_PUBLIC_COMMENT_GISCUS_REPO || '', // 你的Github仓库名 e.g 'tangly1024/NotionNext'
|
||||
COMMENT_GISCUS_REPO_ID: process.env.NEXT_PUBLIC_COMMENT_GISCUS_REPO_ID || '', // 你的Github Repo ID e.g ( 設定完 giscus 即可看到 )
|
||||
COMMENT_GISCUS_CATEGORY_ID:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GISCUS_CATEGORY_ID || '', // 你的Github Discussions 內的 Category ID ( 設定完 giscus 即可看到 )
|
||||
COMMENT_GISCUS_MAPPING:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GISCUS_MAPPING || 'pathname', // 你的Github Discussions 使用哪種方式來標定文章, 預設 'pathname'
|
||||
COMMENT_GISCUS_REACTIONS_ENABLED:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GISCUS_REACTIONS_ENABLED || '1', // 你的 Giscus 是否開啟文章表情符號 '1' 開啟 "0" 關閉 預設開啟
|
||||
COMMENT_GISCUS_EMIT_METADATA:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GISCUS_EMIT_METADATA || '0', // 你的 Giscus 是否提取 Metadata '1' 開啟 '0' 關閉 預設關閉
|
||||
COMMENT_GISCUS_INPUT_POSITION:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GISCUS_INPUT_POSITION || 'bottom', // 你的 Giscus 發表留言位置 'bottom' 尾部 'top' 頂部, 預設 'bottom'
|
||||
COMMENT_GISCUS_LANG: process.env.NEXT_PUBLIC_COMMENT_GISCUS_LANG || 'zh-CN', // 你的 Giscus 語言 e.g 'en', 'zh-TW', 'zh-CN', 預設 'en'
|
||||
COMMENT_GISCUS_LOADING:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GISCUS_LOADING || 'lazy', // 你的 Giscus 載入是否漸進式載入, 預設 'lazy'
|
||||
COMMENT_GISCUS_CROSSORIGIN:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GISCUS_CROSSORIGIN || 'anonymous', // 你的 Giscus 可以跨網域, 預設 'anonymous'
|
||||
|
||||
COMMENT_CUSDIS_APP_ID: process.env.NEXT_PUBLIC_COMMENT_CUSDIS_APP_ID || '', // data-app-id 36位 see https://cusdis.com/
|
||||
COMMENT_CUSDIS_HOST:
|
||||
process.env.NEXT_PUBLIC_COMMENT_CUSDIS_HOST || 'https://cusdis.com', // data-host, change this if you're using self-hosted version
|
||||
COMMENT_CUSDIS_SCRIPT_SRC:
|
||||
process.env.NEXT_PUBLIC_COMMENT_CUSDIS_SCRIPT_SRC ||
|
||||
'https://cusdis.com/js/cusdis.es.js', // change this if you're using self-hosted version
|
||||
|
||||
// gitalk评论插件 更多参考 https://gitalk.github.io/
|
||||
COMMENT_GITALK_REPO: process.env.NEXT_PUBLIC_COMMENT_GITALK_REPO || '', // 你的Github仓库名,例如 'NotionNext'
|
||||
COMMENT_GITALK_OWNER: process.env.NEXT_PUBLIC_COMMENT_GITALK_OWNER || '', // 你的用户名 e.g tangly1024
|
||||
COMMENT_GITALK_ADMIN: process.env.NEXT_PUBLIC_COMMENT_GITALK_ADMIN || '', // 管理员用户名、一般是自己 e.g 'tangly1024'
|
||||
COMMENT_GITALK_CLIENT_ID:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GITALK_CLIENT_ID || '', // e.g 20位ID , 在gitalk后台获取
|
||||
COMMENT_GITALK_CLIENT_SECRET:
|
||||
process.env.NEXT_PUBLIC_COMMENT_GITALK_CLIENT_SECRET || '', // e.g 40位ID, 在gitalk后台获取
|
||||
COMMENT_GITALK_DISTRACTION_FREE_MODE: false, // 类似facebook的无干扰模式
|
||||
|
||||
COMMENT_GITTER_ROOM: process.env.NEXT_PUBLIC_COMMENT_GITTER_ROOM || '', // gitter聊天室 see https://gitter.im/ 不需要则留空
|
||||
COMMENT_DAO_VOICE_ID: process.env.NEXT_PUBLIC_COMMENT_DAO_VOICE_ID || '', // DaoVoice http://dashboard.daovoice.io/get-started
|
||||
COMMENT_TIDIO_ID: process.env.NEXT_PUBLIC_COMMENT_TIDIO_ID || '', // [tidio_id] -> //code.tidio.co/[tidio_id].js
|
||||
|
||||
COMMENT_VALINE_APP_ID: process.env.NEXT_PUBLIC_VALINE_ID || '', // Valine @see https://valine.js.org/quickstart.html 或 https://github.com/stonehank/react-valine#%E8%8E%B7%E5%8F%96app-id-%E5%92%8C-app-key
|
||||
COMMENT_VALINE_APP_KEY: process.env.NEXT_PUBLIC_VALINE_KEY || '',
|
||||
COMMENT_VALINE_SERVER_URLS: process.env.NEXT_PUBLIC_VALINE_SERVER_URLS || '', // 该配置适用于国内自定义域名用户, 海外版本会自动检测(无需手动填写) @see https://valine.js.org/configuration.html#serverURLs
|
||||
COMMENT_VALINE_PLACEHOLDER:
|
||||
process.env.NEXT_PUBLIC_VALINE_PLACEHOLDER || '抢个沙发吧~', // 可以搭配后台管理评论 https://github.com/DesertsP/Valine-Admin 便于查看评论,以及邮件通知,垃圾评论过滤等功能
|
||||
|
||||
COMMENT_WALINE_SERVER_URL: process.env.NEXT_PUBLIC_WALINE_SERVER_URL || '', // 请配置完整的Waline评论地址 例如 hhttps://preview-waline.tangly1024.com @see https://waline.js.org/guide/get-started.html
|
||||
COMMENT_WALINE_RECENT: process.env.NEXT_PUBLIC_WALINE_RECENT || false, // 最新评论
|
||||
|
||||
// 此评论系统基于WebMention,细节可参考https://webmention.io
|
||||
// 它是一个基于IndieWeb理念的开放式评论系统,下方COMMENT_WEBMENTION包含的属性皆需配置:
|
||||
// ENABLE: 是否开启
|
||||
// AUTH: Webmention使用的IndieLogin,可使用Twitter或Github个人页面连结
|
||||
// HOSTNAME: Webmention绑定之网域,通常即为本站网址
|
||||
// TWITTER_USERNAME: 评论显示区域需要的资讯
|
||||
// TOKEN: Webmention的API token
|
||||
COMMENT_WEBMENTION: {
|
||||
ENABLE: process.env.NEXT_PUBLIC_WEBMENTION_ENABLE || false,
|
||||
AUTH: process.env.NEXT_PUBLIC_WEBMENTION_AUTH || '',
|
||||
HOSTNAME: process.env.NEXT_PUBLIC_WEBMENTION_HOSTNAME || '',
|
||||
TWITTER_USERNAME: process.env.NEXT_PUBLIC_TWITTER_USERNAME || '',
|
||||
TOKEN: process.env.NEXT_PUBLIC_WEBMENTION_TOKEN || ''
|
||||
},
|
||||
|
||||
// <---- 评论插件
|
||||
|
||||
// ----> 站点统计
|
||||
ANALYTICS_VERCEL: process.env.NEXT_PUBLIC_ANALYTICS_VERCEL || true, // vercel自带的统计 https://vercel.com/docs/concepts/analytics/quickstart https://github.com/tangly1024/NotionNext/issues/897
|
||||
ANALYTICS_BUSUANZI_ENABLE: true, // 展示网站阅读量、访问数 see http://busuanzi.ibruce.info/
|
||||
ANALYTICS_BAIDU_ID: process.env.NEXT_PUBLIC_ANALYTICS_BAIDU_ID || '', // e.g 只需要填写百度统计的id,[baidu_id] -> https://hm.baidu.com/hm.js?[baidu_id]
|
||||
ANALYTICS_CNZZ_ID: process.env.NEXT_PUBLIC_ANALYTICS_CNZZ_ID || '', // 只需要填写站长统计的id, [cnzz_id] -> https://s9.cnzz.com/z_stat.php?id=[cnzz_id]&web_id=[cnzz_id]
|
||||
ANALYTICS_GOOGLE_ID: process.env.NEXT_PUBLIC_ANALYTICS_GOOGLE_ID || '', // 谷歌Analytics的id e.g: G-XXXXXXXXXX
|
||||
|
||||
ANALYTICS_ACKEE_TRACKER:
|
||||
process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_TRACKER || '', // e.g 'https://ackee.tangly1024.net/tracker.js'
|
||||
ANALYTICS_ACKEE_DATA_SERVER:
|
||||
process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DATA_SERVER || '', // e.g https://ackee.tangly1024.net , don't end with a slash
|
||||
ANALYTICS_ACKEE_DOMAIN_ID:
|
||||
process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DOMAIN_ID || '', // e.g '0e2257a8-54d4-4847-91a1-0311ea48cc7b'
|
||||
|
||||
SEO_GOOGLE_SITE_VERIFICATION:
|
||||
process.env.NEXT_PUBLIC_SEO_GOOGLE_SITE_VERIFICATION || '', // Remove the value or replace it with your own google site verification code
|
||||
|
||||
// <---- 站点统计
|
||||
|
||||
// 谷歌广告
|
||||
ADSENSE_GOOGLE_ID: process.env.NEXT_PUBLIC_ADSENSE_GOOGLE_ID || '', // 谷歌广告ID e.g ca-pub-xxxxxxxxxxxxxxxx
|
||||
|
||||
// 自定义配置notion数据库字段名
|
||||
NOTION_PROPERTY_NAME: {
|
||||
password: process.env.NEXT_PUBLIC_NOTION_PROPERTY_PASSWORD || 'password',
|
||||
type: process.env.NEXT_PUBLIC_NOTION_PROPERTY_TYPE || 'type', // 文章类型,
|
||||
type_post: process.env.NEXT_PUBLIC_NOTION_PROPERTY_TYPE_POST || 'Post', // 当type文章类型与此值相同时,为博文。
|
||||
type_page: process.env.NEXT_PUBLIC_NOTION_PROPERTY_TYPE_PAGE || 'Page', // 当type文章类型与此值相同时,为单页。
|
||||
type_notice:
|
||||
process.env.NEXT_PUBLIC_NOTION_PROPERTY_TYPE_NOTICE || 'Notice', // 当type文章类型与此值相同时,为公告。
|
||||
type_menu: process.env.NEXT_PUBLIC_NOTION_PROPERTY_TYPE_MENU || 'Menu', // 当type文章类型与此值相同时,为菜单。
|
||||
type_sub_menu:
|
||||
process.env.NEXT_PUBLIC_NOTION_PROPERTY_TYPE_SUB_MENU || 'SubMenu', // 当type文章类型与此值相同时,为子菜单。
|
||||
title: process.env.NEXT_PUBLIC_NOTION_PROPERTY_TITLE || 'title', // 文章标题
|
||||
status: process.env.NEXT_PUBLIC_NOTION_PROPERTY_STATUS || 'status',
|
||||
status_publish:
|
||||
process.env.NEXT_PUBLIC_NOTION_PROPERTY_STATUS_PUBLISH || 'Published', // 当status状态值与此相同时为发布,可以为中文
|
||||
status_invisible:
|
||||
process.env.NEXT_PUBLIC_NOTION_PROPERTY_STATUS_INVISIBLE || 'Invisible', // 当status状态值与此相同时为隐藏发布,可以为中文 , 除此之外其他页面状态不会显示在博客上
|
||||
summary: process.env.NEXT_PUBLIC_NOTION_PROPERTY_SUMMARY || 'summary',
|
||||
slug: process.env.NEXT_PUBLIC_NOTION_PROPERTY_SLUG || 'slug',
|
||||
category: process.env.NEXT_PUBLIC_NOTION_PROPERTY_CATEGORY || 'category',
|
||||
date: process.env.NEXT_PUBLIC_NOTION_PROPERTY_DATE || 'date',
|
||||
tags: process.env.NEXT_PUBLIC_NOTION_PROPERTY_TAGS || 'tags',
|
||||
icon: process.env.NEXT_PUBLIC_NOTION_PROPERTY_ICON || 'icon'
|
||||
},
|
||||
|
||||
// RSS
|
||||
ENABLE_RSS: process.env.NEXT_PUBLIC_ENABLE_RSS || true, // 是否开启RSS订阅功能
|
||||
|
||||
// 作废配置
|
||||
AVATAR: process.env.NEXT_PUBLIC_AVATAR || '/avatar.svg', // 作者头像,被notion中的ICON覆盖。若无ICON则取public目录下的avatar.png
|
||||
TITLE: process.env.NEXT_PUBLIC_TITLE || 'NotionNext BLOG', // 站点标题 ,被notion中的页面标题覆盖
|
||||
HOME_BANNER_IMAGE:
|
||||
process.env.NEXT_PUBLIC_HOME_BANNER_IMAGE || './bg_image.jpg', // 首页背景大图, 会被notion中的封面图覆盖,若无封面图则会使用代码中的 /public/bg_image.jpg 文件
|
||||
DESCRIPTION:
|
||||
process.env.NEXT_PUBLIC_DESCRIPTION || '这是一个由NotionNext生成的站点', // 站点描述,被notion中的页面描述覆盖
|
||||
|
||||
// 网站图片
|
||||
IMG_URL_TYPE: process.env.NEXT_PUBLIC_IMG_TYPE || 'Notion', // 此配置已失效,请勿使用;AMAZON方案不再支持,仅支持Notion方案。 ['Notion','AMAZON'] 站点图片前缀 默认 Notion:(https://notion.so/images/xx) , AMAZON(https://s3.us-west-2.amazonaws.com/xxx)
|
||||
IMG_SHADOW: process.env.NEXT_PUBLIC_IMG_SHADOW || false, // 文章图片是否自动添加阴影
|
||||
|
||||
// 开发相关
|
||||
NOTION_ACCESS_TOKEN: process.env.NOTION_ACCESS_TOKEN || '', // Useful if you prefer not to make your database public
|
||||
DEBUG: process.env.NEXT_PUBLIC_DEBUG || false, // 是否显示调试按钮
|
||||
ENABLE_CACHE: process.env.ENABLE_CACHE || false, // 开启缓存会将Notion数据缓存在内存中,通常在开发调试中使用,正式部署开启此功能意义不大。
|
||||
isProd: process.env.VERCEL_ENV === 'production', // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
|
||||
VERSION: process.env.NEXT_PUBLIC_VERSION // 版本号
|
||||
}
|
||||
|
||||
module.exports = BLOG
|
||||
25
themes/example/index.js
Normal file
25
themes/example/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_EXAMPLE from './config_example'
|
||||
import LayoutIndex from './LayoutIndex'
|
||||
import LayoutSearch from './LayoutSearch'
|
||||
import LayoutArchive from './LayoutArchive'
|
||||
import LayoutSlug from './LayoutSlug'
|
||||
import Layout404 from './Layout404'
|
||||
import LayoutCategory from './LayoutCategory'
|
||||
import LayoutCategoryIndex from './LayoutCategoryIndex'
|
||||
import LayoutPage from './LayoutPage'
|
||||
import LayoutTag from './LayoutTag'
|
||||
import LayoutTagIndex from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_EXAMPLE as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
25
themes/fukasawa/index.js
Normal file
25
themes/fukasawa/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_FUKA from './config_fuka'
|
||||
import { LayoutIndex } from './LayoutIndex'
|
||||
import { LayoutSearch } from './LayoutSearch'
|
||||
import { LayoutArchive } from './LayoutArchive'
|
||||
import { LayoutSlug } from './LayoutSlug'
|
||||
import { Layout404 } from './Layout404'
|
||||
import { LayoutCategory } from './LayoutCategory'
|
||||
import { LayoutCategoryIndex } from './LayoutCategoryIndex'
|
||||
import { LayoutPage } from './LayoutPage'
|
||||
import { LayoutTag } from './LayoutTag'
|
||||
import { LayoutTagIndex } from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_FUKA as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { saveDarkModeToCookies } from '@/lib/theme'
|
||||
import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
import CONFIG_HEXO from '../config_hexo'
|
||||
|
||||
export default function FloatDarkModeButton () {
|
||||
|
||||
25
themes/hexo/index.js
Normal file
25
themes/hexo/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_HEXO from './config_hexo'
|
||||
import { LayoutIndex } from './LayoutIndex'
|
||||
import { LayoutSearch } from './LayoutSearch'
|
||||
import { LayoutArchive } from './LayoutArchive'
|
||||
import { LayoutSlug } from './LayoutSlug'
|
||||
import { Layout404 } from './Layout404'
|
||||
import { LayoutCategory } from './LayoutCategory'
|
||||
import { LayoutCategoryIndex } from './LayoutCategoryIndex'
|
||||
import { LayoutPage } from './LayoutPage'
|
||||
import { LayoutTag } from './LayoutTag'
|
||||
import { LayoutTagIndex } from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_HEXO as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { saveDarkModeToCookies } from '@/lib/theme'
|
||||
import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
import CONFIG_MATERY from '../config_matery'
|
||||
|
||||
export default function FloatDarkModeButton() {
|
||||
|
||||
25
themes/matery/indexj.js
Normal file
25
themes/matery/indexj.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_MATERY from './config_matery'
|
||||
import { LayoutIndex } from './LayoutIndex'
|
||||
import { LayoutSearch } from './LayoutSearch'
|
||||
import { LayoutArchive } from './LayoutArchive'
|
||||
import { LayoutSlug } from './LayoutSlug'
|
||||
import { Layout404 } from './Layout404'
|
||||
import { LayoutCategory } from './LayoutCategory'
|
||||
import { LayoutCategoryIndex } from './LayoutCategoryIndex'
|
||||
import { LayoutPage } from './LayoutPage'
|
||||
import { LayoutTag } from './LayoutTag'
|
||||
import { LayoutTagIndex } from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_MATERY as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
25
themes/medium/index.js
Normal file
25
themes/medium/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_MEDIUM from './config_medium'
|
||||
import { LayoutIndex } from './LayoutIndex'
|
||||
import { LayoutSearch } from './LayoutSearch'
|
||||
import { LayoutArchive } from './LayoutArchive'
|
||||
import { LayoutSlug } from './LayoutSlug'
|
||||
import { Layout404 } from './Layout404'
|
||||
import { LayoutCategory } from './LayoutCategory'
|
||||
import { LayoutCategoryIndex } from './LayoutCategoryIndex'
|
||||
import { LayoutPage } from './LayoutPage'
|
||||
import { LayoutTag } from './LayoutTag'
|
||||
import { LayoutTagIndex } from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_MEDIUM as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { saveDarkModeToCookies } from '@/lib/theme'
|
||||
import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
|
||||
const DarkModeButton = () => {
|
||||
const { isDarkMode, updateDarkMode } = useGlobal()
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { saveDarkModeToCookies } from '@/lib/theme'
|
||||
import { saveDarkModeToCookies } from '@/themes/theme'
|
||||
import CONFIG_NEXT from '../config_next'
|
||||
|
||||
export default function FloatDarkModeButton () {
|
||||
const { isDarkMode, updateDarkMode } = useGlobal()
|
||||
|
||||
if (!CONFIG_NEXT.WIDGET_DARK_MODE) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
const { isDarkMode, updateDarkMode } = useGlobal()
|
||||
// 用户手动设置主题
|
||||
const handleChangeDarkMode = () => {
|
||||
const newStatus = !isDarkMode
|
||||
|
||||
25
themes/next/index.js
Normal file
25
themes/next/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_NEXT from './config_next'
|
||||
import { LayoutIndex } from './LayoutIndex'
|
||||
import { LayoutSearch } from './LayoutSearch'
|
||||
import { LayoutArchive } from './LayoutArchive'
|
||||
import { LayoutSlug } from './LayoutSlug'
|
||||
import { Layout404 } from './Layout404'
|
||||
import { LayoutCategory } from './LayoutCategory'
|
||||
import { LayoutCategoryIndex } from './LayoutCategoryIndex'
|
||||
import { LayoutPage } from './LayoutPage'
|
||||
import { LayoutTag } from './LayoutTag'
|
||||
import { LayoutTagIndex } from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_NEXT as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
@@ -19,7 +19,7 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => {
|
||||
const key = searchInputRef.current.value
|
||||
if (key && key !== '') {
|
||||
router.push({ pathname: '/search/' + key }).then(r => {
|
||||
console.log('搜索', key)
|
||||
// console.log('搜索', key)
|
||||
})
|
||||
} else {
|
||||
router.push({ pathname: '/' }).then(r => {
|
||||
|
||||
25
themes/nobelium/index.js
Normal file
25
themes/nobelium/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_NOBELIUM from './config_nobelium'
|
||||
import { LayoutIndex } from './LayoutIndex'
|
||||
import { LayoutSearch } from './LayoutSearch'
|
||||
import { LayoutArchive } from './LayoutArchive'
|
||||
import { LayoutSlug } from './LayoutSlug'
|
||||
import { Layout404 } from './Layout404'
|
||||
import { LayoutCategory } from './LayoutCategory'
|
||||
import { LayoutCategoryIndex } from './LayoutCategoryIndex'
|
||||
import { LayoutPage } from './LayoutPage'
|
||||
import { LayoutTag } from './LayoutTag'
|
||||
import { LayoutTagIndex } from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_NOBELIUM as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
25
themes/simple/index.js
Normal file
25
themes/simple/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import CONFIG_SIMPLE from './config_simple'
|
||||
import { LayoutIndex } from './LayoutIndex'
|
||||
import { LayoutSearch } from './LayoutSearch'
|
||||
import { LayoutArchive } from './LayoutArchive'
|
||||
import { LayoutSlug } from './LayoutSlug'
|
||||
import { Layout404 } from './Layout404'
|
||||
import { LayoutCategory } from './LayoutCategory'
|
||||
import { LayoutCategoryIndex } from './LayoutCategoryIndex'
|
||||
import { LayoutPage } from './LayoutPage'
|
||||
import { LayoutTag } from './LayoutTag'
|
||||
import { LayoutTagIndex } from './LayoutTagIndex'
|
||||
|
||||
export {
|
||||
CONFIG_SIMPLE as THEME_CONFIG,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategory,
|
||||
LayoutCategoryIndex,
|
||||
LayoutPage,
|
||||
LayoutTag,
|
||||
LayoutTagIndex
|
||||
}
|
||||
@@ -1,21 +1,71 @@
|
||||
import cookie from 'react-cookies'
|
||||
import BLOG from '@/blog.config'
|
||||
import { isBrowser, getQueryVariable } from './utils'
|
||||
|
||||
import { getQueryParam, getQueryVariable } from '../lib/utils'
|
||||
import dynamic from 'next/dynamic'
|
||||
// 使用 __THEME__ 变量来动态导入主题组件
|
||||
import * as ThemeComponents from '@theme-components'
|
||||
/**
|
||||
* 所有主题枚举
|
||||
*/
|
||||
export const ALL_THEME = [
|
||||
'hexo',
|
||||
'matery',
|
||||
'next',
|
||||
'medium',
|
||||
'fukasawa',
|
||||
'nobelium',
|
||||
'example',
|
||||
'simple'
|
||||
'hexo', 'matery', 'next', 'medium', 'fukasawa', 'nobelium', 'example', 'simple'
|
||||
]
|
||||
|
||||
/**
|
||||
* 加载主题文件
|
||||
* 如果是
|
||||
* @param {*} router
|
||||
* @returns
|
||||
*/
|
||||
export const getLayoutByTheme = (router) => {
|
||||
const theme = getQueryParam(router.asPath, 'theme') || BLOG.THEME
|
||||
const layout = getLayoutNameByPath(router.pathname)
|
||||
if (theme !== BLOG.THEME) {
|
||||
return dynamic(() => import(`@/themes/${theme}/${layout}`), { ssr: true })
|
||||
} else {
|
||||
console.log('静态主题', layout)
|
||||
return ThemeComponents[layout]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 路径 对应的Layout名称
|
||||
* @param {*} path
|
||||
* @returns
|
||||
*/
|
||||
export const getLayoutNameByPath = (path) => {
|
||||
switch (path) {
|
||||
case '/':
|
||||
return 'LayoutIndex'
|
||||
case '/page/[page]':
|
||||
return 'LayoutPage'
|
||||
case '/archive':
|
||||
return 'LayoutArchive'
|
||||
case '/search':
|
||||
return 'LayoutSearch'
|
||||
case '/search/[keyword]':
|
||||
return 'LayoutSearch'
|
||||
case '/search/[keyword]/page/[page]':
|
||||
return 'LayoutSearch'
|
||||
case '/404':
|
||||
return 'Layout404'
|
||||
case '/tag':
|
||||
return 'LayoutTagIndex'
|
||||
case '/tag/[tag]':
|
||||
return 'LayoutTag'
|
||||
case '/tag/[tag]/page/[page]':
|
||||
return 'LayoutTag'
|
||||
case '/category':
|
||||
return 'LayoutCategoryIndex'
|
||||
case '/category/[category]':
|
||||
return 'LayoutCategory'
|
||||
case '/category/[category]/page/[page]':
|
||||
return 'LayoutCategory'
|
||||
default:
|
||||
return 'LayoutSlug'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化主题 , 优先级 query > cookies > systemPrefer
|
||||
* @param isDarkMode
|
||||
@@ -34,24 +84,6 @@ export const initDarkMode = (isDarkMode, updateDarkMode) => {
|
||||
document.getElementsByTagName('html')[0].setAttribute('class', isDarkMode ? 'dark' : 'light')
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化主题, 优先级 query > cookies > blog.config.js
|
||||
* @param {*} theme
|
||||
* @param {*} changeTheme
|
||||
*/
|
||||
export const initTheme = (theme, changeTheme) => {
|
||||
if (isBrowser()) {
|
||||
// const queryTheme = getQueryVariable('theme') || loadThemeFromCookies() || BLOG.THEME
|
||||
const queryTheme = getQueryVariable('theme') || BLOG.THEME
|
||||
let currentTheme = theme
|
||||
if (queryTheme !== theme && ALL_THEME.indexOf(queryTheme) > -1) {
|
||||
currentTheme = queryTheme
|
||||
}
|
||||
changeTheme(currentTheme)
|
||||
saveThemeToCookies(currentTheme)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否优先深色模式, 根据系统深色模式以及当前时间判断
|
||||
* @returns {*}
|
||||
Reference in New Issue
Block a user