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 (
<>
{/* 文章布局 */}
{/* 解锁密码提示框 */}
{post?.password && post?.password !== '' && !lock && }
{/* 导流工具 */}
>
)
}
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