Merge pull request #1166 from tangly1024/fix/img

Fix/img
This commit is contained in:
tangly1024
2023-06-18 11:18:03 +08:00
committed by GitHub
18 changed files with 92 additions and 75 deletions

View File

@@ -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

View File

@@ -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'

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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>
)}

View File

@@ -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"

View File

@@ -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>
)}

View File

@@ -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 (

View File

@@ -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>
)}

View File

@@ -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,

View File

@@ -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

View File

@@ -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 (

View File

@@ -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"
/>

View File

@@ -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

View File

@@ -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 (

View File

@@ -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>

View File

@@ -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>
)}

View File

@@ -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"