diff --git a/blog.config.js b/blog.config.js index 212b2801..e0fd64c7 100644 --- a/blog.config.js +++ b/blog.config.js @@ -31,6 +31,9 @@ const BLOG = { BACKGROUND_DARK: '#000000', // use hex value, don't forget '#' SUB_PATH: '', // leave this empty unless you want to deploy in a folder + POST_URL_PREFIX: process.env.NEXT_PUBLIC_POST_URL_PREFIX || 'article', // POST类型文章的默认路径前缀,例如默认POST类型的路径是 /article/[slug] + // 如果此项配置为 '' 空, 则文章将没有前缀路径,使用场景: 希望 文章前缀路径为 /post 的情况 支持多级 + POST_LIST_STYLE: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载 POST_LIST_PREVIEW: process.env.NEXT_PUBLIC_POST_PREVIEW || 'false', // 是否在列表加载文章预览 POST_PREVIEW_LINES: 12, // 预览博客行数 diff --git a/components/CommonHead.js b/components/CommonHead.js index d8aea1fc..de4c7d25 100644 --- a/components/CommonHead.js +++ b/components/CommonHead.js @@ -44,7 +44,7 @@ const CommonHead = ({ meta, children }) => { {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && } - {meta?.type === 'article' && ( + {meta?.type === 'Post' && ( <> { // return 'https://www.notion.so/' + id.replace(/-/g, '') - return '/article/' + id.replace(/-/g, '') + return '/' + id.replace(/-/g, '') } function getMediumZoomMargin() { diff --git a/lib/notion/getAllTags.js b/lib/notion/getAllTags.js index 33e82f51..098f62fb 100644 --- a/lib/notion/getAllTags.js +++ b/lib/notion/getAllTags.js @@ -7,7 +7,9 @@ import { isIterable } from '../utils' * @param tagOptions tags的下拉选项 * @returns {Promise<{}|*[]>} */ -export function getAllTags({ allPosts, sliceCount = 0, tagOptions }) { +export function getAllTags({ allPages, sliceCount = 0, tagOptions }) { + const allPosts = allPages.filter(page => page.type === 'Post') + if (!allPosts || !tagOptions) { return [] } diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js index 177c4900..21a43c37 100644 --- a/lib/notion/getNotionData.js +++ b/lib/notion/getNotionData.js @@ -21,8 +21,7 @@ import getPageProperties from './getPageProperties' */ export async function getGlobalNotionData({ pageId = BLOG.NOTION_PAGE_ID, - from, - pageType = ['Post'] + from }) { // 获取Notion数据 const notionPageData = deepClone(await getNotionPageData({ pageId, from })) @@ -42,7 +41,9 @@ export async function getGlobalNotionData({ * @param {*}} param0 * @returns */ -function getLatestPosts({ allPosts, from, latestPostCount }) { +function getLatestPosts({ allPages, from, latestPostCount }) { + const allPosts = allPages.filter(page => page.type === 'Post') + const latestPosts = Object.create(allPosts).sort((a, b) => { const dateA = new Date(a?.lastEditedTime || a?.createdTime || a?.date?.start_date) const dateB = new Date(b?.lastEditedTime || b?.createdTime || b?.date?.start_date) @@ -82,7 +83,7 @@ function getCustomNav({ allPages }) { const customNav = [] if (allPages && allPages.length > 0) { allPages.forEach(p => { - if (p?.status?.[0] === 'Published') { + if (p?.status === 'Published' && p?.type === 'Page') { if (p?.slug?.indexOf('http') === 0) { customNav.push({ icon: p.icon || null, name: p.title, to: p.slug, show: true }) } else { @@ -101,7 +102,7 @@ function getCustomNav({ allPages }) { */ function getTagOptions(schema) { if (!schema) return {} - const tagSchema = Object.values(schema).find(e => e.name === 'tags') + const tagSchema = Object.values(schema).find(e => e.name === BLOG.NOTION_PROPERTY_NAME.tags) return tagSchema?.options || [] } @@ -112,7 +113,7 @@ function getTagOptions(schema) { */ function getCategoryOptions(schema) { if (!schema) return {} - const categorySchema = Object.values(schema).find(e => e.name === 'category') + const categorySchema = Object.values(schema).find(e => e.name === BLOG.NOTION_PROPERTY_NAME.category) return categorySchema?.options || [] } @@ -121,7 +122,8 @@ function getCategoryOptions(schema) { * @param allPosts * @returns {Promise<{}|*[]>} */ -function getAllCategories({ allPosts, categoryOptions, sliceCount = 0 }) { +function getAllCategories({ allPages, categoryOptions, sliceCount = 0 }) { + const allPosts = allPages.filter(page => page.type === 'Post') if (!allPosts || !categoryOptions) { return [] } @@ -220,7 +222,7 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) { // Check Type Page-Database和Inline-Database if ( rawMetadata?.type !== 'collection_view_page' && - rawMetadata?.type !== 'collection_view' + rawMetadata?.type !== 'collection_view' ) { console.warn(`pageId "${pageId}" is not a database`) return null @@ -252,24 +254,23 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) { } } // 读取映射 配置 - console.log('当前Notion映射配置-(在blog.config.js中配置)', BLOG.NOTION_PROPERTY_NAME) - const { type, status } = BLOG.NOTION_PROPERTY_NAME + let postCount = 0 const allPages = collectionData.filter(post => { - return post && post[type] && - ['Page'].indexOf(post[type]?.[0]) > -1 && - (post[status]?.[0] === 'Published' || post[status]?.[0] === 'Invisible') - }) - const allPosts = collectionData.filter(post => { - return post && post[status] && - ['Post'].indexOf(post[type]?.[0]) > -1 && - post[status]?.[0] === 'Published' - }) - console.log('全部单页', allPages.length, '全部博客', allPosts.length) + if (post.type === 'Post' && (post.status === 'Published' || post.status === 'Invisible')) { + postCount++ + } + + return post && + post.type && + (post.type === 'Post' || post.type === 'Page') && + (post.status === 'Published' || post.status === 'Invisible') + } + ) // Sort by date if (BLOG.POSTS_SORT_BY === 'date') { - allPosts.sort((a, b) => { + allPages.sort((a, b) => { const dateA = new Date(a?.date?.start_date || a.createdTime) const dateB = new Date(b?.date?.start_date || b.createdTime) return dateB - dateA @@ -277,15 +278,13 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) { } const customNav = getCustomNav({ allPages }) - const postCount = allPosts?.length || 0 - const categories = getAllCategories({ allPosts, categoryOptions, sliceCount: BLOG.PREVIEW_CATEGORY_COUNT }) - const tags = getAllTags({ allPosts, tagOptions, sliceCount: BLOG.PREVIEW_TAG_COUNT }) - const latestPosts = getLatestPosts({ allPosts, from, latestPostCount: 5 }) + const categories = getAllCategories({ allPages, categoryOptions, sliceCount: BLOG.PREVIEW_CATEGORY_COUNT }) + const tags = getAllTags({ allPages, tagOptions, sliceCount: BLOG.PREVIEW_TAG_COUNT }) + const latestPosts = getLatestPosts({ allPages, from, latestPostCount: 5 }) return { siteInfo, allPages, - allPosts, collection, collectionQuery, collectionId, diff --git a/lib/notion/getPageProperties.js b/lib/notion/getPageProperties.js index 33324928..4061632c 100644 --- a/lib/notion/getPageProperties.js +++ b/lib/notion/getPageProperties.js @@ -58,6 +58,7 @@ async function getPageProperties(id, block, schema, authToken, tagOptions, siteI } } } + // 设置自定义字段 const fieldNames = BLOG.NOTION_PROPERTY_NAME if (fieldNames) { @@ -65,7 +66,16 @@ async function getPageProperties(id, block, schema, authToken, tagOptions, siteI if (fieldNames[key] && properties[fieldNames[key]]) properties[key] = properties[fieldNames[key]] }) } - properties.slug = properties.slug ?? properties.id + + properties.type = properties.type[0] + properties.status = properties.status[0] + + if (properties.type === 'Post') { + properties.slug = BLOG.POST_URL_PREFIX + '/' + (properties.slug ?? properties.id) + } else { + properties.slug = (properties.slug ?? properties.id) + } + properties.createdTime = formatDate(new Date(value.created_time).toString(), BLOG.LANG) properties.lastEditedTime = formatDate(new Date(value?.last_edited_time).toString(), BLOG.LANG) properties.fullWidth = value.format?.page_full_width ?? false diff --git a/lib/rss.js b/lib/rss.js index 9c394c2c..9019f061 100644 --- a/lib/rss.js +++ b/lib/rss.js @@ -38,7 +38,7 @@ export async function generateRss(posts) { feed.addItem({ title: post.title, guid: `${post.id}`, - link: `${BLOG.LINK}/article/${post.slug}`, + link: `${BLOG.LINK}/${post.slug}`, description: post.summary, content: await createFeedContent(post), date: new Date(post?.date?.start_date || post?.createdTime) diff --git a/pages/article/[slug].js b/pages/[...slug].js similarity index 90% rename from pages/article/[slug].js rename to pages/[...slug].js index a0f2bb55..0cef2223 100644 --- a/pages/article/[slug].js +++ b/pages/[...slug].js @@ -62,8 +62,8 @@ const Slug = props => { const meta = { title: `${post?.title} | ${siteInfo?.title}`, description: post?.summary, - type: 'article', - slug: 'article/' + post?.slug, + type: post.type, + slug: post?.slug, image: post?.page_cover, category: post?.category?.[0], tags: post?.tags @@ -95,13 +95,16 @@ export async function getStaticPaths() { } export async function getStaticProps({ params: { slug } }) { - const from = `slug-props-${slug}` + // slug 是个数组 + const fullSlug = slug.join('/') + const from = `slug-props-${fullSlug}` const props = await getGlobalNotionData({ from, pageType: ['Post'] }) - const allPosts = props.allPosts - props.post = props.allPosts.find((p) => { - return p.slug === slug || p.id === idToUuid(slug) + const allPosts = props.allPages.filter(page => page.type === 'Post') + props.post = allPosts.find((p) => { + return p.slug === fullSlug || p.id === idToUuid(fullSlug) }) if (!props.post) { + console.warn('无效地址', fullSlug) return { props, revalidate: 1 } } props.post.blockMap = await getPostBlocks(props.post.id, 'slug') @@ -114,6 +117,7 @@ export async function getStaticProps({ params: { slug } }) { allPosts, BLOG.POST_RECOMMEND_COUNT ) + delete props.allPages return { props, revalidate: 1 diff --git a/pages/[slug].js b/pages/[slug].js deleted file mode 100644 index 64b949e9..00000000 --- a/pages/[slug].js +++ /dev/null @@ -1,115 +0,0 @@ -import BLOG from '@/blog.config' -import { getPostBlocks } from '@/lib/notion' -import { getGlobalNotionData } from '@/lib/notion/getNotionData' -import { useGlobal } from '@/lib/global' -import * as ThemeMap from '@/themes' -import React from 'react' -import { useRouter } from 'next/router' -import { isBrowser } from '@/lib/utils' - -/** - * 根据notion的slug访问页面,针对类型为Page的页面 - * @param {*} props - * @returns - */ -const Slug = props => { - const { theme, changeLoadingState } = useGlobal() - const ThemeComponents = ThemeMap[theme] - const { post } = props - - if (!post) { - changeLoadingState(true) - const router = useRouter() - setTimeout(() => { - if (isBrowser()) { - const article = document.getElementById('container') - if (!article) { - router.push('/404').then(() => { - console.warn('找不到页面', router.asPath) - }) - } - } - }, 5000) - const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading` } - return - } - - changeLoadingState(false) - - // 文章锁🔐 - const [lock, setLock] = React.useState(post.password && post.password !== '') - React.useEffect(() => { - if (post.password && post.password !== '') { - setLock(true) - } else { - setLock(false) - } - }, [post]) - - /** - * 验证文章密码 - * @param {*} result - */ - const validPassword = result => { - if (result) { - setLock(false) - } - } - - const { siteInfo } = props - const meta = { - title: `${post?.title} | ${siteInfo?.title}`, - description: post?.summary, - type: 'article', - slug: 'article/' + post?.slug, - image: post?.page_cover, - category: post?.category?.[0], - tags: post?.tags - } - - props = { ...props, meta, lock, setLock, validPassword } - - return -} - -export async function getStaticPaths() { - if (!BLOG.isProd) { - return { - paths: [], - fallback: true - } - } - - const from = 'slug-paths' - const { allPages } = await getGlobalNotionData({ from, pageType: ['Page'] }) - - return { - paths: allPages.map(row => ({ params: { slug: row.slug } })), - fallback: true - } -} - -export async function getStaticProps({ params: { slug } }) { - const from = `slug-props-${slug}` - const props = await getGlobalNotionData({ from, pageType: ['Page'] }) - const { allPages } = props - const page = allPages?.find(p => p.slug === slug) - if (!page) { - return { props: {}, revalidate: 1 } - } - - try { - page.blockMap = await getPostBlocks(page.id, 'slug') - } catch (error) { - console.error('获取文章详情失败', error) - } - - props.post = page - - return { - props, - revalidate: 1 - } -} - -export default Slug diff --git a/pages/index.js b/pages/index.js index bc519e2c..3c49f983 100644 --- a/pages/index.js +++ b/pages/index.js @@ -11,8 +11,9 @@ const Index = props => { export async function getStaticProps() { const from = 'index' - const props = await getGlobalNotionData({ from, pageType: ['Post'] }) - const { allPosts, siteInfo } = props + const props = await getGlobalNotionData({ from }) + const { allPages, siteInfo } = props + const allPosts = allPages.filter(page => page.type === 'Post') const meta = { title: `${siteInfo?.title} | ${siteInfo?.description}`, description: siteInfo?.description, diff --git a/themes/example/LayoutArchive.js b/themes/example/LayoutArchive.js index a8bc68ee..b85860e0 100644 --- a/themes/example/LayoutArchive.js +++ b/themes/example/LayoutArchive.js @@ -43,7 +43,7 @@ export const LayoutArchive = props => { {' '}   diff --git a/themes/example/LayoutCategory.js b/themes/example/LayoutCategory.js index ef344ea2..a9c99d90 100644 --- a/themes/example/LayoutCategory.js +++ b/themes/example/LayoutCategory.js @@ -30,7 +30,7 @@ export const LayoutCategory = props => { {postsToShow.map(p => (

- + {p.title}

diff --git a/themes/example/LayoutSearch.js b/themes/example/LayoutSearch.js index 29a07f99..7c5dbafb 100644 --- a/themes/example/LayoutSearch.js +++ b/themes/example/LayoutSearch.js @@ -62,7 +62,7 @@ export const LayoutSearch = props => { {postsToShow.map(p => (

- + {p.title}

diff --git a/themes/example/LayoutTag.js b/themes/example/LayoutTag.js index e9809123..f60653e3 100644 --- a/themes/example/LayoutTag.js +++ b/themes/example/LayoutTag.js @@ -28,7 +28,7 @@ export const LayoutTag = props => { {postsToShow.map(p => (

- + {p.title}

diff --git a/themes/example/components/BlogList.js b/themes/example/components/BlogList.js index ec2e7a88..1a45d6f7 100644 --- a/themes/example/components/BlogList.js +++ b/themes/example/components/BlogList.js @@ -23,7 +23,7 @@ export const BlogList = (props) => { {posts.map(p => (

- + {p.title}

diff --git a/themes/example/components/SideBar.js b/themes/example/components/SideBar.js index 0e90fe1c..0e737fa3 100644 --- a/themes/example/components/SideBar.js +++ b/themes/example/components/SideBar.js @@ -30,7 +30,7 @@ export const SideBar = (props) => {