This commit is contained in:
tangly1024
2021-09-27 09:33:21 +08:00
parent 22ca7f6d63
commit dfc0f645d4
76 changed files with 3650 additions and 2 deletions

31
pages/404.js Normal file
View File

@@ -0,0 +1,31 @@
/**
* 自定义404界面
* @returns {JSX.Element}
* @constructor
*/
import { useRouter } from 'next/router'
import { useEffect } from 'react'
export default function Custom404 () {
const route = useRouter()
if (route.asPath.indexOf('/article') < 0 && route.asPath.indexOf('/404') < 0) {
// article 重定向,处理旧文章链接迁移。
const redirectUrl = '/article' + route.asPath
route.push(redirectUrl)
} else {
useEffect(() => {
setTimeout(() => {
window.location.href = '/'
}, 3000)
})
}
return <div
className='text-black bg-white h-screen text-center justify-center content-center items-center flex flex-col'>
<div>
<h1 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'>404</h1>
<div className='inline-block text-left h-32 leading-10 align-middle'>
<h2 className='m-0 p-0'>页面丢失了3秒后返回首页</h2></div>
</div>
</div>
}

37
pages/_app.js Normal file
View File

@@ -0,0 +1,37 @@
import '@/styles/notion.css'
import 'rc-dropdown/assets/index.css'
import 'katex/dist/katex.min.css'
import '@/styles/globals.css'
import 'prismjs'
import 'prismjs/themes/prism-okaidia.css'
import 'prismjs/components/prism-markup'
import 'prismjs/components/prism-python'
import 'prismjs/components/prism-bash'
import 'animate.css'
import 'font-awesome/css/font-awesome.min.css'
import BLOG from '@/blog.config'
import dynamic from 'next/dynamic'
import { LocaleProvider } from '@/lib/locale'
import { ThemeProvider } from '@/lib/theme'
const Ackee = dynamic(() => import('@/components/Ackee'), { ssr: false })
const Gtag = dynamic(() => import('@/components/Gtag'), { ssr: false })
function MyApp ({ Component, pageProps }) {
return (
<LocaleProvider>
<ThemeProvider>
{BLOG.isProd && BLOG?.analytics?.provider === 'ackee' && (
<Ackee
ackeeServerUrl={BLOG.analytics.ackeeConfig.dataAckeeServer}
ackeeDomainId={BLOG.analytics.ackeeConfig.domainId}
/>
)}
{BLOG.isProd && BLOG?.analytics?.provider === 'ga' && <Gtag />}
<Component {...pageProps} />
</ThemeProvider>
</LocaleProvider>
)
}
export default MyApp

119
pages/_document.js Normal file
View File

@@ -0,0 +1,119 @@
import Document, { Html, Head, Main, NextScript } from 'next/document'
import BLOG from '@/blog.config'
class MyDocument extends Document {
static async getInitialProps (ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render () {
return (
<Html lang={BLOG.lang} >
<Head>
<link rel='icon' href='/favicon.ico' />
<link rel='icon' href='/favicon.svg' type='image/svg+xml'></link>
{/* 字体 */}
{/* <link rel='stylesheet' href='/font-awesome-4.7.0/css/font-awesome.min.css'/> */}
{/* <link rel='stylesheet' href='https://cdn.bootcdn.net/ajax/libs/font-awesome/5.15.3/css/all.min.css'/> */}
{/* GoogleAdsense */}
{BLOG.isProd && (
<script data-ad-client="ca-pub-2708419466378217" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
)}
{/* 统计脚本 */}
{BLOG.isProd && BLOG.analytics && 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.isProd && BLOG.autoCollapsedNavBar === true && (
<script
dangerouslySetInnerHTML={{
__html: `
var windowTop=0;
function scrollTrigger(){
let scrollS = window.scrollY;
let nav = document.querySelector('.sticky-nav');
if(scrollS >= windowTop){
nav.style.opacity = 0;
windowTop = scrollS;
}else{
nav.style.opacity = 1;
windowTop = scrollS;
}
};
window.addEventListener('scroll',scrollTrigger);
`
}}
/>
)}
{/* 百度 */}
{BLOG.isProd && (
<script async
dangerouslySetInnerHTML={{
__html: `
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?f683ef76f06bb187cbed5546f6f28f28";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
`
}}
/>
)}
{/* 不蒜子 */}
{BLOG.isProd && (
<script async
src={'//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js'}
/>
)}
{BLOG.isProd && (
<script async
dangerouslySetInnerHTML={{
__html: `
document.write(unescape("%3Cspan style='display:none' id='cnzz_stat_icon_1279970751'%3E%3C/span%3E%3Cscript src='https://s9.cnzz.com/z_stat.php%3Fid%3D1279970751' type='text/javascript'%3E%3C/script%3E"));
`
}}
/>
)}
{/* 谷歌统计 */}
{BLOG.isProd && BLOG.analytics && BLOG.analytics.provider === 'ga' && (
<>
<script async
src={`https://www.googletagmanager.com/gtag/js?id=${BLOG.analytics.gaConfig.measurementId}`}
/>
<script async
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${BLOG.analytics.gaConfig.measurementId}', {
page_path: window.location.pathname,
});
`
}}
/>
</>
)}
</Head>
<body className='dark:bg-black h-full'>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument

60
pages/article/[slug].js Normal file
View File

@@ -0,0 +1,60 @@
import ArticleLayout from '@/layouts/ArticleLayout'
import { getAllPosts, getAllTags, getPostBlocks } from '@/lib/notion'
import BLOG from '@/blog.config'
import { createHash } from 'crypto'
import { getPageTableOfContents } from 'notion-utils'
import Custom404 from '@/pages/404'
const BlogPost = ({ post, blockMap, emailHash, tags, prev, next }) => {
if (!post) {
return <Custom404/>
}
return (
<ArticleLayout
blockMap={blockMap}
frontMatter={post}
emailHash={emailHash}
tags={tags}
prev={prev}
next={next}
></ArticleLayout>
)
}
export async function getStaticPaths () {
let posts = await getAllPosts()
posts = posts.filter(post => post.status[0] === 'Published')
return {
paths: posts.map(row => `${BLOG.path}/article/${row.slug}`),
fallback: true
}
}
export async function getStaticProps ({ params: { slug } }) {
let posts = await getAllPosts()
posts = posts.filter(post => post.status[0] === 'Published')
const post = posts.find(t => t.slug === slug)
if (!post) {
return {
props: { },
revalidate: 1
}
}
const blockMap = await getPostBlocks(post.id)
const emailHash = createHash('md5').update(BLOG.email).digest('hex')
post.toc = getPageTableOfContents(post, blockMap)
posts = posts.filter(post => post.type[0] === 'Post')
const tags = await getAllTags(posts)
// 获取推荐文章
const index = posts.indexOf(post)
const prev = posts.slice(index - 1, index)[0] ?? posts.slice(-1)[0]
const next = posts.slice(index + 1, index + 2)[0] ?? posts[0]
return {
props: { post, blockMap, emailHash, tags, prev, next },
revalidate: 1
}
}
export default BlogPost

19
pages/feed.js Normal file
View File

@@ -0,0 +1,19 @@
import { getAllPosts } from '@/lib/notion'
import { generateRss } from '@/lib/rss'
export async function getServerSideProps ({ res }) {
res.setHeader('Content-Type', 'text/xml')
let posts = await getAllPosts()
posts = posts
.filter(post => post.status[0] === 'Published' && post.type[0] === 'Post')
.slice(0, 10)
const xmlFeed = generateRss(posts)
res.write(xmlFeed)
res.end()
return {
props: {}
}
}
const feed = () => null
export default feed

27
pages/index.js Normal file
View File

@@ -0,0 +1,27 @@
import { getAllPosts, getAllTags } from '@/lib/notion'
import DefaultLayout from '@/layouts/DefaultLayout'
export async function getStaticProps () {
let posts = await getAllPosts()
posts = posts.filter(
post => post.status[0] === 'Published' && post.type[0] === 'Post'
)
const tags = await getAllTags(posts)
return {
props: {
page: 1, // current page is 1
posts,
tags
},
revalidate: 1
}
}
const blog = ({ posts, page, tags }) => {
return (
<DefaultLayout tags={tags} posts={posts} page={page} />
)
}
export default blog

63
pages/page/[page].js Normal file
View File

@@ -0,0 +1,63 @@
import { getAllPosts, getAllTags } from '@/lib/notion'
import BLOG from '@/blog.config'
import DefaultLayout from '@/layouts/DefaultLayout'
import { useRouter } from 'next/router'
const Page = ({ posts, tags, page }) => {
let filteredBlogPosts = posts
if (posts) {
const router = useRouter()
if (router.query && router.query.s) {
filteredBlogPosts = posts.filter(post => {
const tagContent = post.tags ? post.tags.join(' ') : ''
const searchContent = post.title + post.summary + tagContent
return searchContent.toLowerCase().includes(router.query.s.toLowerCase())
})
}
}
return <DefaultLayout tags={tags} posts={filteredBlogPosts} page={page} />
}
export async function getStaticProps (context) {
const { page } = context.params // Get Current Page No.
let posts = await getAllPosts()
posts = posts.filter(
post => post.status[0] === 'Published' && post.type[0] === 'Post'
)
const tags = await getAllTags(posts)
return {
props: {
tags,
posts,
page
},
revalidate: 1
}
}
export async function getStaticPaths () {
if (BLOG.isProd) {
// 预渲染
let posts = await getAllPosts()
posts = posts.filter(
post => post.status[0] === 'Published' && post.type[0] === 'Post'
)
const totalPosts = posts.length
const totalPages = Math.ceil(totalPosts / BLOG.postsPerPage)
return {
// remove first page, we 're not gonna handle that.
paths: Array.from({ length: totalPages - 1 }, (_, i) => ({
params: { page: '' + (i + 2) }
})),
fallback: true
}
} else {
return {
paths: [],
fallback: true
}
}
}
export default Page

43
pages/tag/[tag].js Normal file
View File

@@ -0,0 +1,43 @@
import { getAllPosts, getAllTags } from '@/lib/notion'
import DefaultLayout from '@/layouts/DefaultLayout'
import BLOG from '@/blog.config'
export default function Tag ({ tags, posts, currentTag }) {
return <DefaultLayout tags={tags} posts={posts} currentTag={currentTag} />
}
export async function getStaticProps ({ params }) {
const currentTag = params.tag
let posts = await getAllPosts()
posts = posts.filter(
post => post.status[0] === 'Published' && post.type[0] === 'Post'
)
const tags = await getAllTags(posts)
const filteredPosts = posts.filter(
post => post && post.tags && post.tags.includes(currentTag)
)
return {
props: {
tags,
posts: filteredPosts,
currentTag
},
revalidate: 1
}
}
export async function getStaticPaths () {
if (BLOG.isProd) {
// 预渲染
const tags = await getAllTags()
return {
paths: Object.keys(tags).map(tag => ({ params: { tag } })),
fallback: true
}
} else {
return {
paths: [],
fallback: true
}
}
}