mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-04 15:10:23 +00:00
Code🤣
This commit is contained in:
31
pages/404.js
Normal file
31
pages/404.js
Normal 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
37
pages/_app.js
Normal 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
119
pages/_document.js
Normal 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
60
pages/article/[slug].js
Normal 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
19
pages/feed.js
Normal 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
27
pages/index.js
Normal 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
63
pages/page/[page].js
Normal 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
43
pages/tag/[tag].js
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user