feat: change social image urls

This commit is contained in:
Travis Fischer
2022-04-06 09:28:08 -04:00
parent 03c12f9c94
commit 0b7d6187c0
5 changed files with 93 additions and 123 deletions

View File

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

View File

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

View File

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

View File

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

View File

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