Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override file based images with social images property #52416

Merged
merged 2 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 62 additions & 0 deletions packages/next/src/lib/metadata/resolve-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,68 @@ describe('accumulateMetadata', () => {
},
})
})

it('should override openGraph or twitter images when current layer specifies social images properties', async () => {
const metadataItems1: MetadataItems = [
[
{
openGraph: {
images: 'https://test.com/og.png',
},
twitter: {
images: 'https://test.com/twitter.png',
},
},
// has static metadata files
{
icon: undefined,
apple: undefined,
twitter: ['/filebased/twitter.png'],
openGraph: ['/filebased/og.png'],
manifest: undefined,
},
],
]
const metadata1 = await accumulateMetadata(metadataItems1)
expect(metadata1).toMatchObject({
openGraph: {
images: [{ url: new URL('https://test.com/og.png') }],
},
twitter: {
images: [{ url: new URL('https://test.com/twitter.png ') }],
},
})

const metadataItems2: MetadataItems = [
[
function gM2() {
return {
openGraph: {
images: undefined,
},
// twitter is not specified, supposed to merged with openGraph but images should not be picked up
}
},
// has static metadata files
{
icon: undefined,
apple: undefined,
twitter: undefined,
openGraph: ['/filebased/og.png'],
manifest: undefined,
},
],
]
const metadata2 = await accumulateMetadata(metadataItems2)
expect(metadata2).toMatchObject({
openGraph: {
images: undefined,
},
twitter: {
images: undefined,
},
})
})
})

describe('themeColor', () => {
Expand Down
42 changes: 26 additions & 16 deletions packages/next/src/lib/metadata/resolve-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,54 +51,61 @@ type TitleTemplates = {
}

function mergeStaticMetadata(
metadata: ResolvedMetadata,
source: Metadata | null,
target: ResolvedMetadata,
staticFilesMetadata: StaticMetadata,
metadataContext: MetadataContext,
titleTemplates: TitleTemplates
) {
if (!staticFilesMetadata) return
const { icon, apple, openGraph, twitter, manifest } = staticFilesMetadata
if (icon || apple) {
metadata.icons = {
// file based metadata is specified and current level metadata icons is not specified
if (
(icon && !source?.icons && !source?.icons?.hasOwnProperty('icon')) ||
(apple && !source?.icons?.hasOwnProperty('apple'))
) {
target.icons = {
icon: icon || [],
apple: apple || [],
}
}
if (twitter) {
// file based metadata is specified and current level metadata twitter.images is not specified
if (twitter && !source?.twitter?.hasOwnProperty('images')) {
const resolvedTwitter = resolveTwitter(
{ ...metadata.twitter, images: twitter } as Twitter,
metadata.metadataBase,
{ ...target.twitter, images: twitter } as Twitter,
target.metadataBase,
titleTemplates.twitter
)
metadata.twitter = resolvedTwitter
target.twitter = resolvedTwitter
}

if (openGraph) {
// file based metadata is specified and current level metadata openGraph.images is not specified
if (openGraph && !source?.openGraph?.hasOwnProperty('images')) {
const resolvedOpenGraph = resolveOpenGraph(
{ ...metadata.openGraph, images: openGraph } as OpenGraph,
metadata.metadataBase,
{ ...target.openGraph, images: openGraph } as OpenGraph,
target.metadataBase,
metadataContext,
titleTemplates.openGraph
)
metadata.openGraph = resolvedOpenGraph
target.openGraph = resolvedOpenGraph
}
if (manifest) {
metadata.manifest = manifest
target.manifest = manifest
}

return metadata
return target
}

// Merge the source metadata into the resolved target metadata.
function merge({
target,
source,
target,
staticFilesMetadata,
titleTemplates,
metadataContext,
}: {
target: ResolvedMetadata
source: Metadata | null
target: ResolvedMetadata
staticFilesMetadata: StaticMetadata
titleTemplates: TitleTemplates
metadataContext: MetadataContext
Expand Down Expand Up @@ -211,6 +218,7 @@ function merge({
}
}
mergeStaticMetadata(
source,
target,
staticFilesMetadata,
metadataContext,
Expand Down Expand Up @@ -388,7 +396,9 @@ function postProcessMetadata(
}> = {}
const hasTwTitle = twitter?.title.absolute
const hasTwDescription = twitter?.description
const hasTwImages = twitter?.images
const hasTwImages = Boolean(
twitter?.hasOwnProperty('images') && twitter.images
)
if (!hasTwTitle) autoFillProps.title = openGraph.title
if (!hasTwDescription) autoFillProps.description = openGraph.description
if (!hasTwImages) autoFillProps.images = openGraph.images
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export default function Page() {
return 'opengraph-static-override'
}

export const metadata = {
icons: ['https://custom-icon-1.png'],
openGraph: {
title: 'no-og-image',
images: undefined,
},
twitter: {
title: 'no-tw-image',
images: null,
},
}
25 changes: 22 additions & 3 deletions test/e2e/app-dir/metadata/metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ createNextDescribe(
tag: string,
queryKey: string,
domAttributeField: string,
expected: Record<string, string | string[]>
expected: Record<string, string | string[] | undefined>
) => {
const res = {}
for (const key of Object.keys(expected)) {
Expand Down Expand Up @@ -569,8 +569,27 @@ createNextDescribe(
})

// favicon shouldn't be overridden
const $icon = $('link[rel="icon"]')
expect($icon.attr('href')).toBe('/favicon.ico')
expect($('link[rel="icon"]').attr('href')).toBe('/favicon.ico')
})

it('should override file based images when opengraph-image and twitter-image specify images property', async () => {
const $ = await next.render$('/opengraph/static/override')

const match = createMultiHtmlMatcher($)
await match('meta', 'property', 'content', {
'og:title': 'no-og-image',
'og:image': undefined,
})

await match('meta', 'name', 'content', {
'twitter:image': undefined,
'twitter:title': 'no-tw-image',
})

// icon should be overridden
expect($('link[rel="icon"]').attr('href')).toBe(
'https://custom-icon-1.png'
)
})
})

Expand Down