Update robots meta and add verification rendering (#45409)

Follow up for: #45237

* Adding more fields for robots meta, most related to googlebot
* Add `me` and `yandex` field and render for verification field
This commit is contained in:
Jiachi Liu 2023-01-30 21:49:30 +01:00 committed by GitHub
parent d3a9f5a54a
commit 41e2613aca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 119 additions and 23 deletions

View file

@ -1,7 +1,7 @@
import type { ResolvedMetadata } from '../types/metadata-interface'
import React from 'react'
import { Meta } from './meta'
import { Meta, MultiMeta } from './meta'
export function BasicMetadata({ metadata }: { metadata: ResolvedMetadata }) {
return (
@ -100,9 +100,7 @@ export function AppleWebAppMeta({
{capable ? (
<meta name="apple-mobile-web-app-capable" content="yes" />
) : null}
{title ? (
<meta name="apple-mobile-web-app-title" content={title} />
) : null}
<Meta name="apple-mobile-web-app-title" content={title} />
{startupImage
? startupImage.map((image, index) => (
<link
@ -122,3 +120,31 @@ export function AppleWebAppMeta({
</>
)
}
export function VerificationMeta({
verification,
}: {
verification: ResolvedMetadata['verification']
}) {
if (!verification) return null
return (
<>
<MultiMeta
namePrefix="google-site-verification"
contents={verification.google}
/>
<MultiMeta namePrefix="y_key" contents={verification.yahoo} />
<MultiMeta
namePrefix="yandex-verification"
contents={verification.yandex}
/>
<MultiMeta namePrefix="me" contents={verification.me} />
{verification.other
? Object.entries(verification.other).map(([key, value], index) => (
<MultiMeta key={key + index} namePrefix={key} contents={value} />
))
: null}
</>
)
}

View file

@ -91,6 +91,7 @@ export function MultiMeta({
} else {
return (
<ExtendMeta
key={keyPrefix + '_' + index}
namePrefix={namePrefix}
propertyPrefix={propertyPrefix}
content={content}

View file

@ -6,6 +6,7 @@ import {
FormatDetectionMeta,
ItunesMeta,
BasicMetadata,
VerificationMeta,
} from './generate/basic'
import { AlternatesMetadata } from './generate/alternate'
import {
@ -27,6 +28,7 @@ export async function Metadata({ metadata }: { metadata: any }) {
<AlternatesMetadata alternates={resolved.alternates} />
<ItunesMeta itunes={resolved.itunes} />
<FormatDetectionMeta formatDetection={resolved.formatDetection} />
<VerificationMeta verification={resolved.verification} />
<AppleWebAppMeta appleWebApp={resolved.appleWebApp} />
<OpenGraphMetadata openGraph={resolved.openGraph} />
<TwitterMetadata twitter={resolved.twitter} />

View file

@ -10,6 +10,7 @@ import type {
Icon,
IconDescriptor,
Icons,
ResolvedVerification,
} from './types/metadata-types'
import { createDefaultMetadata } from './default-metadata'
import { resolveOpenGraph } from './resolve-opengraph'
@ -76,22 +77,26 @@ const resolveViewport: FieldResolver<'viewport'> = (viewport) => {
return resolved
}
const VerificationKeys = ['google', 'yahoo', 'yandex', 'me', 'other'] as const
const resolveVerification: FieldResolver<'verification'> = (verification) => {
const google = resolveAsArrayOrUndefined(verification?.google)
const yahoo = resolveAsArrayOrUndefined(verification?.yahoo)
let other: Record<string, (string | number)[]> | undefined
if (verification?.other) {
other = {}
for (const key in verification.other) {
const value = resolveAsArrayOrUndefined(verification.other[key])
if (value) other[key] = value
if (!verification) return null
const res = {} as ResolvedVerification
for (const key of VerificationKeys) {
const value = verification[key]
if (value) {
if (key === 'other') {
res.other = {}
for (const otherKey in verification.other) {
const otherValue = resolveAsArrayOrUndefined(
verification.other[otherKey]
)
if (otherValue) res.other[otherKey] = otherValue
}
} else res[key] = resolveAsArrayOrUndefined(value) as (string | number)[]
}
}
return {
google,
yahoo,
other,
}
return res
}
function isStringOrURL(icon: any): icon is string | URL {
@ -203,23 +208,39 @@ const resolveAppLinks: FieldResolver<'appLinks'> = (appLinks) => {
return appLinks as ResolvedMetadata['appLinks']
}
const robotsKeys = [
'noarchive',
'nosnippet',
'noimageindex',
'nocache',
'notranslate',
'indexifembedded',
'nositelinkssearchbox',
'unavailable_after',
'max-video-preview',
'max-image-preview',
'max-snippet',
] as const
const resolveRobotsValue: (robots: Metadata['robots']) => string | null = (
robots
) => {
if (!robots) return null
if (typeof robots === 'string') return robots
const values = []
const values: string[] = []
if (robots.index) values.push('index')
else if (typeof robots.index === 'boolean') values.push('noindex')
if (robots.follow) values.push('follow')
else if (typeof robots.follow === 'boolean') values.push('nofollow')
if (robots.noarchive) values.push('noarchive')
if (robots.nosnippet) values.push('nosnippet')
if (robots.noimageindex) values.push('noimageindex')
if (robots.nocache) values.push('nocache')
for (const key of robotsKeys) {
const value = robots[key]
if (typeof value !== 'undefined' && value !== false) {
values.push(typeof value === 'boolean' ? key : `${key}:${value}`)
}
}
return values.join(', ')
}

View file

@ -59,6 +59,13 @@ type RobotsInfo = {
nosnippet?: boolean
noimageindex?: boolean
nocache?: boolean
notranslate?: boolean
indexifembedded?: boolean
nositelinkssearchbox?: boolean
unavailable_after?: string
'max-video-preview'?: number | string
'max-image-preview'?: 'none' | 'standard' | 'large'
'max-snippet'?: number
}
export type Robots = RobotsInfo & {
// if you want to specify an alternate robots just for google
@ -93,6 +100,8 @@ export type Icons = {
export type Verification = {
google?: null | string | number | (string | number)[]
yahoo?: null | string | number | (string | number)[]
yandex?: null | string | number | (string | number)[]
me?: null | string | number | (string | number)[]
// if you ad-hoc additional verification
other?: {
[name: string]: string | number | (string | number)[]
@ -102,6 +111,8 @@ export type Verification = {
export type ResolvedVerification = {
google?: null | (string | number)[]
yahoo?: null | (string | number)[]
yandex?: null | (string | number)[]
me?: null | (string | number)[]
other?: {
[name: string]: (string | number)[]
}

View file

@ -12,6 +12,10 @@ export const metadata = {
index: true,
follow: false,
noimageindex: true,
'max-video-preview': 'standard',
'max-image-preview': -1,
'max-snippet': -1,
},
},
}

View file

@ -0,0 +1,14 @@
export default function page() {
return 'verification'
}
export const metadata = {
verification: {
google: 'google',
yandex: 'yandex',
yahoo: 'yahoo',
other: {
me: ['my-email', 'my-link'],
},
},
}

View file

@ -235,10 +235,27 @@ createNextDescribe(
await checkMetaNameContentPair(
browser,
'googlebot',
'index, nofollow, noimageindex'
'index, nofollow, noimageindex, max-video-preview:standard, max-image-preview:-1, max-snippet:-1'
)
})
it('should support verification tags', async () => {
const browser = await next.browser('/verification')
await checkMetaNameContentPair(
browser,
'google-site-verification',
'google'
)
await checkMetaNameContentPair(browser, 'y_key', 'yahoo')
await checkMetaNameContentPair(
browser,
'yandex-verification',
'yandex'
)
await checkMetaNameContentPair(browser, 'me', ['my-email', 'my-link'])
})
it('should support appLinks tags', async () => {
const browser = await next.browser('/app-links')
await checkMetaPropertyContentPair(