next
Version:
The React Framework
1,190 lines (1,189 loc) • 67.5 kB
JavaScript
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import React, { Suspense, cache } from 'react';
import { resolveMetadata, resolveViewport } from './resolve-metadata';
import { isHTTPAccessFallbackError } from '../../client/components/http-access-fallback/http-access-fallback';
import { createServerSearchParamsForMetadata } from '../../server/request/search-params';
import { createServerPathnameForMetadata } from '../../server/request/pathname';
import { isPostpone } from '../../server/lib/router-utils/is-postpone';
import { workUnitAsyncStorage, getStagedRenderingController } from '../../server/app-render/work-unit-async-storage.external';
import { RenderStage } from '../../server/app-render/staged-rendering';
import { MetadataBoundary, ViewportBoundary, OutletBoundary } from '../framework/boundary-components';
import { getOrigin } from './generate/utils';
import { IconMark } from './generate/icon-mark';
// Use a promise to share the status of the metadata resolving,
// returning two components `MetadataTree` and `MetadataOutlet`
// `MetadataTree` is the one that will be rendered at first in the content sequence for metadata tags.
// `MetadataOutlet` is the one that will be rendered under error boundaries for metadata resolving errors.
// In this way we can let the metadata tags always render successfully,
// and the error will be caught by the error boundary and trigger fallbacks.
export function createMetadataComponents({ tree, pathname, parsedQuery, metadataContext, interpolatedParams, errorType, serveStreamingMetadata, isRuntimePrefetchable }) {
const searchParams = createServerSearchParamsForMetadata(parsedQuery, isRuntimePrefetchable);
const pathnameForMetadata = createServerPathnameForMetadata(pathname);
async function Viewport() {
// Gate metadata to the correct render stage. If the page is not
// runtime-prefetchable, defer until the Static stage so that
// prefetchable segments get a head start.
if (!isRuntimePrefetchable) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
const stagedRendering = getStagedRenderingController(workUnitStore);
if (stagedRendering) {
await stagedRendering.waitForStage(RenderStage.Static);
}
}
}
const tags = await getResolvedViewport(tree, searchParams, interpolatedParams, isRuntimePrefetchable, errorType).catch((viewportErr)=>{
// When Legacy PPR is enabled viewport can reject with a Postpone type
// This will go away once Legacy PPR is removed and dynamic metadata will
// stay pending until after the prerender is complete when it is dynamic
if (isPostpone(viewportErr)) {
throw viewportErr;
}
if (!errorType && isHTTPAccessFallbackError(viewportErr)) {
return getNotFoundViewport(tree, searchParams, interpolatedParams, isRuntimePrefetchable).catch(()=>null);
}
// We're going to throw the error from the metadata outlet so we just render null here instead
return null;
});
return tags;
}
Viewport.displayName = 'Next.Viewport';
function ViewportWrapper() {
return /*#__PURE__*/ _jsx(ViewportBoundary, {
children: /*#__PURE__*/ _jsx(Viewport, {})
});
}
async function Metadata() {
// Gate metadata to the correct render stage. If the page is not
// runtime-prefetchable, defer until the Static stage so that
// prefetchable segments get a head start.
if (!isRuntimePrefetchable) {
const workUnitStore = workUnitAsyncStorage.getStore();
if (workUnitStore) {
const stagedRendering = getStagedRenderingController(workUnitStore);
if (stagedRendering) {
await stagedRendering.waitForStage(RenderStage.Static);
}
}
}
const tags = await getResolvedMetadata(tree, pathnameForMetadata, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable, errorType).catch((metadataErr)=>{
// When Legacy PPR is enabled metadata can reject with a Postpone type
// This will go away once Legacy PPR is removed and dynamic metadata will
// stay pending until after the prerender is complete when it is dynamic
if (isPostpone(metadataErr)) {
throw metadataErr;
}
if (!errorType && isHTTPAccessFallbackError(metadataErr)) {
return getNotFoundMetadata(tree, pathnameForMetadata, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable).catch(()=>null);
}
// We're going to throw the error from the metadata outlet so we just render null here instead
return null;
});
return tags;
}
Metadata.displayName = 'Next.Metadata';
function MetadataWrapper() {
// TODO: We shouldn't change what we render based on whether we are streaming or not.
// If we aren't streaming we should just block the response until we have resolved the
// metadata.
if (!serveStreamingMetadata) {
return /*#__PURE__*/ _jsx(MetadataBoundary, {
children: /*#__PURE__*/ _jsx(Metadata, {})
});
}
return /*#__PURE__*/ _jsx("div", {
hidden: true,
children: /*#__PURE__*/ _jsx(MetadataBoundary, {
children: /*#__PURE__*/ _jsx(Suspense, {
name: "Next.Metadata",
children: /*#__PURE__*/ _jsx(Metadata, {})
})
})
});
}
function MetadataOutlet() {
const pendingOutlet = Promise.all([
getResolvedMetadata(tree, pathnameForMetadata, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable, errorType),
getResolvedViewport(tree, searchParams, interpolatedParams, isRuntimePrefetchable, errorType)
]).then(()=>null);
// TODO: We shouldn't change what we render based on whether we are streaming or not.
// If we aren't streaming we should just block the response until we have resolved the
// metadata.
if (!serveStreamingMetadata) {
return /*#__PURE__*/ _jsx(OutletBoundary, {
children: pendingOutlet
});
}
return /*#__PURE__*/ _jsx(OutletBoundary, {
children: /*#__PURE__*/ _jsx(Suspense, {
name: "Next.MetadataOutlet",
children: pendingOutlet
})
});
}
MetadataOutlet.displayName = 'Next.MetadataOutlet';
return {
Viewport: ViewportWrapper,
Metadata: MetadataWrapper,
MetadataOutlet
};
}
const getResolvedMetadata = cache(getResolvedMetadataImpl);
async function getResolvedMetadataImpl(tree, pathname, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable, errorType) {
const errorConvention = errorType === 'redirect' ? undefined : errorType;
return renderMetadata(tree, pathname, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable, errorConvention);
}
const getNotFoundMetadata = cache(getNotFoundMetadataImpl);
async function getNotFoundMetadataImpl(tree, pathname, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable) {
const notFoundErrorConvention = 'not-found';
return renderMetadata(tree, pathname, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable, notFoundErrorConvention);
}
const getResolvedViewport = cache(getResolvedViewportImpl);
async function getResolvedViewportImpl(tree, searchParams, interpolatedParams, isRuntimePrefetchable, errorType) {
const errorConvention = errorType === 'redirect' ? undefined : errorType;
return renderViewport(tree, searchParams, interpolatedParams, isRuntimePrefetchable, errorConvention);
}
const getNotFoundViewport = cache(getNotFoundViewportImpl);
async function getNotFoundViewportImpl(tree, searchParams, interpolatedParams, isRuntimePrefetchable) {
const notFoundErrorConvention = 'not-found';
return renderViewport(tree, searchParams, interpolatedParams, isRuntimePrefetchable, notFoundErrorConvention);
}
async function renderMetadata(tree, pathname, searchParams, interpolatedParams, metadataContext, isRuntimePrefetchable, errorConvention) {
const resolvedMetadata = await resolveMetadata(tree, pathname, searchParams, errorConvention, interpolatedParams, metadataContext, isRuntimePrefetchable);
return /*#__PURE__*/ _jsx(_Fragment, {
children: createMetadataElements(resolvedMetadata)
});
}
async function renderViewport(tree, searchParams, interpolatedParams, isRuntimePrefetchable, errorConvention) {
const resolvedViewport = await resolveViewport(tree, searchParams, errorConvention, interpolatedParams, isRuntimePrefetchable);
return /*#__PURE__*/ _jsx(_Fragment, {
children: createViewportElements(resolvedViewport)
});
}
// ---------------------------------------------------------------------------
// Viewport tag rendering
// ---------------------------------------------------------------------------
function createViewportElements(viewport) {
const tags = [];
let i = 0;
tags.push(/*#__PURE__*/ _jsx("meta", {
charSet: "utf-8"
}, i++));
// Build viewport content string from layout properties
const viewportParts = [];
if (viewport.width != null) {
viewportParts.push(`width=${viewport.width}`);
}
if (viewport.height != null) {
viewportParts.push(`height=${viewport.height}`);
}
if (viewport.initialScale != null) {
viewportParts.push(`initial-scale=${viewport.initialScale}`);
}
if (viewport.minimumScale != null) {
viewportParts.push(`minimum-scale=${viewport.minimumScale}`);
}
if (viewport.maximumScale != null) {
viewportParts.push(`maximum-scale=${viewport.maximumScale}`);
}
if (viewport.userScalable != null) {
viewportParts.push(`user-scalable=${viewport.userScalable ? 'yes' : 'no'}`);
}
if (viewport.viewportFit) {
viewportParts.push(`viewport-fit=${viewport.viewportFit}`);
}
if (viewport.interactiveWidget) {
viewportParts.push(`interactive-widget=${viewport.interactiveWidget}`);
}
if (viewportParts.length) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "viewport",
content: viewportParts.join(', ')
}, i++));
}
if (viewport.themeColor) {
for (const themeColor of viewport.themeColor){
if (themeColor.media) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "theme-color",
content: themeColor.color,
media: themeColor.media
}, i++));
} else {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "theme-color",
content: themeColor.color
}, i++));
}
}
}
if (viewport.colorScheme) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "color-scheme",
content: viewport.colorScheme
}, i++));
}
return tags;
}
// ---------------------------------------------------------------------------
// Metadata tag rendering
// ---------------------------------------------------------------------------
function createMetadataElements(metadata) {
var _metadata_robots, _metadata_robots1;
const tags = [];
let i = 0;
// --- Title ---
if (metadata.title !== null && metadata.title.absolute) {
tags.push(/*#__PURE__*/ _jsx("title", {
children: metadata.title.absolute
}, i++));
}
// --- Basic meta tags ---
if (metadata.description) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "description",
content: metadata.description
}, i++));
}
if (metadata.applicationName) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "application-name",
content: metadata.applicationName
}, i++));
}
// --- Authors ---
if (metadata.authors) {
for (const author of metadata.authors){
if (author.url) {
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "author",
href: author.url.toString()
}, i++));
}
if (author.name) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "author",
content: author.name
}, i++));
}
}
}
// --- Manifest ---
if (metadata.manifest) {
const manifestOrigin = getOrigin(metadata.manifest);
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "manifest",
href: metadata.manifest.toString(),
crossOrigin: !manifestOrigin && process.env.VERCEL_ENV === 'preview' ? 'use-credentials' : undefined
}, i++));
}
if (metadata.generator) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "generator",
content: metadata.generator
}, i++));
}
if (metadata.keywords && metadata.keywords.length) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "keywords",
content: metadata.keywords.join(',')
}, i++));
}
if (metadata.referrer) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "referrer",
content: metadata.referrer
}, i++));
}
if (metadata.creator) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "creator",
content: metadata.creator
}, i++));
}
if (metadata.publisher) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "publisher",
content: metadata.publisher
}, i++));
}
if ((_metadata_robots = metadata.robots) == null ? void 0 : _metadata_robots.basic) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "robots",
content: metadata.robots.basic
}, i++));
}
if ((_metadata_robots1 = metadata.robots) == null ? void 0 : _metadata_robots1.googleBot) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "googlebot",
content: metadata.robots.googleBot
}, i++));
}
if (metadata.abstract) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "abstract",
content: metadata.abstract
}, i++));
}
// --- Link rel arrays ---
if (metadata.archives) {
for (const archive of metadata.archives){
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "archives",
href: archive
}, i++));
}
}
if (metadata.assets) {
for (const asset of metadata.assets){
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "assets",
href: asset
}, i++));
}
}
if (metadata.bookmarks) {
for (const bookmark of metadata.bookmarks){
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "bookmarks",
href: bookmark
}, i++));
}
}
// --- Pagination ---
if (metadata.pagination) {
if (metadata.pagination.previous) {
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "prev",
href: metadata.pagination.previous
}, i++));
}
if (metadata.pagination.next) {
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "next",
href: metadata.pagination.next
}, i++));
}
}
if (metadata.category) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "category",
content: metadata.category
}, i++));
}
if (metadata.classification) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "classification",
content: metadata.classification
}, i++));
}
// --- Other (arbitrary name/value pairs) ---
if (metadata.other) {
for (const [name, content] of Object.entries(metadata.other)){
if (Array.isArray(content)) {
for (const contentItem of content){
if (contentItem != null && contentItem !== '') {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: name,
content: String(contentItem)
}, i++));
}
}
} else if (content != null && content !== '') {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: name,
content: String(content)
}, i++));
}
}
}
// --- Alternates ---
if (metadata.alternates) {
const { canonical, languages, media, types } = metadata.alternates;
if (canonical && canonical.url) {
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "canonical",
href: canonical.url.toString(),
...canonical.title ? {
title: canonical.title
} : undefined
}, i++));
}
if (languages) {
for (const [locale, descriptors] of Object.entries(languages)){
if (descriptors) {
for (const descriptor of descriptors){
if (descriptor.url) {
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "alternate",
hrefLang: locale,
href: descriptor.url.toString(),
...descriptor.title ? {
title: descriptor.title
} : undefined
}, i++));
}
}
}
}
}
if (media) {
for (const [mediaName, descriptors] of Object.entries(media)){
if (descriptors) {
for (const descriptor of descriptors){
if (descriptor.url) {
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "alternate",
media: mediaName,
href: descriptor.url.toString(),
...descriptor.title ? {
title: descriptor.title
} : undefined
}, i++));
}
}
}
}
}
if (types) {
for (const [type, descriptors] of Object.entries(types)){
if (descriptors) {
for (const descriptor of descriptors){
if (descriptor.url) {
tags.push(/*#__PURE__*/ _jsx("link", {
rel: "alternate",
type: type,
href: descriptor.url.toString(),
...descriptor.title ? {
title: descriptor.title
} : undefined
}, i++));
}
}
}
}
}
}
// --- iTunes ---
if (metadata.itunes) {
const { appId, appArgument } = metadata.itunes;
let itunesContent = `app-id=${appId}`;
if (appArgument) {
itunesContent += `, app-argument=${appArgument}`;
}
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "apple-itunes-app",
content: itunesContent
}, i++));
}
// --- Facebook ---
if (metadata.facebook) {
if (metadata.facebook.appId) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "fb:app_id",
content: metadata.facebook.appId
}, i++));
}
if (metadata.facebook.admins) {
for (const admin of metadata.facebook.admins){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "fb:admins",
content: admin
}, i++));
}
}
}
// --- Pinterest ---
if (metadata.pinterest && metadata.pinterest.richPin !== undefined) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "pinterest-rich-pin",
content: metadata.pinterest.richPin.toString()
}, i++));
}
// --- Format Detection ---
if (metadata.formatDetection) {
const formatDetectionKeys = [
'telephone',
'date',
'address',
'email',
'url'
];
let formatContent = '';
for (const key of formatDetectionKeys){
if (metadata.formatDetection[key] === false) {
if (formatContent) formatContent += ', ';
formatContent += `${key}=no`;
}
}
if (formatContent) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "format-detection",
content: formatContent
}, i++));
}
}
// --- Verification ---
if (metadata.verification) {
const verification = metadata.verification;
if (verification.google) {
for (const value of verification.google){
if (value != null && value !== '') {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "google-site-verification",
content: String(value)
}, i++));
}
}
}
if (verification.yahoo) {
for (const value of verification.yahoo){
if (value != null && value !== '') {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "y_key",
content: String(value)
}, i++));
}
}
}
if (verification.yandex) {
for (const value of verification.yandex){
if (value != null && value !== '') {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "yandex-verification",
content: String(value)
}, i++));
}
}
}
if (verification.me) {
for (const value of verification.me){
if (value != null && value !== '') {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "me",
content: String(value)
}, i++));
}
}
}
if (verification.other) {
for (const [name, values] of Object.entries(verification.other)){
for (const value of values){
if (value != null && value !== '') {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: name,
content: String(value)
}, i++));
}
}
}
}
}
// --- Apple Web App ---
if (metadata.appleWebApp) {
const { capable, title, startupImage, statusBarStyle } = metadata.appleWebApp;
if (capable) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "mobile-web-app-capable",
content: "yes"
}, i++));
}
if (title) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "apple-mobile-web-app-title",
content: title
}, i++));
}
if (startupImage) {
for (const image of startupImage){
if (image.media) {
tags.push(/*#__PURE__*/ _jsx("link", {
href: image.url,
media: image.media,
rel: "apple-touch-startup-image"
}, i++));
} else {
tags.push(/*#__PURE__*/ _jsx("link", {
href: image.url,
rel: "apple-touch-startup-image"
}, i++));
}
}
}
if (statusBarStyle) {
tags.push(/*#__PURE__*/ _jsx("meta", {
name: "apple-mobile-web-app-status-bar-style",
content: statusBarStyle
}, i++));
}
}
// --- Open Graph ---
if (metadata.openGraph) {
var _og_title;
const og = metadata.openGraph;
if (og.determiner) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:determiner",
content: og.determiner
}, i++));
}
if ((_og_title = og.title) == null ? void 0 : _og_title.absolute) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:title",
content: og.title.absolute
}, i++));
}
if (og.description) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:description",
content: og.description
}, i++));
}
if (og.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:url",
content: og.url.toString()
}, i++));
}
if (og.siteName) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:site_name",
content: og.siteName
}, i++));
}
if (og.locale) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:locale",
content: og.locale
}, i++));
}
if (og.countryName) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:country_name",
content: og.countryName
}, i++));
}
if (og.ttl != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:ttl",
content: og.ttl.toString()
}, i++));
}
// OG images
if (og.images) {
for (const image of og.images){
if (typeof image === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:image",
content: image
}, i++));
} else {
if (image.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:image",
content: String(image.url)
}, i++));
}
if (image.secureUrl) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:image:secure_url",
content: String(image.secureUrl)
}, i++));
}
if (image.type) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:image:type",
content: image.type
}, i++));
}
if (image.width) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:image:width",
content: String(image.width)
}, i++));
}
if (image.height) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:image:height",
content: String(image.height)
}, i++));
}
if (image.alt) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:image:alt",
content: image.alt
}, i++));
}
}
}
}
// OG videos
if (og.videos) {
for (const video of og.videos){
if (typeof video === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:video",
content: video
}, i++));
} else {
if (video.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:video",
content: String(video.url)
}, i++));
}
if (video.secureUrl) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:video:secure_url",
content: String(video.secureUrl)
}, i++));
}
if (video.type) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:video:type",
content: video.type
}, i++));
}
if (video.width) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:video:width",
content: String(video.width)
}, i++));
}
if (video.height) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:video:height",
content: String(video.height)
}, i++));
}
}
}
}
// OG audio
if (og.audio) {
for (const audio of og.audio){
if (typeof audio === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:audio",
content: audio
}, i++));
} else {
if (audio.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:audio",
content: String(audio.url)
}, i++));
}
if (audio.secureUrl) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:audio:secure_url",
content: String(audio.secureUrl)
}, i++));
}
if (audio.type) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:audio:type",
content: audio.type
}, i++));
}
}
}
}
// OG simple array properties
if (og.emails) {
for (const email of og.emails){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:email",
content: email
}, i++));
}
}
if (og.phoneNumbers) {
for (const phone of og.phoneNumbers){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:phone_number",
content: phone
}, i++));
}
}
if (og.faxNumbers) {
for (const fax of og.faxNumbers){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:fax_number",
content: fax
}, i++));
}
}
if (og.alternateLocale) {
for (const locale of og.alternateLocale){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:locale:alternate",
content: locale
}, i++));
}
}
// OG type-specific tags
if ('type' in og) {
const ogType = og.type;
switch(ogType){
case 'website':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "website"
}, i++));
break;
case 'article':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "article"
}, i++));
if (og.publishedTime) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "article:published_time",
content: og.publishedTime.toString()
}, i++));
}
if (og.modifiedTime) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "article:modified_time",
content: og.modifiedTime.toString()
}, i++));
}
if (og.expirationTime) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "article:expiration_time",
content: og.expirationTime.toString()
}, i++));
}
if (og.authors) {
for (const author of og.authors){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "article:author",
content: String(author)
}, i++));
}
}
if (og.section) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "article:section",
content: og.section
}, i++));
}
if (og.tags) {
for (const tag of og.tags){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "article:tag",
content: tag
}, i++));
}
}
break;
case 'book':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "book"
}, i++));
if (og.isbn) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "book:isbn",
content: og.isbn
}, i++));
}
if (og.releaseDate) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "book:release_date",
content: og.releaseDate
}, i++));
}
if (og.authors) {
for (const author of og.authors){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "book:author",
content: String(author)
}, i++));
}
}
if (og.tags) {
for (const tag of og.tags){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "book:tag",
content: tag
}, i++));
}
}
break;
case 'profile':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "profile"
}, i++));
if (og.firstName) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "profile:first_name",
content: og.firstName
}, i++));
}
if (og.lastName) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "profile:last_name",
content: og.lastName
}, i++));
}
if (og.username) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "profile:username",
content: og.username
}, i++));
}
if (og.gender) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "profile:gender",
content: og.gender
}, i++));
}
break;
case 'music.song':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "music.song"
}, i++));
if (og.duration != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:duration",
content: og.duration.toString()
}, i++));
}
if (og.albums) {
for (const album of og.albums){
if (typeof album === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:album",
content: album
}, i++));
} else {
if (album.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:album",
content: String(album.url)
}, i++));
}
if (album.disc != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:album:disc",
content: String(album.disc)
}, i++));
}
if (album.track != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:album:track",
content: String(album.track)
}, i++));
}
}
}
}
if (og.musicians) {
for (const musician of og.musicians){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:musician",
content: String(musician)
}, i++));
}
}
break;
case 'music.album':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "music.album"
}, i++));
if (og.songs) {
for (const song of og.songs){
if (typeof song === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song",
content: song
}, i++));
} else {
if (song.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song",
content: String(song.url)
}, i++));
}
if (song.disc != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song:disc",
content: String(song.disc)
}, i++));
}
if (song.track != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song:track",
content: String(song.track)
}, i++));
}
}
}
}
if (og.musicians) {
for (const musician of og.musicians){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:musician",
content: String(musician)
}, i++));
}
}
if (og.releaseDate) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:release_date",
content: og.releaseDate
}, i++));
}
break;
case 'music.playlist':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "music.playlist"
}, i++));
if (og.songs) {
for (const song of og.songs){
if (typeof song === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song",
content: song
}, i++));
} else {
if (song.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song",
content: String(song.url)
}, i++));
}
if (song.disc != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song:disc",
content: String(song.disc)
}, i++));
}
if (song.track != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:song:track",
content: String(song.track)
}, i++));
}
}
}
}
if (og.creators) {
for (const creator of og.creators){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:creator",
content: String(creator)
}, i++));
}
}
break;
case 'music.radio_station':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "music.radio_station"
}, i++));
if (og.creators) {
for (const creator of og.creators){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "music:creator",
content: String(creator)
}, i++));
}
}
break;
case 'video.movie':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "video.movie"
}, i++));
if (og.actors) {
for (const actor of og.actors){
if (typeof actor === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:actor",
content: actor
}, i++));
} else {
if (actor.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:actor",
content: String(actor.url)
}, i++));
}
if (actor.role) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:actor:role",
content: actor.role
}, i++));
}
}
}
}
if (og.directors) {
for (const director of og.directors){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:director",
content: String(director)
}, i++));
}
}
if (og.writers) {
for (const writer of og.writers){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:writer",
content: String(writer)
}, i++));
}
}
if (og.duration != null) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:duration",
content: String(og.duration)
}, i++));
}
if (og.releaseDate) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:release_date",
content: og.releaseDate
}, i++));
}
if (og.tags) {
for (const tag of og.tags){
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:tag",
content: tag
}, i++));
}
}
break;
case 'video.episode':
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "og:type",
content: "video.episode"
}, i++));
if (og.actors) {
for (const actor of og.actors){
if (typeof actor === 'string') {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:actor",
content: actor
}, i++));
} else {
if (actor.url) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:actor",
content: String(actor.url)
}, i++));
}
if (actor.role) {
tags.push(/*#__PURE__*/ _jsx("meta", {
property: "video:actor:role",
content: actor.role
}, i++));
}