mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-09 07:26:47 +00:00
Merge branch 'feature/link-outer-page' into develop
This commit is contained in:
37
lib/notion/getNotion.js
Normal file
37
lib/notion/getNotion.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import BLOG from '@/blog.config'
|
||||||
|
import { idToUuid } from 'notion-utils'
|
||||||
|
import formatDate from '../formatDate'
|
||||||
|
import { getPostBlocks } from './getPostBlocks'
|
||||||
|
import { defaultMapImageUrl } from 'react-notion-x'
|
||||||
|
|
||||||
|
export async function getNotion(pageId) {
|
||||||
|
const blockMap = await getPostBlocks(pageId, 'slug')
|
||||||
|
if (!blockMap) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const postInfo = blockMap?.block?.[idToUuid(pageId)].value
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: pageId,
|
||||||
|
type: postInfo,
|
||||||
|
category: '',
|
||||||
|
tags: [],
|
||||||
|
title: postInfo?.properties?.title?.[0],
|
||||||
|
status: 'Published',
|
||||||
|
createdTime: formatDate(new Date(postInfo.created_time).toString(), BLOG.LANG),
|
||||||
|
lastEditedTime: formatDate(new Date(postInfo?.last_edited_time).toString(), BLOG.LANG),
|
||||||
|
fullWidth: false,
|
||||||
|
page_cover: getPageCover(postInfo),
|
||||||
|
date: { start_date: formatDate(new Date(postInfo?.last_edited_time).toString(), BLOG.LANG) },
|
||||||
|
blockMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPageCover(postInfo) {
|
||||||
|
const pageCover = postInfo.format?.page_cover
|
||||||
|
if (pageCover) {
|
||||||
|
if (pageCover.startsWith('/')) return 'https://www.notion.so' + pageCover
|
||||||
|
if (pageCover.startsWith('http')) return defaultMapImageUrl(pageCover, postInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import BLOG from '@/blog.config'
|
|||||||
import formatDate from '../formatDate'
|
import formatDate from '../formatDate'
|
||||||
import { defaultMapImageUrl } from 'react-notion-x'
|
import { defaultMapImageUrl } from 'react-notion-x'
|
||||||
|
|
||||||
async function getPageProperties(id, block, schema, authToken, tagOptions, siteInfo) {
|
export default async function getPageProperties(id, block, schema, authToken, tagOptions, siteInfo) {
|
||||||
const rawProperties = Object.entries(block?.[id]?.value?.properties || [])
|
const rawProperties = Object.entries(block?.[id]?.value?.properties || [])
|
||||||
const excludeProperties = ['date', 'select', 'multi_select', 'person']
|
const excludeProperties = ['date', 'select', 'multi_select', 'person']
|
||||||
const value = block[id]?.value
|
const value = block[id]?.value
|
||||||
@@ -96,5 +96,3 @@ async function getPageProperties(id, block, schema, authToken, tagOptions, siteI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getPageProperties as default }
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export async function getPostBlocks(id, from, slice) {
|
|||||||
* @param {*} id
|
* @param {*} id
|
||||||
* @param {*} retryAttempts
|
* @param {*} retryAttempts
|
||||||
*/
|
*/
|
||||||
async function getPageWithRetry(id, from, retryAttempts = 3) {
|
export async function getPageWithRetry(id, from, retryAttempts = 3) {
|
||||||
if (retryAttempts && retryAttempts > 0) {
|
if (retryAttempts && retryAttempts > 0) {
|
||||||
console.log('[请求API]', `from:${from}`, `id:${id}`, retryAttempts < 3 ? `剩余重试次数:${retryAttempts}` : '')
|
console.log('[请求API]', `from:${from}`, `id:${id}`, retryAttempts < 3 ? `剩余重试次数:${retryAttempts}` : '')
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import React from 'react'
|
|||||||
import { idToUuid } from 'notion-utils'
|
import { idToUuid } from 'notion-utils'
|
||||||
import Router from 'next/router'
|
import Router from 'next/router'
|
||||||
import { isBrowser } from '@/lib/utils'
|
import { isBrowser } from '@/lib/utils'
|
||||||
|
import { getNotion } from '@/lib/notion/getNotion'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据notion的slug访问页面
|
* 根据notion的slug访问页面
|
||||||
@@ -26,11 +27,11 @@ const Slug = props => {
|
|||||||
const article = document.getElementById('container')
|
const article = document.getElementById('container')
|
||||||
if (!article) {
|
if (!article) {
|
||||||
router.push('/404').then(() => {
|
router.push('/404').then(() => {
|
||||||
// console.warn('找不到页面', router.asPath)
|
console.warn('找不到页面', router.asPath)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 10000)
|
}, 20 * 1000)
|
||||||
const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading`, image: siteInfo?.pageCover }
|
const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading`, image: siteInfo?.pageCover }
|
||||||
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={true} meta={meta} />
|
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={true} meta={meta} />
|
||||||
}
|
}
|
||||||
@@ -62,7 +63,7 @@ const Slug = props => {
|
|||||||
const meta = {
|
const meta = {
|
||||||
title: `${post?.title} | ${siteInfo?.title}`,
|
title: `${post?.title} | ${siteInfo?.title}`,
|
||||||
description: post?.summary,
|
description: post?.summary,
|
||||||
type: post.type,
|
type: post?.type,
|
||||||
slug: post?.slug,
|
slug: post?.slug,
|
||||||
image: post?.page_cover,
|
image: post?.page_cover,
|
||||||
category: post?.category?.[0],
|
category: post?.category?.[0],
|
||||||
@@ -102,11 +103,17 @@ export async function getStaticProps({ params: { slug } }) {
|
|||||||
props.post = props.allPages.find((p) => {
|
props.post = props.allPages.find((p) => {
|
||||||
return p.slug === fullSlug || p.id === idToUuid(fullSlug)
|
return p.slug === fullSlug || p.id === idToUuid(fullSlug)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!props.post) {
|
if (!props.post) {
|
||||||
console.warn('无效地址', fullSlug)
|
const post = await getNotion(slug.slice(-1)[0])
|
||||||
return { props, revalidate: 1 }
|
if (post) {
|
||||||
|
props.post = post
|
||||||
|
} else {
|
||||||
|
return { props, revalidate: 1 }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
props.post.blockMap = await getPostBlocks(props.post.id, 'slug')
|
||||||
}
|
}
|
||||||
props.post.blockMap = await getPostBlocks(props.post.id, 'slug')
|
|
||||||
|
|
||||||
const allPosts = props.allPages.filter(page => page.type === 'Post')
|
const allPosts = props.allPages.filter(page => page.type === 'Post')
|
||||||
const index = allPosts.indexOf(props.post)
|
const index = allPosts.indexOf(props.post)
|
||||||
@@ -134,7 +141,7 @@ export async function getStaticProps({ params: { slug } }) {
|
|||||||
function getRecommendPost(post, allPosts, count = 6) {
|
function getRecommendPost(post, allPosts, count = 6) {
|
||||||
let recommendPosts = []
|
let recommendPosts = []
|
||||||
const postIds = []
|
const postIds = []
|
||||||
const currentTags = post.tags || []
|
const currentTags = post?.tags || []
|
||||||
for (let i = 0; i < allPosts.length; i++) {
|
for (let i = 0; i < allPosts.length; i++) {
|
||||||
const p = allPosts[i]
|
const p = allPosts[i]
|
||||||
if (p.id === post.id || p.type.indexOf('Post') < 0) {
|
if (p.id === post.id || p.type.indexOf('Post') < 0) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const ArticleInfo = (props) => {
|
|||||||
|
|
||||||
return <section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
return <section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||||
<div>
|
<div>
|
||||||
{post?.type[0] !== 'Page' && <>
|
{post?.type !== 'Page' && <>
|
||||||
<Link href={`/category/${post.category}`} passHref>
|
<Link href={`/category/${post.category}`} passHref>
|
||||||
<a className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
<a className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||||
<i className="mr-1 fas fa-folder-open" />
|
<i className="mr-1 fas fa-folder-open" />
|
||||||
@@ -20,7 +20,7 @@ export const ArticleInfo = (props) => {
|
|||||||
<span className='mr-2'>|</span>
|
<span className='mr-2'>|</span>
|
||||||
</>}
|
</>}
|
||||||
|
|
||||||
{post?.type[0] !== 'Page' && (<>
|
{post?.type !== 'Page' && (<>
|
||||||
<Link
|
<Link
|
||||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||||
passHref
|
passHref
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default function ArticleDetail(props) {
|
|||||||
<span className='mr-2'>|</span>
|
<span className='mr-2'>|</span>
|
||||||
</>)}
|
</>)}
|
||||||
|
|
||||||
{post?.type[0] !== 'Page' && (<>
|
{post?.type !== 'Page' && (<>
|
||||||
<Link
|
<Link
|
||||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||||
passHref
|
passHref
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import BLOG from '@/blog.config'
|
|||||||
export const LayoutCategory = props => {
|
export const LayoutCategory = props => {
|
||||||
const { category } = props
|
const { category } = props
|
||||||
return <LayoutBase {...props}>
|
return <LayoutBase {...props}>
|
||||||
<div className="cursor-pointer px-5 py-1 mb-2 font-light hover:underline hover:text-indigo-700 dark:hover:text-indigo-400 transform text-center dark:text-white">
|
<div className="cursor-pointer text-lg px-5 py-1 mb-2 font-light hover:text-indigo-700 dark:hover:text-indigo-400 transform dark:text-white">
|
||||||
<i className="mr-1 far fa-folder" />
|
<i className="mr-1 far fa-folder-open" />
|
||||||
{category}
|
{category}
|
||||||
</div>
|
</div>
|
||||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||||
|
|||||||
@@ -2,18 +2,23 @@ import BLOG from '@/blog.config'
|
|||||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||||
import BlogPostListPage from './components/BlogPostListPage'
|
import BlogPostListPage from './components/BlogPostListPage'
|
||||||
import LayoutBase from './LayoutBase'
|
import LayoutBase from './LayoutBase'
|
||||||
import TagItemMini from '../next/components/TagItemMini'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
export const LayoutTag = (props) => {
|
export const LayoutTag = (props) => {
|
||||||
const currentTag = props.tags.find((t) => {
|
const tag = props.tags.find((t) => {
|
||||||
return t.name === props.tag
|
return t.name === props.tag
|
||||||
})
|
})
|
||||||
|
|
||||||
return <LayoutBase {...props}>
|
return <LayoutBase {...props}>
|
||||||
{currentTag && (
|
{tag && (
|
||||||
<div className="cursor-pointer px-5 py-1 mb-2 font-light hover:underline hover:text-indigo-700 dark:hover:text-indigo-400 transform text-center dark:text-white">
|
<div className="cursor-pointer px-3 py-2 mb-2 font-light hover:text-indigo-700 dark:hover:text-indigo-400 transform dark:text-white">
|
||||||
<TagItemMini tag={currentTag} />
|
<Link key={tag} href={`/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||||
|
<a className={`cursor-pointer inline-block rounded duration-200
|
||||||
|
mr-2 py-0.5 px-1 text-xl whitespace-nowrap ` }>
|
||||||
|
<div className='font-light dark:text-gray-400 dark:hover:text-white'> #{tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default function HeaderArticle({ post, siteInfo }) {
|
|||||||
</>}
|
</>}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex justify-center'>
|
<div className='flex justify-center'>
|
||||||
{post?.type[0] !== 'Page' && (
|
{post?.type !== 'Page' && (
|
||||||
<>
|
<>
|
||||||
<Link
|
<Link
|
||||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function ArticleDetail(props) {
|
|||||||
>
|
>
|
||||||
|
|
||||||
{showArticleInfo && <header className='animate__slideInDown animate__animated'>
|
{showArticleInfo && <header className='animate__slideInDown animate__animated'>
|
||||||
{post?.type && !post?.type.includes('Page') && post?.page_cover && (
|
{post?.type && !post?.type !== 'Page' && post?.page_cover && (
|
||||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||||
@@ -51,7 +51,7 @@ export default function ArticleDetail(props) {
|
|||||||
</Link>
|
</Link>
|
||||||
<span className='mr-2'>|</span>
|
<span className='mr-2'>|</span>
|
||||||
</>}
|
</>}
|
||||||
{post?.type[0] !== 'Page' && (<>
|
{post?.type !== 'Page' && (<>
|
||||||
<Link
|
<Link
|
||||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||||
passHref
|
passHref
|
||||||
|
|||||||
Reference in New Issue
Block a user