Files
NotionNext/pages/[prefix]/index.js

210 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import BLOG from '@/blog.config'
import useNotification from '@/components/Notification'
import OpenWrite from '@/components/OpenWrite'
import { siteConfig } from '@/lib/config'
import { getGlobalData, getPost, getPostBlocks } from '@/lib/db/getSiteData'
import { useGlobal } from '@/lib/global'
import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents'
import { getPasswordQuery } from '@/lib/password'
import { uploadDataToAlgolia } from '@/lib/plugins/algolia'
import { checkSlugHasNoSlash, getRecommendPost } from '@/lib/utils/post'
import { DynamicLayout } from '@/themes/theme'
import md5 from 'js-md5'
import { useRouter } from 'next/router'
import { idToUuid } from 'notion-utils'
import { useEffect, useState } from 'react'
/**
* 根据notion的slug访问页面
* 只解析一级目录例如 /about
* @param {*} props
* @returns
*/
const Slug = props => {
const { post } = props
const router = useRouter()
const { locale } = useGlobal()
// 文章锁🔐
const [lock, setLock] = useState(post?.password && post?.password !== '')
const { showNotification, Notification } = useNotification()
/**
* 验证文章密码
* @param {*} passInput
*/
const validPassword = passInput => {
if (!post) {
return false
}
const encrypt = md5(post?.slug + passInput)
if (passInput && encrypt === post?.password) {
setLock(false)
// 输入密码存入localStorage下次自动提交
localStorage.setItem('password_' + router.asPath, passInput)
showNotification(locale.COMMON.ARTICLE_UNLOCK_TIPS) // 设置解锁成功提示显示
return true
}
return false
}
// 文章加载
useEffect(() => {
// 文章加密
if (post?.password && post?.password !== '') {
setLock(true)
} else {
setLock(false)
}
// 读取上次记录 自动提交密码
const passInputs = getPasswordQuery(router.asPath)
if (passInputs.length > 0) {
for (const passInput of passInputs) {
if (validPassword(passInput)) {
break // 密码验证成功,停止尝试
}
}
}
}, [post])
// 文章加载
useEffect(() => {
if (lock) {
return
}
// 文章解锁后生成目录与内容
if (post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block).filter(
key => post.blockMap.block[key]?.value?.parent_id === post.id
)
post.toc = getPageTableOfContents(post, post.blockMap)
}
}, [router, lock])
props = { ...props, lock, validPassword }
const theme = siteConfig('THEME', BLOG.THEME, props.NOTION_CONFIG)
return (
<>
{/* 文章布局 */}
<DynamicLayout theme={theme} layoutName='LayoutSlug' {...props} />
{/* 解锁密码提示框 */}
{post?.password && post?.password !== '' && !lock && <Notification />}
{/* 导流工具 */}
<OpenWrite />
</>
)
}
export async function getStaticPaths() {
if (!BLOG.isProd) {
return {
paths: [],
fallback: true
}
}
const from = 'slug-paths'
const { allPages } = await getGlobalData({ from })
const paths = allPages
?.filter(row => checkSlugHasNoSlash(row))
.map(row => ({ params: { prefix: row.slug } }))
return {
paths: paths,
fallback: true
}
}
export async function getStaticProps({ params: { prefix }, locale }) {
let fullSlug = prefix
const from = `slug-props-${fullSlug}`
const props = await getGlobalData({ from, locale })
if (siteConfig('PSEUDO_STATIC', false, props.NOTION_CONFIG)) {
if (!fullSlug.endsWith('.html')) {
fullSlug += '.html'
}
}
// 在列表内查找文章
props.post = props?.allPages?.find(p => {
return (
p.type.indexOf('Menu') < 0 &&
(p.slug === prefix || p.id === idToUuid(prefix))
)
})
// 处理非列表内文章的内信息
if (!props?.post) {
const pageId = prefix
if (pageId.length >= 32) {
const post = await getPost(pageId)
props.post = post
}
}
// 无法获取文章
if (!props?.post) {
props.post = null
return {
props,
revalidate: process.env.EXPORT
? undefined
: siteConfig(
'NEXT_REVALIDATE_SECOND',
BLOG.NEXT_REVALIDATE_SECOND,
props.NOTION_CONFIG
)
}
}
// 文章内容加载
if (!props?.post?.blockMap) {
props.post.blockMap = await getPostBlocks(props.post.id, from)
}
// 目录默认加载
if (props.post?.blockMap?.block) {
props.post.content = Object.keys(props.post.blockMap.block).filter(
key => props.post.blockMap.block[key]?.value?.parent_id === props.post.id
)
props.post.toc = getPageTableOfContents(props.post, props.post.blockMap)
}
// 生成全文索引 && process.env.npm_lifecycle_event === 'build' && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA)
if (BLOG.ALGOLIA_APP_ID) {
uploadDataToAlgolia(props?.post)
}
// 推荐关联文章处理
const allPosts = props.allPages?.filter(
page => page.type === 'Post' && page.status === 'Published'
)
if (allPosts && allPosts.length > 0) {
const index = allPosts.indexOf(props.post)
props.prev = allPosts.slice(index - 1, index)[0] ?? allPosts.slice(-1)[0]
props.next = allPosts.slice(index + 1, index + 2)[0] ?? allPosts[0]
props.recommendPosts = getRecommendPost(
props.post,
allPosts,
siteConfig('POST_RECOMMEND_COUNT')
)
} else {
props.prev = null
props.next = null
props.recommendPosts = []
}
delete props.allPages
return {
props,
revalidate: process.env.EXPORT
? undefined
: siteConfig(
'NEXT_REVALIDATE_SECOND',
BLOG.NEXT_REVALIDATE_SECOND,
props.NOTION_CONFIG
)
}
}
export default Slug