mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
@@ -151,10 +151,10 @@ function getCategoryOptions(schema) {
|
||||
* @param from
|
||||
* @returns {Promise<{title,description,pageCover,icon}>}
|
||||
*/
|
||||
function getBlogInfo({ collection, block }) {
|
||||
function getSiteInfo({ collection, block }) {
|
||||
const title = collection?.name?.[0][0] || BLOG.TITLE
|
||||
const description = collection?.description ? Object.assign(collection).description[0][0] : BLOG.DESCRIPTION
|
||||
const pageCover = collection?.cover ? (mapImgUrl(collection?.cover, block[idToUuid(BLOG.NOTION_PAGE_ID)]?.value)) : BLOG.HOME_BANNER_IMAGE
|
||||
const pageCover = collection?.cover ? mapImgUrl(collection?.cover, block[idToUuid(BLOG.NOTION_PAGE_ID)]?.value) : BLOG.HOME_BANNER_IMAGE
|
||||
let icon = collection?.icon ? mapImgUrl(collection?.icon, collection, 'collection') : BLOG.AVATAR
|
||||
|
||||
// 用户头像压缩一下
|
||||
@@ -181,7 +181,7 @@ async function getNotice(post) {
|
||||
const EmptyData = (pageId) => {
|
||||
const empty = {
|
||||
notice: null,
|
||||
siteInfo: getBlogInfo({}),
|
||||
siteInfo: getSiteInfo({}),
|
||||
allPages: [{ id: 1, title: `无法获取Notion数据,请检查Notion_ID: \n 当前 ${pageId}`, summary: '访问文档获取帮助→ https://tangly1024.com/article/vercel-deploy-notion-next', status: 'Published', type: 'Post', slug: '13a171332816461db29d50e9f575b00d', date: { start_date: '2023-04-24', lastEditedTime: '2023-04-24', tagItems: [] } }],
|
||||
collection: [],
|
||||
collectionQuery: {},
|
||||
@@ -223,7 +223,7 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) {
|
||||
return EmptyData(pageId)
|
||||
}
|
||||
const collection = Object.values(pageRecordMap.collection)[0]?.value || {}
|
||||
const siteInfo = getBlogInfo({ collection, block })
|
||||
const siteInfo = getSiteInfo({ collection, block })
|
||||
const collectionId = rawMetadata?.collection_id
|
||||
const collectionQuery = pageRecordMap.collection_query
|
||||
const collectionView = pageRecordMap.collection_view
|
||||
|
||||
@@ -2,9 +2,9 @@ import { getTextContent, getDateValue } from 'notion-utils'
|
||||
import { NotionAPI } from 'notion-client'
|
||||
import BLOG from '@/blog.config'
|
||||
import formatDate from '../formatDate'
|
||||
import { defaultMapImageUrl } from 'react-notion-x'
|
||||
// import { createHash } from 'crypto'
|
||||
import md5 from 'js-md5'
|
||||
import { mapImgUrl } from './mapImage'
|
||||
|
||||
export default async function getPageProperties(id, block, schema, authToken, tagOptions) {
|
||||
const rawProperties = Object.entries(block?.[id]?.value?.properties || [])
|
||||
@@ -96,8 +96,9 @@ export default async function getPageProperties(id, block, schema, authToken, ta
|
||||
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
|
||||
properties.pageIcon = getImageUrl(block[id].value?.format?.page_icon, block[id].value) ?? ''
|
||||
properties.page_cover = getImageUrl(block[id].value?.format?.page_cover, block[id].value) ?? ''
|
||||
properties.pageIcon = mapImgUrl(block[id].value?.format?.page_icon, block[id].value) ?? ''
|
||||
properties.pageCover = mapImgUrl(block[id].value?.format?.page_cover, block[id].value) ?? ''
|
||||
properties.pageCoverThumbnail = mapImgUrl(block[id].value?.format?.page_cover, block[id].value, 'block', 'pageCoverThumbnail') ?? ''
|
||||
properties.content = value.content ?? []
|
||||
properties.password = properties.password
|
||||
? md5(properties.slug + properties.password)
|
||||
@@ -109,27 +110,6 @@ export default async function getPageProperties(id, block, schema, authToken, ta
|
||||
return properties
|
||||
}
|
||||
|
||||
// 从Block获取封面图;优先取PageCover,否则取内容图片
|
||||
function getImageUrl(imgObj, blockVal) {
|
||||
if (!imgObj) {
|
||||
return null
|
||||
}
|
||||
if (imgObj.startsWith('/')) {
|
||||
return BLOG.NOTION_HOST + imgObj // notion内部图片转相对路径为绝对路径
|
||||
}
|
||||
|
||||
if (imgObj.startsWith('http')) {
|
||||
// 判断如果是notion上传的图片要拼接访问token
|
||||
const u = new URL(imgObj)
|
||||
if (u.pathname.startsWith('/secure.notion-static.com') && u.hostname.endsWith('.amazonaws.com')) {
|
||||
return defaultMapImageUrl(imgObj, blockVal) // notion上传的图片需要转换请求地址
|
||||
}
|
||||
}
|
||||
|
||||
// 其他图片链接 或 emoji
|
||||
return imgObj
|
||||
}
|
||||
|
||||
function mapProperties(properties) {
|
||||
if (properties?.type === BLOG.NOTION_PROPERTY_NAME.type_post) {
|
||||
properties.type = 'Post'
|
||||
|
||||
@@ -1,37 +1,74 @@
|
||||
import BLOG from '@/blog.config'
|
||||
|
||||
/**
|
||||
* notion图片可以通过指定url-query参数来压缩裁剪图片 例如 ?width=200
|
||||
* 压缩图片
|
||||
* 1. Notion图床可以通过指定url-query参数来压缩裁剪图片 例如 ?xx=xx&width=400
|
||||
* 2. UnPlash 图片可以通过api q=50 控制压缩质量 width=400 控制图片尺寸
|
||||
* @param {*} image
|
||||
*/
|
||||
const compressImage = (image) => {
|
||||
if (image && image.indexOf(BLOG.NOTION_HOST) === 0) {
|
||||
return image + '&width=200'
|
||||
const compressImage = (image, width = 400) => {
|
||||
if (!image) {
|
||||
return null
|
||||
}
|
||||
if (image.indexOf(BLOG.NOTION_HOST) === 0) {
|
||||
return `${image}&width=${width}`
|
||||
}
|
||||
// 压缩unsplash图片
|
||||
if (image.indexOf('https://images.unsplash.com/') === 0) {
|
||||
// 将URL解析为一个对象
|
||||
const urlObj = new URL(image)
|
||||
// 获取URL参数
|
||||
const params = new URLSearchParams(urlObj.search)
|
||||
// 将q参数的值替换
|
||||
params.set('q', '50')
|
||||
// 尺寸
|
||||
params.set('width', width)
|
||||
// 格式
|
||||
params.set('fmt', 'webp')
|
||||
// 生成新的URL
|
||||
urlObj.search = params.toString()
|
||||
return urlObj.toString()
|
||||
}
|
||||
|
||||
// 此处还可以添加您的自定义图传的封面图压缩参数。
|
||||
// .e.g
|
||||
if (image.indexOf('https://your_picture_bed') === 0) {
|
||||
return 'do_somethin_here'
|
||||
}
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
/**
|
||||
* Notion图片映射处理有emoji的图标
|
||||
* 图片映射
|
||||
* 1. 如果是 /xx.xx 相对路径格式,则转化为 完整notion域名图片
|
||||
* 2. 如果是 bookmark类型的block 图片封面无需处理
|
||||
* @param {*} img
|
||||
* @param {*} value
|
||||
* @returns
|
||||
*/
|
||||
const mapImgUrl = (img, block, type = 'block') => {
|
||||
let ret = null
|
||||
const mapImgUrl = (img, block, type = 'block', from) => {
|
||||
if (!img) {
|
||||
return ret
|
||||
return null
|
||||
}
|
||||
let ret = null
|
||||
// 相对目录,则视为notion的自带图片
|
||||
if (img.startsWith('/')) {
|
||||
ret = BLOG.NOTION_HOST + img
|
||||
}
|
||||
// 书签的地址本身就是永久链接,无需处理
|
||||
if (!ret && block?.type === 'bookmark') {
|
||||
} else {
|
||||
ret = img
|
||||
}
|
||||
// notion永久图床地址
|
||||
if (!ret && ret !== null && ret.indexOf('secure.notion-static.com') > 0 && (BLOG.IMG_URL_TYPE === 'Notion' || type !== 'block')) {
|
||||
|
||||
// Notion 图床转换为永久地址
|
||||
if (ret.indexOf('secure.notion-static.com') > 0 && (BLOG.IMG_URL_TYPE === 'Notion' || type !== 'block')) {
|
||||
ret = BLOG.NOTION_HOST + '/image/' + encodeURIComponent(ret) + '?table=' + type + '&id=' + block.id
|
||||
}
|
||||
|
||||
// 文章封面
|
||||
if (from === 'pageCoverThumbnail') {
|
||||
ret = compressImage(ret)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ const Slug = props => {
|
||||
description: post?.summary,
|
||||
type: post?.type,
|
||||
slug: post?.slug,
|
||||
image: post?.page_cover || (siteInfo?.pageCover || BLOG.HOME_BANNER_IMAGE),
|
||||
image: post?.pageCoverThumbnail || (siteInfo?.pageCover || BLOG.HOME_BANNER_IMAGE),
|
||||
category: post?.category?.[0],
|
||||
tags: post?.tags
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ const BlogPostCard = ({ post }) => {
|
||||
{showPageCover && (
|
||||
<div className="md:w-5/12 w-full overflow-hidden p-1">
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<div className='h-44 bg-center bg-cover hover:scale-110 duration-200' style={{ backgroundImage: `url('${post?.page_cover}')` }} />
|
||||
<div className='h-44 bg-center bg-cover hover:scale-110 duration-200' style={{ backgroundImage: `url('${post?.pageCoverThumbnail}')` }} />
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -22,10 +22,10 @@ export default function ArticleDetail(props) {
|
||||
const date = formatDate(post?.date?.start_date || post?.createdTime, locale.LOCALE)
|
||||
return (
|
||||
<div id="container" className="max-w-5xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
|
||||
{post?.type && !post?.type !== 'Page' && post?.page_cover && (
|
||||
{post?.type && !post?.type !== 'Page' && post?.pageCover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* 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?.pageCover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
<article itemScope itemType="https://schema.org/Movie"
|
||||
|
||||
@@ -7,10 +7,10 @@ import CONFIG_FUKA from '../config_fuka'
|
||||
const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = CONFIG_FUKA.POST_LIST_PREVIEW && post.blockMap
|
||||
// matery 主题默认强制显示图片
|
||||
if (post && !post.page_cover) {
|
||||
post.page_cover = siteInfo?.pageCover
|
||||
if (post && !post.pageCover) {
|
||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||
}
|
||||
const showPageCover = CONFIG_FUKA.POST_LIST_COVER && post?.page_cover
|
||||
const showPageCover = CONFIG_FUKA.POST_LIST_COVER && post?.pageCoverThumbnail
|
||||
|
||||
return (
|
||||
<div data-aos="fade-up" data-aos-duration="500" data-aos-once="true"
|
||||
@@ -33,17 +33,17 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
{post.summary}
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
{/* 分类标签 */}
|
||||
<div className="mt-1 text-gray-400 justify-between flex">
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer font-light text-sm hover:underline hover:text-indigo-700 dark:hover:text-indigo-400 transform">
|
||||
|
||||
|
||||
<i className="mr-1 far fa-folder" />
|
||||
{post.category}
|
||||
|
||||
|
||||
</Link>
|
||||
<div className="md:flex-nowrap flex-wrap md:justify-start inline-block">
|
||||
<div>
|
||||
@@ -61,11 +61,11 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
<div className="h-40 w-full relative duration-200 cursor-pointer transform overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={post?.page_cover}
|
||||
src={post?.pageCoverThumbnail}
|
||||
alt={post.title}
|
||||
className="w-full hover:scale-125 transform duration-500"
|
||||
></img>
|
||||
{/* <Image className='hover:scale-105 transform duration-500' src={post?.page_cover} alt={post.title} layout='fill' objectFit='cover' loading='lazy' /> */}
|
||||
{/* <Image className='hover:scale-105 transform duration-500' src={post?.pageCover} alt={post.title} layout='fill' objectFit='cover' loading='lazy' /> */}
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
@@ -29,8 +29,8 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{recommendPosts.map(post => {
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
const headerImage = post?.pageCoverThumbnail
|
||||
? `url("${post.pageCoverThumbnail}")`
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,10 +7,10 @@ import BLOG from '@/blog.config'
|
||||
|
||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = CONFIG_HEXO.POST_LIST_PREVIEW && post.blockMap
|
||||
if (post && !post.page_cover && CONFIG_HEXO.POST_LIST_COVER_DEFAULT) {
|
||||
post.page_cover = siteInfo?.pageCover
|
||||
if (post && !post.pageCoverThumbnail && CONFIG_HEXO.POST_LIST_COVER_DEFAULT) {
|
||||
post.pageCover = siteInfo?.pageCoverThumbnail
|
||||
}
|
||||
const showPageCover = CONFIG_HEXO.POST_LIST_COVER && post?.page_cover && !showPreview
|
||||
const showPageCover = CONFIG_HEXO.POST_LIST_COVER && post?.pageCoverThumbnail && !showPreview
|
||||
// const delay = (index % 2) * 200
|
||||
|
||||
return (
|
||||
@@ -36,7 +36,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
{showPageCover && (
|
||||
<div className="md:w-5/12 overflow-hidden">
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<div className='h-56 bg-center bg-cover hover:scale-110 duration-200' style={{ backgroundImage: `url('${post?.page_cover}')` }} />
|
||||
<div className='h-56 bg-center bg-cover hover:scale-110 duration-200' style={{ backgroundImage: `url('${post?.pageCoverThumbnail}')` }} />
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -11,7 +11,7 @@ export default function HeaderArticle({ post, siteInfo }) {
|
||||
if (!post) {
|
||||
return <></>
|
||||
}
|
||||
const headerImage = post?.page_cover ? `url("${post.page_cover}")` : `url("${siteInfo?.pageCover}")`
|
||||
const headerImage = post?.pageCover ? `url("${post.pageCover}")` : `url("${siteInfo?.pageCover}")`
|
||||
|
||||
const date = formatDate(
|
||||
post?.date?.start_date || post?.createdTime,
|
||||
|
||||
@@ -29,7 +29,7 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
|
||||
const headerImage = post?.page_cover ? post.page_cover : siteInfo?.pageCover
|
||||
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
||||
|
||||
return (
|
||||
(<Link
|
||||
|
||||
@@ -29,8 +29,8 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
||||
</div>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{recommendPosts.map(post => {
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
const headerImage = post?.pageCoverThumbnail
|
||||
? `url("${post.pageCoverThumbnail}")`
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
|
||||
return (
|
||||
|
||||
@@ -9,10 +9,10 @@ import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = CONFIG_MATERY.POST_LIST_PREVIEW && post.blockMap
|
||||
// matery 主题默认强制显示图片
|
||||
if (post && !post.page_cover) {
|
||||
post.page_cover = siteInfo?.pageCover
|
||||
if (post && !post.pageCoverThumbnail) {
|
||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||
}
|
||||
const showPageCover = CONFIG_MATERY.POST_LIST_COVER && post?.page_cover
|
||||
const showPageCover = CONFIG_MATERY.POST_LIST_COVER && post?.pageCoverThumbnail
|
||||
const delay = (index % 3) * 300
|
||||
return (
|
||||
<div
|
||||
@@ -33,7 +33,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
className="flex flex-grow w-full relative duration-200 bg-black rounded-t-md cursor-pointer transform overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={post?.page_cover}
|
||||
src={post?.pageCoverThumbnail}
|
||||
alt={post.title}
|
||||
className="opacity-50 h-full w-full hover:scale-125 rounded-t-md transform object-cover duration-500"
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Image from 'next/image'
|
||||
|
||||
export default function HeaderArticle({ post, siteInfo }) {
|
||||
const headerImage = post?.page_cover ? post?.page_cover : siteInfo?.pageCover
|
||||
const headerImage = post?.pageCoverThumbnail ? post?.pageCoverThumbnail : siteInfo?.pageCover
|
||||
const title = post?.title
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -27,8 +27,8 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
const headerImage = post?.pageCoverThumbnail
|
||||
? `url("${post.pageCoverThumbnail}")`
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
|
||||
return (
|
||||
|
||||
@@ -31,7 +31,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<div>
|
||||
{CONFIG_MEDIUM.POST_LIST_COVER && <div className='w-full max-h-96 object-cover overflow-hidden mb-2'>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={post.page_cover} className='w-full max-h-96 object-cover hover:scale-125 duration-150' />
|
||||
<img src={post.pageCoverThumbnail} className='w-full max-h-96 object-cover hover:scale-125 duration-150' />
|
||||
</div>}
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
@@ -39,10 +39,10 @@ export default function ArticleDetail(props) {
|
||||
|
||||
{showArticleInfo && <header>
|
||||
{/* 头图 */}
|
||||
{CONFIG_NEXT.POST_HEADER_IMAGE_VISIBLE && post?.type && !post?.type !== 'Page' && post?.page_cover && (
|
||||
{CONFIG_NEXT.POST_HEADER_IMAGE_VISIBLE && post?.type && !post?.type !== 'Page' && post?.pageCover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* 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?.pageCover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -114,12 +114,12 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{CONFIG_NEXT.POST_LIST_COVER && post?.page_cover && (
|
||||
{CONFIG_NEXT.POST_LIST_COVER && post?.pageCoverThumbnail && (
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<div className="h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden">
|
||||
<Image
|
||||
className="hover:scale-105 transform duration-500"
|
||||
src={post?.page_cover}
|
||||
src={post?.pageCoverThumbnail}
|
||||
alt={post.title}
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
|
||||
Reference in New Issue
Block a user