mirror of
https://github.com/d0zingcat/nextjs-notion-starter-kit.git
synced 2026-05-13 23:16:47 +00:00
feat: change social image urls
This commit is contained in:
@@ -15,12 +15,7 @@ import { Tweet, TwitterContextProvider } from 'react-static-tweets'
|
||||
import { NotionRenderer } from 'react-notion-x'
|
||||
|
||||
// utils
|
||||
import {
|
||||
getBlockTitle,
|
||||
getBlockIcon,
|
||||
getPageProperty,
|
||||
isUrl
|
||||
} from 'notion-utils'
|
||||
import { getBlockTitle, getPageProperty } from 'notion-utils'
|
||||
import { mapPageUrl, getCanonicalPageUrl } from 'lib/map-page-url'
|
||||
import { mapImageUrl } from 'lib/map-image-url'
|
||||
import { getPageTweet } from 'lib/get-page-tweet'
|
||||
@@ -134,36 +129,10 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
block
|
||||
)
|
||||
|
||||
const socialImageCoverPosition =
|
||||
(block as PageBlock).format?.page_cover_position ??
|
||||
config.defaultPageCoverPosition
|
||||
const socialImageObjectPosition = socialImageCoverPosition
|
||||
? `center ${(1 - socialImageCoverPosition) * 100}%`
|
||||
: null
|
||||
|
||||
const blockIcon = getBlockIcon(block, recordMap)
|
||||
const socialAuthorImage = mapImageUrl(
|
||||
blockIcon && isUrl(blockIcon) ? blockIcon : config.defaultPageIcon,
|
||||
block
|
||||
)
|
||||
|
||||
const socialAuthor =
|
||||
getPageProperty<string>('Author', block, recordMap) || config.author
|
||||
|
||||
const socialDescription =
|
||||
getPageProperty<string>('Description', block, recordMap) ||
|
||||
config.description
|
||||
|
||||
const timePublished = getPageProperty<number>('Published', block, recordMap)
|
||||
const datePublished = timePublished ? new Date(timePublished) : undefined
|
||||
const socialDate =
|
||||
isBlogPost && datePublished
|
||||
? `${datePublished.toLocaleString('en-US', {
|
||||
month: 'long'
|
||||
})} ${datePublished.getFullYear()}`
|
||||
: undefined
|
||||
const socialDetail = socialDate || site.domain
|
||||
|
||||
let pageAside: React.ReactNode = null
|
||||
|
||||
// only display comments and page actions on blog post pages
|
||||
@@ -187,14 +156,11 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
}}
|
||||
>
|
||||
<PageHead
|
||||
pageId={pageId}
|
||||
site={site}
|
||||
title={title}
|
||||
description={socialDescription}
|
||||
image={socialImage}
|
||||
imageObjectPosition={socialImageObjectPosition}
|
||||
author={socialAuthor}
|
||||
authorImage={socialAuthorImage}
|
||||
detail={socialDetail}
|
||||
url={canonicalPageUrl}
|
||||
/>
|
||||
|
||||
|
||||
@@ -10,34 +10,13 @@ export const PageHead: React.FC<
|
||||
title?: string
|
||||
description?: string
|
||||
image?: string
|
||||
imageObjectPosition?: string
|
||||
author?: string
|
||||
authorImage?: string
|
||||
detail?: string
|
||||
url?: string
|
||||
}
|
||||
> = ({
|
||||
site,
|
||||
title,
|
||||
description,
|
||||
image,
|
||||
imageObjectPosition,
|
||||
author,
|
||||
authorImage,
|
||||
detail,
|
||||
url
|
||||
}) => {
|
||||
> = ({ site, title, description, pageId, image, url }) => {
|
||||
title = title ?? site?.name
|
||||
description = description ?? site?.description
|
||||
|
||||
const socialImageUrl = getSocialImageUrl({
|
||||
title,
|
||||
image,
|
||||
imageObjectPosition,
|
||||
author,
|
||||
authorImage,
|
||||
detail
|
||||
})
|
||||
const socialImageUrl = getSocialImageUrl(pageId) || image
|
||||
|
||||
return (
|
||||
<Head>
|
||||
|
||||
@@ -1,45 +1,16 @@
|
||||
import { api, host } from './config'
|
||||
|
||||
export function getSocialImageUrl({
|
||||
title,
|
||||
image,
|
||||
imageObjectPosition,
|
||||
author,
|
||||
authorImage,
|
||||
detail
|
||||
}: {
|
||||
title: string
|
||||
image?: string
|
||||
imageObjectPosition?: string
|
||||
author?: string
|
||||
authorImage?: string
|
||||
detail?: string
|
||||
}) {
|
||||
const url = new URL(api.getSocialImage, host)
|
||||
export function getSocialImageUrl(pageId: string) {
|
||||
try {
|
||||
const url = new URL(api.getSocialImage, host)
|
||||
|
||||
if (title) {
|
||||
url.searchParams.set('title', title)
|
||||
if (pageId) {
|
||||
url.searchParams.set('id', pageId)
|
||||
return url.toString()
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('error invalid social image url', pageId, err.message)
|
||||
}
|
||||
|
||||
if (image) {
|
||||
url.searchParams.set('image', image)
|
||||
}
|
||||
|
||||
if (imageObjectPosition) {
|
||||
url.searchParams.set('imageObjectPosition', imageObjectPosition)
|
||||
}
|
||||
|
||||
if (author) {
|
||||
url.searchParams.set('author', author)
|
||||
}
|
||||
|
||||
if (authorImage) {
|
||||
url.searchParams.set('authorImage', authorImage)
|
||||
}
|
||||
|
||||
if (detail) {
|
||||
url.searchParams.set('detail', detail)
|
||||
}
|
||||
|
||||
return url.toString()
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -9,12 +9,6 @@ import { defaultPageIcon, defaultPageCover } from './config'
|
||||
import { db } from './db'
|
||||
import { mapImageUrl } from './map-image-url'
|
||||
|
||||
// NOTE: this is just an example of how to pre-compute preview images.
|
||||
// Depending on how many images you're working with, this can potentially be
|
||||
// very expensive to recompute, so in production we recommend that you cache
|
||||
// the preview image results in a key-value database of your choosing.
|
||||
// If you're not sure where to start, check out https://github.com/jaredwray/keyv
|
||||
|
||||
export async function getPreviewImageMap(
|
||||
recordMap: ExtendedRecordMap
|
||||
): Promise<PreviewImageMap> {
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
import React from 'react'
|
||||
import { withOGImage } from 'next-api-og-image'
|
||||
import { interRegular } from '../../lib/fonts'
|
||||
|
||||
import {
|
||||
getBlockTitle,
|
||||
getBlockIcon,
|
||||
getPageProperty,
|
||||
isUrl,
|
||||
parsePageId
|
||||
} from 'notion-utils'
|
||||
import { PageBlock } from 'notion-types'
|
||||
|
||||
import { notion } from 'lib/notion'
|
||||
import { getSiteForDomain } from 'lib/get-site-for-domain'
|
||||
import { mapImageUrl } from 'lib/map-image-url'
|
||||
import * as config from 'lib/config'
|
||||
import { interRegular } from 'lib/fonts'
|
||||
|
||||
/**
|
||||
* Social image generation via headless chrome.
|
||||
@@ -12,24 +26,69 @@ import { interRegular } from '../../lib/fonts'
|
||||
*/
|
||||
const debugInspectHtml = false
|
||||
|
||||
export default withOGImage<
|
||||
'query',
|
||||
| 'title'
|
||||
| 'image'
|
||||
| 'author'
|
||||
| 'authorImage'
|
||||
| 'detail'
|
||||
| 'imageObjectPosition'
|
||||
>({
|
||||
export default withOGImage<'query', 'id'>({
|
||||
template: {
|
||||
react: ({
|
||||
title,
|
||||
image,
|
||||
author,
|
||||
authorImage,
|
||||
detail,
|
||||
imageObjectPosition
|
||||
}) => {
|
||||
react: async ({ id }) => {
|
||||
const pageId = parsePageId(id)
|
||||
|
||||
if (!pageId) {
|
||||
throw new Error('Invalid notion page id')
|
||||
}
|
||||
|
||||
const site = await getSiteForDomain(config.domain)
|
||||
const recordMap = await notion.getPage(pageId)
|
||||
|
||||
const keys = Object.keys(recordMap?.block || {})
|
||||
const block = recordMap?.block?.[keys[0]]?.value
|
||||
|
||||
if (!block) {
|
||||
throw new Error('Invalid recordMap for page')
|
||||
}
|
||||
|
||||
const isBlogPost =
|
||||
block.type === 'page' && block.parent_table === 'collection'
|
||||
const title = getBlockTitle(block, recordMap) || site.name
|
||||
const image = mapImageUrl(
|
||||
getPageProperty<string>('Social Image', block, recordMap) ||
|
||||
(block as PageBlock).format?.page_cover ||
|
||||
config.defaultPageCover,
|
||||
block
|
||||
)
|
||||
|
||||
const imageCoverPosition =
|
||||
(block as PageBlock).format?.page_cover_position ??
|
||||
config.defaultPageCoverPosition
|
||||
const imageObjectPosition = imageCoverPosition
|
||||
? `center ${(1 - imageCoverPosition) * 100}%`
|
||||
: null
|
||||
|
||||
const blockIcon = getBlockIcon(block, recordMap)
|
||||
const authorImage = mapImageUrl(
|
||||
blockIcon && isUrl(blockIcon) ? blockIcon : config.defaultPageIcon,
|
||||
block
|
||||
)
|
||||
|
||||
const author =
|
||||
getPageProperty<string>('Author', block, recordMap) || config.author
|
||||
|
||||
// const socialDescription =
|
||||
// getPageProperty<string>('Description', block, recordMap) ||
|
||||
// config.description
|
||||
|
||||
const timePublished = getPageProperty<number>(
|
||||
'Published',
|
||||
block,
|
||||
recordMap
|
||||
)
|
||||
const datePublished = timePublished ? new Date(timePublished) : undefined
|
||||
const date =
|
||||
isBlogPost && datePublished
|
||||
? `${datePublished.toLocaleString('en-US', {
|
||||
month: 'long'
|
||||
})} ${datePublished.getFullYear()}`
|
||||
: undefined
|
||||
const detail = date || site.domain
|
||||
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
@@ -142,7 +201,8 @@ body {
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 3em;
|
||||
font-size: 3.2em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
|
||||
Reference in New Issue
Block a user