mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 15:09:13 +00:00
feature: 配置文件整理
This commit is contained in:
175
blog.config.js
175
blog.config.js
@@ -1,73 +1,108 @@
|
||||
const BLOG = {
|
||||
title: '小唐笔记', // 站点标题
|
||||
description: '分享编程技术与记录生活', // 站点描述
|
||||
author: 'tangly1024', // 作者
|
||||
bio: '一个普通的干饭人🍚', // 作者简介
|
||||
email: 'tlyong1992@hotmail.com', // 联系邮箱
|
||||
link: 'https://tangly1024.com', // 网站地址
|
||||
keywords: ['Notion', '写作', '博客'], // 网站关键词
|
||||
lang: 'zh-CN', // ['zh-CN','en-US'] default lang => see /lib/lang.js for more.
|
||||
beian: '闽ICP备20010331号', // 备案号
|
||||
notionPageId: process.env.NOTION_PAGE_ID || 'bee1fccfa3bd47a1a7be83cc71372d83', // Important page_id!!!
|
||||
notionAccessToken: process.env.NOTION_ACCESS_TOKEN || '', // Useful if you prefer not to make your database public
|
||||
appearance: 'auto', // ['light', 'dark', 'auto'],
|
||||
font: 'font-serif tracking-wider subpixel-antialiased', // 文章字体 ['font-sans', 'font-serif', 'font-mono'] @see https://www.tailwindcss.cn/docs/font-family
|
||||
lightBackground: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc
|
||||
darkBackground: '#111827', // use hex value, don't forget '#'
|
||||
path: '', // leave this empty unless you want to deploy in a folder
|
||||
since: 2020, // if leave this empty, current year will be used.
|
||||
postListStyle: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
|
||||
postsPerPage: 6, // post counts per page
|
||||
previewLines: 12, // 预览博客行数
|
||||
sortByDate: false,
|
||||
socialLink: { // 社交链接,如不需要展示可以留空白,例如 weibo:''
|
||||
weibo: 'https://weibo.com/tangly1024',
|
||||
twitter: 'https://twitter.com/troy1024_1',
|
||||
github: 'https://github.com/tangly1024',
|
||||
telegram: 'https://t.me/tangly_1024'
|
||||
},
|
||||
comment: { // 评论插件,支持 gitalk, utterances, cusdis
|
||||
provider: 'gitalk', // 不需要则留空白
|
||||
gitalkConfig: {
|
||||
repo: 'NotionNext', // The repository of store comments
|
||||
owner: 'tangly1024',
|
||||
admin: ['tangly1024'],
|
||||
clientID: process.env.GITALK_ID || 'be7864a16b693e256f8f',
|
||||
clientSecret: process.env.GITALK_SECRET || 'dbd0f6d9ceea8940f6ed20936b415274b8fe66a2',
|
||||
distractionFreeMode: false
|
||||
},
|
||||
cusdisConfig: {
|
||||
appId: '445ba48e-f751-487f-b22f-cdbe3310d28f', // data-app-id
|
||||
host: 'https://cusdis.com', // data-host, change this if you're using self-hosted version
|
||||
scriptSrc: 'https://cusdis.com/js/cusdis.es.js' // change this if you're using self-hosted version
|
||||
},
|
||||
utterancesConfig: {
|
||||
repo: 'tangly1024/NotionNext'
|
||||
},
|
||||
gitter: '', // gitter聊天室
|
||||
DaoVoiceId: '', // DaoVoice http://dashboard.daovoice.io/get-started
|
||||
TidioId: '' // https://www.tidio.com/
|
||||
},
|
||||
// --- 高级设置
|
||||
analytics: { // 文章访问量统计
|
||||
busuanzi: true, // 展示网站阅读量、访问数 see http://busuanzi.ibruce.info/
|
||||
provider: 'ga', // 支持 Google Analytics and Ackee, please fill with 'ga' or 'ackee', leave it empty to disable it.
|
||||
baiduAnalytics: 'f683ef76f06bb187cbed5546f6f28f28', // e.g only need xxxxx -> https://hm.baidu.com/hm.js?[xxxxx]
|
||||
cnzzAnalytics: '', // 站长统计id only need xxxxxxxx -> https://s9.cnzz.com/z_stat.php?id=[xxxxxxxx]&web_id=[xxxxxxx]
|
||||
gaConfig: {
|
||||
measurementId: 'G-68EK0W049N' // e.g: G-XXXXXXXXXX
|
||||
},
|
||||
ackeeConfig: {
|
||||
tracker: '', // e.g 'https://ackee.tangly1024.net/tracker.js'
|
||||
dataAckeeServer: '', // e.g https://ackee.tangly1024.net , don't end with a slash
|
||||
domainId: '' // e.g '0e2257a8-54d4-4847-91a1-0311ea48cc7b'
|
||||
}
|
||||
},
|
||||
seo: {
|
||||
googleSiteVerification: '' // Remove the value or replace it with your own google site verification code
|
||||
},
|
||||
googleAdsenseId: 'ca-pub-2708419466378217', // 谷歌广告ID
|
||||
// 注: 配置文件可以读取Vercel的环境变量,配置方式参考:https://docs.tangly1024.com/zh/features/personality
|
||||
const BLOG = mergeDeep(process.env, {
|
||||
TITLE: 'NotionNext BLOG', // 站点标题
|
||||
DESCRIPTION: '这是一个由NotionNext生成的站点', // 站点描述
|
||||
AUTHOR: 'tangly1024', // 作者
|
||||
BIO: '一个普通的干饭人🍚', // 作者简介
|
||||
LINK: 'https://tangly1024.com', // 网站地址
|
||||
NOTION_PAGE_ID: '02ab3b8678004aa69e9e415905ef32a5', // Important page_id!!!Duplicate Template from https://www.notion.so/tanghh/02ab3b8678004aa69e9e415905ef32a5
|
||||
NOTION_ACCESS_TOKEN: '', // Useful if you prefer not to make your database public
|
||||
KEYWORDS: 'Notion, 博客', // 网站关键词 英文逗号隔开
|
||||
LANG: 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more.
|
||||
BEI_AN: '', // 备案号 闽ICP备XXXXXXX
|
||||
SINCE: 2020, // if leave this empty, current year will be used.
|
||||
|
||||
APPEARANCE: 'auto', // ['light', 'dark', 'auto'],
|
||||
FONT: 'font-serif tracking-wider subpixel-antialiased', // 文章字体 ['font-sans', 'font-serif', 'font-mono'] @see https://www.tailwindcss.cn/docs/font-family
|
||||
BACKGROUND_LIGHT: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc
|
||||
BACKGROUND_DARK: '#111827', // use hex value, don't forget '#'
|
||||
PATH: '', // leave this empty unless you want to deploy in a folder
|
||||
|
||||
POST_LIST_STYLE: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
|
||||
POST_PREVIEW_LINES: 12, // 预览博客行数
|
||||
POSTS_PER_PAGE: 6, // post counts per page
|
||||
POSTS_SORT_BY_DATE: false, // 是否强制按时间排序,否则默认由notion排序文章
|
||||
|
||||
// 社交链接,不需要可留空白,例如 CONTACT_WEIBO:''
|
||||
CONTACT_EMAIL: 'tlyong1992@hotmail.com', // 联系邮箱
|
||||
CONTACT_WEIBO: 'https://weibo.com/tangly1024',
|
||||
CONTACT_TWITTER: 'https://twitter.com/troy1024_1',
|
||||
CONTACT_GITHUB: 'https://github.com/tangly1024',
|
||||
CONTACT_TELEGRAM: 'https://t.me/tangly_1024',
|
||||
|
||||
COMMENT_PROVIDER: '', // 支持 gitalk, utterances, cusdis
|
||||
|
||||
COMMENT_GITALK_REPO: '', // e.g NotionNext
|
||||
COMMENT_GITALK_OWNER: '', // e.g tangly1024
|
||||
COMMENT_GITALK_ADMIN: '', // e.g 'tangly1024'
|
||||
COMMENT_GITALK_CLIENT_ID: '',
|
||||
COMMENT_GITALK_CLIENT_SECRET: '',
|
||||
COMMENT_GITALK_DISTRACTION_FREE_MODE: false,
|
||||
|
||||
COMMENT_CUSDIS_APP_ID: '', // data-app-id
|
||||
COMMENT_CUSDIS_HOST: 'https://cusdis.com', // data-host, change this if you're using self-hosted version
|
||||
COMMENT_CUSDIS_SCRIPT_SRC: 'https://cusdis.com/js/cusdis.es.js', // change this if you're using self-hosted version
|
||||
|
||||
COMMENT_UTTERRANCES_REPO: '', // e.g 'tangly1024/NotionNext'
|
||||
|
||||
COMMENT_GITTER_ENABLE: false, // gitter see https://gitter.im/
|
||||
COMMENT_GITTER_ROOM: '', // gitter聊天室
|
||||
|
||||
COMMENT_DAO_VOICE_ENABLE: false, // DaoVoice see http://dashboard.daovoice.io/get-started
|
||||
COMMENT_DAO_VOICE_ID: '', // DaoVoice http://dashboard.daovoice.io/get-started
|
||||
|
||||
COMMENT_TIDIO_ENABLE: false, // https://www.tidio.com/
|
||||
COMMENT_TIDIO_ID: '', // [tidio_id] -> //code.tidio.co/[tidio_id].js
|
||||
|
||||
// 站点统计
|
||||
|
||||
ANALYTICS_BUSUANZI_ENABLE: true, // 展示网站阅读量、访问数 see http://busuanzi.ibruce.info/
|
||||
|
||||
ANALYTICS_BAIDU_ENABLE: false,
|
||||
ANALYTICS_BAIDU_ID: '', // e.g 只需要填写百度统计的id,[baidu_id] -> https://hm.baidu.com/hm.js?[baidu_id]
|
||||
|
||||
ANALYTICS_CNZZ_ENABLE: false,
|
||||
ANALYTICS_CNZZ_ID: '', // 只需要填写站长统计的id, [cnzz_id] -> https://s9.cnzz.com/z_stat.php?id=[cnzz_id]&web_id=[cnzz_id]
|
||||
|
||||
ANALYTICS_GOOGLE_ENABLE: false,
|
||||
ANALYTICS_GOOGLE_ID: '', // 谷歌Analytics的id e.g: G-XXXXXXXXXX
|
||||
|
||||
ANALYTICS_ACKEE_ENABLE: false,
|
||||
ANALYTICS_ACKEE_TRACKER: '', // e.g 'https://ackee.tangly1024.net/tracker.js'
|
||||
ANALYTICS_ACKEE_DATA_SERVER: '', // e.g https://ackee.tangly1024.net , don't end with a slash
|
||||
ANALYTICS_ACKEE_DOMAIN_ID: '', // e.g '0e2257a8-54d4-4847-91a1-0311ea48cc7b'
|
||||
|
||||
SEO_GOOGLE_SITE_VERIFICATION: '', // Remove the value or replace it with your own google site verification code
|
||||
|
||||
GOOGLE_ADSENSE_ENABLE: false,
|
||||
GOOGLE_ADSENSE_ID: process.env.GOOGLE_AD_ID, // 谷歌广告ID
|
||||
isProd: process.env.VERCEL_ENV === 'production'// distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
|
||||
})
|
||||
|
||||
/**
|
||||
* 深度合并两个对象
|
||||
* @param target
|
||||
* @param sources
|
||||
*/
|
||||
function mergeDeep (target, ...sources) {
|
||||
if (!sources.length) return target
|
||||
const source = sources.shift()
|
||||
|
||||
if (isObject(target) && isObject(source)) {
|
||||
for (const key in source) {
|
||||
if (isObject(source[key])) {
|
||||
if (!target[key]) Object.assign(target, { [key]: {} })
|
||||
mergeDeep(target[key], source[key])
|
||||
} else {
|
||||
Object.assign(target, { [key]: source[key] })
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergeDeep(target, ...sources)
|
||||
}
|
||||
// export default BLOG
|
||||
|
||||
function isObject (item) {
|
||||
return (item && typeof item === 'object' && !Array.isArray(item))
|
||||
}
|
||||
|
||||
module.exports = BLOG
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import useAckee from 'use-ackee'
|
||||
import BLOG from '@/blog.config'
|
||||
|
||||
const Ackee = ({ ackeeServerUrl, ackeeDomainId }) => {
|
||||
const Ackee = () => {
|
||||
const ackeeServerUrl = BLOG.ANALYTICS_ACKEE_DATA_SERVER
|
||||
const ackeeDomainId = BLOG.ANALYTICS_ACKEE_DOMAIN_ID
|
||||
const router = useRouter()
|
||||
useAckee(
|
||||
router.asPath,
|
||||
{ server: ackeeServerUrl, domainId: ackeeDomainId },
|
||||
{ detailed: false, ignoreLocalhost: true }
|
||||
{
|
||||
server: ackeeServerUrl,
|
||||
domainId: ackeeDomainId
|
||||
},
|
||||
{
|
||||
detailed: false,
|
||||
ignoreLocalhost: true
|
||||
}
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import dynamic from 'next/dynamic'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import 'gitalk/dist/gitalk.css'
|
||||
import Tabs from '@/components/Tabs'
|
||||
|
||||
const GitalkComponent = dynamic(
|
||||
() => {
|
||||
@@ -28,44 +29,44 @@ const Comment = ({ frontMatter }) => {
|
||||
const { theme } = useGlobal()
|
||||
|
||||
return (
|
||||
BLOG.comment.provider !== '' && (
|
||||
<div className='comment mt-5 text-gray-800 dark:text-gray-300'>
|
||||
{BLOG.comment.provider === 'gitalk' && (<div className='m-10'>
|
||||
<div className='comment mt-5 text-gray-800 dark:text-gray-300'>
|
||||
<Tabs>
|
||||
{BLOG.COMMENT_GITALK_CLIENT_ID && (<div className='m-10' key='gitalk'>
|
||||
<GitalkComponent
|
||||
options={{
|
||||
id: frontMatter.id,
|
||||
title: frontMatter.title,
|
||||
clientID: BLOG.comment.gitalkConfig.clientID,
|
||||
clientSecret: BLOG.comment.gitalkConfig.clientSecret,
|
||||
repo: BLOG.comment.gitalkConfig.repo,
|
||||
owner: BLOG.comment.gitalkConfig.owner,
|
||||
admin: BLOG.comment.gitalkConfig.admin,
|
||||
distractionFreeMode: BLOG.comment.gitalkConfig.distractionFreeMode
|
||||
clientID: BLOG.COMMENT_GITALK_CLIENT_ID,
|
||||
clientSecret: BLOG.COMMENT_GITALK_CLIENT_SECRET,
|
||||
repo: BLOG.COMMENT_GITALK_REPO,
|
||||
owner: BLOG.COMMENT_GITALK_OWNER,
|
||||
admin: BLOG.COMMENT_GITALK_ADMIN.split(','),
|
||||
distractionFreeMode: BLOG.COMMENT_GITALK_DISTRACTION_FREE_MODE
|
||||
}}
|
||||
/>
|
||||
</div>)}
|
||||
{BLOG.comment.provider === 'utterances' && (<div className='m-10'>
|
||||
<UtterancesComponent issueTerm={frontMatter.id} className='px-2' />
|
||||
</div>
|
||||
{BLOG.COMMENT_UTTERRANCES_REPO && (<div className='m-10' key='utterance'>
|
||||
<UtterancesComponent issueTerm={frontMatter.id} className='px-2' />
|
||||
</div>
|
||||
)}
|
||||
{BLOG.comment.provider === 'cusdis' && (<>
|
||||
{BLOG.COMMENT_CUSDIS_APP_ID && (<>
|
||||
<script defer src='https://cusdis.com/js/widget/lang/zh-cn.js' />
|
||||
<div className='m-10'>
|
||||
<div className='m-10' key='cusdis'>
|
||||
<CusdisComponent
|
||||
attrs={{
|
||||
host: BLOG.comment.cusdisConfig.host,
|
||||
appId: BLOG.comment.cusdisConfig.appId,
|
||||
host: BLOG.COMMENT_CUSDIS_HOST,
|
||||
appId: BLOG.COMMENT_CUSDIS_APP_ID,
|
||||
pageId: frontMatter.id,
|
||||
pageTitle: frontMatter.title,
|
||||
pageUrl: BLOG.link + router.asPath,
|
||||
pageUrl: BLOG.LINK + router.asPath,
|
||||
theme: theme
|
||||
}}
|
||||
lang={BLOG.lang.toLowerCase()}
|
||||
lang={BLOG.LANG.toLowerCase()}
|
||||
/>
|
||||
</div>
|
||||
</>)}
|
||||
</div>
|
||||
)
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,32 +2,30 @@ 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 <Head>
|
||||
<title>{title}</title>
|
||||
<meta name='theme-color' content={BLOG.darkBackground} />
|
||||
<meta name='theme-color' content={BLOG.BACKGROUND_DARK} />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
||||
<meta name='robots' content='follow, index' />
|
||||
<meta charSet='UTF-8' />
|
||||
{BLOG.seo.googleSiteVerification && (
|
||||
{BLOG.SEO_GOOGLE_SITE_VERIFICATION && (
|
||||
<meta
|
||||
name='google-site-verification'
|
||||
content={BLOG.seo.googleSiteVerification}
|
||||
content={BLOG.SEO_GOOGLE_SITE_VERIFICATION}
|
||||
/>
|
||||
)}
|
||||
{keywords && (
|
||||
<meta name='keywords' content={keywords.join(', ')} />
|
||||
)}
|
||||
<meta name='keywords' content={keywords} />
|
||||
<meta name='description' content={description} />
|
||||
<meta property='og:locale' content={BLOG.lang} />
|
||||
<meta property='og:locale' content={BLOG.LANG} />
|
||||
<meta property='og:title' content={title} />
|
||||
<meta property='og:description' content={description} />
|
||||
<meta property='og:url' content={url}
|
||||
@@ -42,7 +40,7 @@ const CommonHead = ({ meta }) => {
|
||||
property='article:published_time'
|
||||
content={meta.date || meta.createdTime}
|
||||
/>
|
||||
<meta property='article:author' content={BLOG.author} />
|
||||
<meta property='article:author' content={BLOG.AUTHOR} />
|
||||
</>
|
||||
)}
|
||||
</Head>
|
||||
|
||||
@@ -7,7 +7,7 @@ import BLOG from '@/blog.config'
|
||||
*/
|
||||
const CommonScript = () => {
|
||||
return (<>
|
||||
{BLOG.comment?.DaoVoiceId && (<>
|
||||
{BLOG.COMMENT_DAO_VOICE_ENABLE && (<>
|
||||
{/* DaoVoice 反馈 */}
|
||||
<script async dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
@@ -18,7 +18,7 @@ const CommonScript = () => {
|
||||
<script async dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
daovoice('init', {
|
||||
app_id: "${BLOG.comment.DaoVoiceId}"
|
||||
app_id: "${BLOG.COMMENT_DAO_VOICE_ID}"
|
||||
});
|
||||
daovoice('update');
|
||||
`
|
||||
@@ -30,44 +30,45 @@ const CommonScript = () => {
|
||||
{BLOG.googleAdsenseId && (<script data-ad-client={BLOG.googleAdsenseId} async
|
||||
src='https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'/>)}
|
||||
|
||||
{BLOG.comment?.TidioId && (<>
|
||||
{BLOG.COMMENT_TIDIO_ENABLE && (<>
|
||||
{/* Tidio在线反馈 */}
|
||||
<script async
|
||||
src={`//code.tidio.co/${BLOG.comment.TidioId}.js`}
|
||||
src={`//code.tidio.co/${BLOG.COMMENT_TIDIO_ID}.js`}
|
||||
/>
|
||||
</>)}
|
||||
|
||||
{/* */}
|
||||
{BLOG.gitter && (<>
|
||||
{BLOG.COMMENT_GITTER_ENABLE && (<>
|
||||
<script async dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
((window.gitter = {}).chat = {}).options = {
|
||||
room: 'tangly1024/community'
|
||||
room: '${BLOG.COMMENT_GITTER_ROOM}'
|
||||
};
|
||||
`
|
||||
}}/>
|
||||
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
|
||||
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer/>
|
||||
</>)}
|
||||
|
||||
{/* 代码统计 */}
|
||||
{BLOG.isProd && (<>
|
||||
|
||||
{/* ackee统计脚本 */}
|
||||
{BLOG.analytics.provider === 'ackee' && (
|
||||
<script async src={BLOG.analytics.ackeeConfig.tracker}
|
||||
data-ackee-server={BLOG.analytics.ackeeConfig.dataAckeeServer}
|
||||
data-ackee-domain-id={BLOG.analytics.ackeeConfig.domainId}
|
||||
{BLOG.ANALYTICS_ACKEE_ENABLE && (
|
||||
<script async src={BLOG.ANALYTICS_ACKEE_TRACKER}
|
||||
data-ackee-server={BLOG.ANALYTICS_ACKEE_DATA_SERVER}
|
||||
data-ackee-domain-id={BLOG.ANALYTICS_ACKEE_DOMAIN_ID}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 百度统计 */}
|
||||
{BLOG.analytics.baiduAnalytics && (
|
||||
{BLOG.ANALYTICS_BAIDU_ENABLE && (
|
||||
<script async
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?${BLOG.analytics.baiduAnalytics}";
|
||||
hm.src = "https://hm.baidu.com/hm.js?${BLOG.ANALYTICS_BAIDU_ID}";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
@@ -77,20 +78,20 @@ const CommonScript = () => {
|
||||
)}
|
||||
|
||||
{/* 站长统计 */}
|
||||
{BLOG.analytics.cnzzAnalytics && (
|
||||
{BLOG.ANALYTICS_CNZZ_ENABLE && (
|
||||
<script async
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
document.write(unescape("%3Cspan style='display:none' id='cnzz_stat_icon_${BLOG.analytics.cnzzAnalytics}'%3E%3C/span%3E%3Cscript src='https://s9.cnzz.com/z_stat.php%3Fid%3D${BLOG.analytics.cnzzAnalytics}' type='text/javascript'%3E%3C/script%3E"));
|
||||
document.write(unescape("%3Cspan style='display:none' id='cnzz_stat_icon_${BLOG.ANALYTICS_CNZZ_ID}'%3E%3C/span%3E%3Cscript src='https://s9.cnzz.com/z_stat.php%3Fid%3D${BLOG.ANALYTICS_CNZZ_ID}' type='text/javascript'%3E%3C/script%3E"));
|
||||
`
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 谷歌统计 */}
|
||||
{BLOG.analytics.provider === 'ga' && (<>
|
||||
{BLOG.ANALYTICS_GOOGLE_ENABLE && (<>
|
||||
<script async
|
||||
src={`https://www.googletagmanager.com/gtag/js?id=${BLOG.analytics.gaConfig.measurementId}`}
|
||||
src={`https://www.googletagmanager.com/gtag/js?id=${BLOG.ANALYTICS_GOOGLE_ID}`}
|
||||
/>
|
||||
<script async
|
||||
dangerouslySetInnerHTML={{
|
||||
@@ -98,7 +99,7 @@ const CommonScript = () => {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', '${BLOG.analytics.gaConfig.measurementId}', {
|
||||
gtag('config', '${BLOG.ANALYTICS_GOOGLE_ID}', {
|
||||
page_path: window.location.pathname,
|
||||
});
|
||||
`
|
||||
|
||||
@@ -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 }) => {
|
||||
<div id="comments">
|
||||
<div
|
||||
id="cusdis_thread"
|
||||
data-host={BLOG.comment.cusdisConfig.host || 'https://cusdis.com'}
|
||||
data-app-id={BLOG.comment.cusdisConfig.appId}
|
||||
data-host={BLOG.COMMENT_CUSDIS_HOST}
|
||||
data-app-id={BLOG.COMMENT_CUSDIS_APP_ID}
|
||||
data-page-id={id}
|
||||
data-page-url={url}
|
||||
data-page-title={title}
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -35,7 +35,7 @@ const Utterances = ({ issueTerm, layout }) => {
|
||||
id="comments"
|
||||
className={layout && layout === 'fullWidth' ? '' : 'md:-ml-16'}
|
||||
>
|
||||
<div className="utterances-frame"></div>
|
||||
<div className="utterances-frame"/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
30
lib/rss.js
30
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)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const BLOG = require('./blog.config')
|
||||
|
||||
module.exports = {
|
||||
siteUrl: BLOG.link,
|
||||
siteUrl: BLOG.LINK,
|
||||
changefreq: 'daily',
|
||||
priority: 0.7,
|
||||
generateRobotsTxt: true,
|
||||
|
||||
@@ -26,15 +26,12 @@ const GoogleAdsense = dynamic(() => import('@/components/GoogleAdsense'), { ssr:
|
||||
const MyApp = ({ Component, pageProps }) => {
|
||||
return (
|
||||
<GlobalContextProvider>
|
||||
{BLOG.isProd && BLOG?.analytics?.provider === 'ackee' && (
|
||||
<Ackee
|
||||
ackeeServerUrl={BLOG.analytics.ackeeConfig.dataAckeeServer}
|
||||
ackeeDomainId={BLOG.analytics.ackeeConfig.domainId}
|
||||
/>
|
||||
{BLOG.ANALYTICS_ACKEE_ENABLE && (
|
||||
<Ackee />
|
||||
)}
|
||||
{BLOG.isProd && BLOG?.analytics?.provider === 'ga' && <Gtag />}
|
||||
{BLOG.analytics.busuanzi && <Busuanzi/>}
|
||||
{BLOG.googleAdsenseId && <GoogleAdsense/>}
|
||||
{BLOG.ANALYTICS_GOOGLE_ENABLE && <Gtag />}
|
||||
{BLOG.ANALYTICS_BUSUANZI_ENABLE && <Busuanzi/>}
|
||||
{BLOG.GOOGLE_ADSENSE_ENABLE && <GoogleAdsense/>}
|
||||
<Component {...pageProps} />
|
||||
</GlobalContextProvider>
|
||||
)
|
||||
|
||||
@@ -11,14 +11,15 @@ class MyDocument extends Document {
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Html lang={BLOG.lang}>
|
||||
<Html lang={BLOG.LANG}>
|
||||
<Head>
|
||||
<title>{BLOG.title}</title>
|
||||
<link rel='icon' href='/favicon.ico' />
|
||||
<link rel='icon' href='/favicon.svg' type='image/svg+xml' />
|
||||
<CommonScript />
|
||||
</Head>
|
||||
|
||||
<body className={`${BLOG.font} bg-day dark:bg-night`}>
|
||||
<body className={`${BLOG.FONT} bg-day dark:bg-night`}>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
|
||||
@@ -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 { allPosts } = getGlobalNotionData({ from: 'rss' })
|
||||
const xmlFeed = generateRss(allPosts.slice(0, 10))
|
||||
res.write(xmlFeed)
|
||||
res.end()
|
||||
return {
|
||||
|
||||
@@ -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.previewLines)
|
||||
const blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES)
|
||||
if (blockMap) {
|
||||
post.blockMap = blockMap
|
||||
}
|
||||
|
||||
@@ -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,20 +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.previewLines)
|
||||
const blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES)
|
||||
if (blockMap) {
|
||||
post.blockMap = blockMap
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ export const LayoutArchive = (props) => {
|
||||
})
|
||||
|
||||
const meta = {
|
||||
title: `${locale.NAV.ARCHIVE} | ${BLOG.title}`,
|
||||
description: BLOG.description,
|
||||
title: `${locale.NAV.ARCHIVE} | ${BLOG.TITLE}`,
|
||||
description: BLOG.DESCRIPTION,
|
||||
type: 'website'
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ export const LayoutCategoryIndex = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { categories } = props
|
||||
const meta = {
|
||||
title: `${locale.COMMON.CATEGORY} | ${BLOG.title}`,
|
||||
description: BLOG.description,
|
||||
title: `${locale.COMMON.CATEGORY} | ${BLOG.TITLE}`,
|
||||
description: BLOG.DESCRIPTION,
|
||||
type: 'website'
|
||||
}
|
||||
return <LayoutBase {...props} meta={meta}>
|
||||
|
||||
@@ -11,7 +11,7 @@ import LayoutBase from './LayoutBase'
|
||||
export const LayoutSlug = (props) => {
|
||||
const { post } = props
|
||||
const meta = {
|
||||
title: `${post.title} | ${BLOG.title}`,
|
||||
title: `${post.title} | ${BLOG.TITLE}`,
|
||||
description: post.summary,
|
||||
type: 'article',
|
||||
tags: post.tags
|
||||
|
||||
@@ -9,8 +9,8 @@ export const LayoutTagIndex = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { tags } = props
|
||||
const meta = {
|
||||
title: `${locale.COMMON.TAGS} | ${BLOG.title}`,
|
||||
description: BLOG.description,
|
||||
title: `${locale.COMMON.TAGS} | ${BLOG.TITLE}`,
|
||||
description: BLOG.DESCRIPTION,
|
||||
type: 'website'
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ function AsideLeft ({ tags, currentTag, categories, currentCategory }) {
|
||||
|
||||
<section className='flex flex-col'>
|
||||
<hr className='w-12 my-8 ' />
|
||||
{ BLOG.description }
|
||||
{ BLOG.DESCRIPTION }
|
||||
</section>
|
||||
|
||||
<section className='flex flex-col'>
|
||||
|
||||
@@ -12,7 +12,7 @@ const BlogCard = ({ post, showSummary }) => {
|
||||
<div key={post.id} className='animate__animated animate__fadeIn flex flex-col-reverse justify-between duration-300'>
|
||||
|
||||
<div className='p-2 flex flex-col w-full'>
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<a className={`cursor-pointer font-bold hover:underline text-xl flex ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
|
||||
{post.title}
|
||||
</a>
|
||||
@@ -24,7 +24,7 @@ const BlogCard = ({ post, showSummary }) => {
|
||||
</div>
|
||||
|
||||
{CONFIG_FUKA.POST_LIST_COVER && post?.page_cover && (
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<div className='h-40 w-full relative duration-200 cursor-pointer transform overflow-hidden'>
|
||||
<Image className='hover:scale-105 transform duration-500' src={post?.page_cover} alt={post.title} layout='fill' objectFit='cover' loading='lazy' />
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ import PaginationSimple from './PaginationSimple'
|
||||
* @constructor
|
||||
*/
|
||||
const BlogListPage = ({ page = 1, posts = [], postCount }) => {
|
||||
const totalPage = Math.ceil(postCount / BLOG.postsPerPage)
|
||||
const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE)
|
||||
const showNext = page < totalPage && posts.length < postCount
|
||||
const [colCount, changeCol] = useState(3)
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
||||
<ul>
|
||||
{posts.map(post => (
|
||||
<li key={post.id} className='border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500'>
|
||||
<div name={post?.date?.start_date}><span className='text-gray-400'>{post.date.start_date}</span>
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<div id={post?.date?.start_date}><span className='text-gray-400'>{post.date.start_date}</span>
|
||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<a className='dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600'>{post.title}</a>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@ import Link from 'next/link'
|
||||
function Logo () {
|
||||
return <section className='flex'>
|
||||
<Link href='/'>
|
||||
<a className='hover:bg-black hover:text-white border-black border-2 duration-500 px-4 py-2 cursor-pointer font-black'>{BLOG.title}</a>
|
||||
<a className='hover:bg-black hover:text-white border-black border-2 duration-500 px-4 py-2 cursor-pointer font-black'>{BLOG.TITLE}</a>
|
||||
</Link>
|
||||
</section>
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const PaginationSimple = ({ page, showNext }) => {
|
||||
<div className='my-10 flex justify-between font-medium text-black dark:text-gray-100 space-x-2'>
|
||||
<Link
|
||||
href={ {
|
||||
pathname: (currentPage === 2 ? `${BLOG.path || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
pathname: (currentPage === 2 ? `${BLOG.PATH || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
} } passHref >
|
||||
<a
|
||||
rel='prev'
|
||||
|
||||
@@ -5,16 +5,16 @@ 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 + '-'
|
||||
const startYear = BLOG.SINCE && BLOG.SINCE !== currentYear && BLOG.SINCE + '-'
|
||||
return (
|
||||
<footer
|
||||
className='leading-6 justify-start w-full text-gray-400 text-xs font-sans'
|
||||
>
|
||||
<span> © {`${startYear}${currentYear}`} <span> <a href={BLOG.link} className='text-gray-500 dark:text-gray-300 '>{BLOG.author}</a>. <br /></span>
|
||||
<span> © {`${startYear}${currentYear}`} <span> <a href={BLOG.LINK} className='text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>. <br /></span>
|
||||
|
||||
<span>Powered by <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-500 dark:text-gray-300'>NotionNext</a>.</span><br /></span>
|
||||
|
||||
{BLOG.beian && <><FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.beian}</a><br/></>}
|
||||
{BLOG.BEI_AN && <><FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
|
||||
|
||||
<span className='hidden busuanzi_container_site_pv'> <FontAwesomeIcon icon={faEye} /><span className='px-1 busuanzi_value_site_pv'> </span> </span>
|
||||
<span className='pl-2 hidden busuanzi_container_site_uv'> <FontAwesomeIcon icon={faUsers} /> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
|
||||
|
||||
@@ -21,7 +21,7 @@ export const Layout404 = () => {
|
||||
}, 30000000)
|
||||
})
|
||||
|
||||
return <LayoutBase meta={{ title: `${BLOG.title} | 页面找不到啦` }}>
|
||||
return <LayoutBase meta={{ title: `${BLOG.TITLE} | 页面找不到啦` }}>
|
||||
<div
|
||||
className='md:-mt-20 text-black w-full h-screen text-center justify-center content-center items-center flex flex-col'>
|
||||
<div className='dark:text-gray-200'>
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <LayoutBase meta={meta} tags={tags} currentCategory={category} postCount={postCount} latestPosts={latestPosts} categories={categories}>
|
||||
|
||||
@@ -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 <LayoutBase meta={meta} totalPosts={allPosts} tags={tags} postCount={postCount} latestPosts={latestPosts}>
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -27,7 +27,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
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <LayoutBase meta={meta} categories={categories} postCount={postCount} latestPosts={latestPosts}>
|
||||
|
||||
@@ -28,7 +28,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)
|
||||
|
||||
@@ -144,7 +144,7 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
|
||||
</section>
|
||||
|
||||
{/* 版权声明 */}
|
||||
<ArticleCopyright author={BLOG.author} url={url} />
|
||||
<ArticleCopyright author={BLOG.AUTHOR} url={url} />
|
||||
|
||||
{/* 推荐文章 */}
|
||||
<RecommendPosts currentPost={post} recommendPosts={recommendPosts} />
|
||||
|
||||
@@ -17,8 +17,8 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
<ul>
|
||||
{posts.map(post => (
|
||||
<li key={post.id} className='border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500'>
|
||||
<div name={post?.date?.start_date}><span className='text-gray-400'>{post.date.start_date}</span>
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<div id={post?.date?.start_date}><span className='text-gray-400'>{post.date.start_date}</span>
|
||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<a className='dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600'>{post.title}</a>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<div key={post.id} className='animate__animated animate__fadeIn flex flex-col-reverse justify-between duration-300'>
|
||||
|
||||
<div className='lg:p-8 p-4 flex flex-col w-full'>
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<a className={`cursor-pointer font-bold hover:underline text-3xl flex ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
|
||||
{post.title}
|
||||
</a>
|
||||
@@ -60,7 +60,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
</div> }
|
||||
|
||||
<div className='article-cover pointer-events-none'>
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<a className='hover:bg-opacity-100 hover:scale-105 pointer-events-auto transform duration-300 rounded-md p-2 text-red-500 cursor-pointer'>
|
||||
{locale.COMMON.ARTICLE_DETAIL}
|
||||
<FontAwesomeIcon className='ml-1' icon={faAngleRight} /></a>
|
||||
@@ -69,7 +69,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
</div>
|
||||
|
||||
{CONFIG_NEXT.POST_LIST_COVER && post?.page_cover && (
|
||||
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<div className='h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden'>
|
||||
<Image className='hover:scale-105 transform duration-500' src={post?.page_cover} alt={post.title} layout='fill' objectFit='cover' loading='lazy' />
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@ import BlogPostListEmpty from './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 <BlogPostListEmpty />
|
||||
|
||||
@@ -14,7 +14,7 @@ import CONFIG_NEXT from '../config_next'
|
||||
* @constructor
|
||||
*/
|
||||
const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_NEXT.POST_LIST_SUMMARY }) => {
|
||||
const postsPerPage = BLOG.postsPerPage
|
||||
const postsPerPage = BLOG.POSTS_PER_PAGE
|
||||
const [page, updatePage] = useState(1)
|
||||
const postsToShow = getPostByPage(page, posts, postsPerPage)
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ 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 (
|
||||
<footer
|
||||
className='dark:bg-gray-900 flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-gray-400 text-sm p-6'
|
||||
>
|
||||
<FontAwesomeIcon icon={faCopyright} /> {`${startYear}${currentYear}`} <span><FontAwesomeIcon icon={faHeart} className='mx-1 animate-pulse'/> <a href={BLOG.link} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.author}</a>.
|
||||
<FontAwesomeIcon icon={faCopyright} /> {`${startYear}${currentYear}`} <span><FontAwesomeIcon icon={faHeart} className='mx-1 animate-pulse'/> <a href={BLOG.LINK} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
|
||||
<br/>
|
||||
|
||||
<span>Powered by <a href='https://notion.so' className='underline font-bold text-gray-500 dark:text-gray-300'>Notion</a> & <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-500 dark:text-gray-300'>NotionNext</a>.</span></span>
|
||||
|
||||
@@ -4,12 +4,12 @@ import Router from 'next/router'
|
||||
import React from 'react'
|
||||
import SocialButton from './SocialButton'
|
||||
|
||||
const InfoCard = ({ postCount }) => {
|
||||
const InfoCard = () => {
|
||||
return <>
|
||||
<div className='flex flex-col items-center justify-center '>
|
||||
<div className='hover:rotate-45 hover:scale-125 transform duration-200 cursor-pointer' onClick={ () => { Router.push('/about') }}>
|
||||
<Image
|
||||
alt={BLOG.author}
|
||||
alt={BLOG.AUTHOR}
|
||||
width={120}
|
||||
height={120}
|
||||
loading='lazy'
|
||||
@@ -17,8 +17,8 @@ const InfoCard = ({ postCount }) => {
|
||||
className='rounded-full'
|
||||
/>
|
||||
</div>
|
||||
<div className='text-2xl font-serif dark:text-white py-2 hover:scale-105 transform duration-200'>{BLOG.author}</div>
|
||||
<div className='font-light dark:text-white py-2 hover:scale-105 transform duration-200'>{BLOG.bio}</div>
|
||||
<div className='text-2xl font-serif dark:text-white py-2 hover:scale-105 transform duration-200'>{BLOG.AUTHOR}</div>
|
||||
<div className='font-light dark:text-white py-2 hover:scale-105 transform duration-200'>{BLOG.BIO}</div>
|
||||
<SocialButton/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -24,9 +24,9 @@ const LatestPostsGroup = ({ posts }) => {
|
||||
<div className='font-light text-gray-600 dark:text-gray-200'><FontAwesomeIcon icon={faArchive} className='mr-2' />{locale.COMMON.LATEST_POSTS}</div>
|
||||
</div>
|
||||
{posts.map(post => {
|
||||
const selected = currentPath === `${BLOG.path}/article/${post.slug}`
|
||||
const selected = currentPath === `${BLOG.PATH}/article/${post.slug}`
|
||||
return (
|
||||
<Link key={post.id} title={post.title} href={`${BLOG.path}/article/${post.slug}`} passHref>
|
||||
<Link key={post.id} title={post.title} href={`${BLOG.PATH}/article/${post.slug}`} passHref>
|
||||
<a className={ 'my-1 flex font-light'}>
|
||||
<div className={ (selected ? 'text-white bg-gray-600 ' : 'text-gray-500 dark:text-gray-400 ') + ' text-xs py-1.5 flex overflow-x-hidden whitespace-nowrap hover:bg-gray-500 px-2 duration-200 w-full ' +
|
||||
'hover:text-white dark:hover:text-white cursor-pointer' }>
|
||||
|
||||
@@ -5,8 +5,8 @@ import React from 'react'
|
||||
const Logo = () => {
|
||||
return <Link href='/' passHref>
|
||||
<div className='flex flex-col justify-center items-center cursor-pointer bg-black space-y-3 h-32 font-bold'>
|
||||
<div className='font-serif text-xl text-white'> {BLOG.title}</div>
|
||||
<div className='text-sm text-gray-300 font-light'> {BLOG.description}</div>
|
||||
<div className='font-serif text-xl text-white'> {BLOG.TITLE}</div>
|
||||
<div className='text-sm text-gray-300 font-light'> {BLOG.DESCRIPTION}</div>
|
||||
</div>
|
||||
</Link>
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const PaginationNumber = ({ page, totalPage }) => {
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={ {
|
||||
pathname: (currentPage - 1 === 1 ? `${BLOG.path || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
pathname: (currentPage - 1 === 1 ? `${BLOG.PATH || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
} } passHref >
|
||||
<div
|
||||
rel='prev'
|
||||
|
||||
@@ -18,7 +18,7 @@ const PaginationSimple = ({ page, showNext }) => {
|
||||
<div className='my-10 flex justify-between font-medium text-black dark:text-gray-100 space-x-2'>
|
||||
<Link
|
||||
href={ {
|
||||
pathname: (currentPage - 1 === 1 ? `${BLOG.path || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
pathname: (currentPage - 1 === 1 ? `${BLOG.PATH || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
} } passHref >
|
||||
<button
|
||||
rel='prev'
|
||||
|
||||
@@ -22,7 +22,7 @@ const ShareBar = ({ post }) => {
|
||||
return <></>
|
||||
}
|
||||
const router = useRouter()
|
||||
const shareUrl = BLOG.link + router.asPath
|
||||
const shareUrl = BLOG.LINK + router.asPath
|
||||
|
||||
// 二维码悬浮
|
||||
const [qrCodeShow, setQrCodeShow] = React.useState(false)
|
||||
|
||||
@@ -4,7 +4,7 @@ import SearchInput from './SearchInput'
|
||||
import Toc from './Toc'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import React from 'react'
|
||||
import Tabs from './Tabs'
|
||||
import Tabs from '@/components/Tabs'
|
||||
import Logo from './Logo'
|
||||
import Card from './Card'
|
||||
import CONFIG_NEXT from '../config_next'
|
||||
|
||||
@@ -12,19 +12,19 @@ import React from 'react'
|
||||
const SocialButton = () => {
|
||||
return <div className='w-52 justify-center flex-wrap flex'>
|
||||
<div className='space-x-3 text-xl text-gray-600 dark:text-gray-400 '>
|
||||
{BLOG.socialLink.github && <a target='_blank' rel='noreferrer' title={'github'} href={BLOG.socialLink.github} >
|
||||
{BLOG.CONTACT_GITHUB && <a target='_blank' rel='noreferrer' title={'github'} href={BLOG.CONTACT_GITHUB} >
|
||||
<FontAwesomeIcon icon={faGithub} className='transform hover:scale-125 duration-150'/>
|
||||
</a>}
|
||||
{BLOG.socialLink.twitter && <a target='_blank' rel='noreferrer' title={'twitter'} href={BLOG.socialLink.twitter} >
|
||||
{BLOG.CONTACT_TWITTER && <a target='_blank' rel='noreferrer' title={'twitter'} href={BLOG.CONTACT_TWITTER} >
|
||||
<FontAwesomeIcon icon={faTwitter} className='transform hover:scale-125 duration-150'/>
|
||||
</a>}
|
||||
{BLOG.socialLink.telegram && <a target='_blank' rel='noreferrer' href={BLOG.socialLink.telegram} title={'telegram'} >
|
||||
{BLOG.CONTACT_TELEGRAM && <a target='_blank' rel='noreferrer' href={BLOG.CONTACT_TELEGRAM} title={'telegram'} >
|
||||
<FontAwesomeIcon icon={faTelegram} className='transform hover:scale-125 duration-150'/>
|
||||
</a>}
|
||||
{BLOG.socialLink.weibo && <a target='_blank' rel='noreferrer' title={'weibo'} href={BLOG.socialLink.weibo} >
|
||||
{BLOG.CONTACT_WEIBO && <a target='_blank' rel='noreferrer' title={'weibo'} href={BLOG.CONTACT_WEIBO} >
|
||||
<FontAwesomeIcon icon={faWeibo} className='transform hover:scale-125 duration-150'/>
|
||||
</a>}
|
||||
{BLOG.email && <a target='_blank' rel='noreferrer' title={'email'} href={`mailto:${BLOG.email}`} >
|
||||
{BLOG.CONTACT_EMAIL && <a target='_blank' rel='noreferrer' title={'email'} href={`mailto:${BLOG.CONTACT_EMAIL}`} >
|
||||
<FontAwesomeIcon icon={faEnvelope} className='transform hover:scale-125 duration-150'/>
|
||||
</a>}
|
||||
<a target='_blank' rel='noreferrer' title={'RSS'} href={'/feed'} >
|
||||
|
||||
Reference in New Issue
Block a user