240 lines
10 KiB
JavaScript
240 lines
10 KiB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
import React, { Suspense, cache, cloneElement } from 'react';
|
|
import { AppleWebAppMeta, FormatDetectionMeta, ItunesMeta, BasicMeta, ViewportMeta, VerificationMeta, FacebookMeta, PinterestMeta } from './generate/basic';
|
|
import { AlternatesMetadata } from './generate/alternate';
|
|
import { OpenGraphMetadata, TwitterMetadata, AppLinksMeta } from './generate/opengraph';
|
|
import { IconsMetadata } from './generate/icons';
|
|
import { resolveMetadata, resolveViewport } from './resolve-metadata';
|
|
import { MetaFilter } from './generate/meta';
|
|
import { isHTTPAccessFallbackError } from '../../client/components/http-access-fallback/http-access-fallback';
|
|
import { METADATA_BOUNDARY_NAME, VIEWPORT_BOUNDARY_NAME } from './metadata-constants';
|
|
import { AsyncMetadata, AsyncMetadataOutlet } from '../../client/components/metadata/async-metadata';
|
|
import { isPostpone } from '../../server/lib/router-utils/is-postpone';
|
|
import { createServerSearchParamsForMetadata } from '../../server/request/search-params';
|
|
// 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, parsedQuery, metadataContext, getDynamicParamFromSegment, appUsingSizeAdjustment, errorType, workStore, MetadataBoundary, ViewportBoundary, serveStreamingMetadata }) {
|
|
const searchParams = createServerSearchParamsForMetadata(parsedQuery, workStore);
|
|
function ViewportTree() {
|
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
children: [
|
|
/*#__PURE__*/ _jsx(ViewportBoundary, {
|
|
children: /*#__PURE__*/ _jsx(Viewport, {})
|
|
}),
|
|
appUsingSizeAdjustment ? /*#__PURE__*/ _jsx("meta", {
|
|
name: "next-size-adjust",
|
|
content: ""
|
|
}) : null
|
|
]
|
|
});
|
|
}
|
|
function MetadataTree() {
|
|
return /*#__PURE__*/ _jsx(MetadataBoundary, {
|
|
children: /*#__PURE__*/ _jsx(Metadata, {})
|
|
});
|
|
}
|
|
function viewport() {
|
|
return getResolvedViewport(tree, searchParams, getDynamicParamFromSegment, workStore, errorType);
|
|
}
|
|
async function Viewport() {
|
|
try {
|
|
return await viewport();
|
|
} catch (error) {
|
|
if (!errorType && isHTTPAccessFallbackError(error)) {
|
|
try {
|
|
return await getNotFoundViewport(tree, searchParams, getDynamicParamFromSegment, workStore);
|
|
} catch {}
|
|
}
|
|
// We don't actually want to error in this component. We will
|
|
// also error in the MetadataOutlet which causes the error to
|
|
// bubble from the right position in the page to be caught by the
|
|
// appropriate boundaries
|
|
return null;
|
|
}
|
|
}
|
|
Viewport.displayName = VIEWPORT_BOUNDARY_NAME;
|
|
function metadata() {
|
|
return getResolvedMetadata(tree, searchParams, getDynamicParamFromSegment, metadataContext, workStore, errorType);
|
|
}
|
|
async function resolveFinalMetadata() {
|
|
let result;
|
|
let error = null;
|
|
try {
|
|
result = await metadata();
|
|
return {
|
|
metadata: result,
|
|
error: null,
|
|
digest: undefined
|
|
};
|
|
} catch (metadataErr) {
|
|
error = metadataErr;
|
|
if (!errorType && isHTTPAccessFallbackError(metadataErr)) {
|
|
try {
|
|
result = await getNotFoundMetadata(tree, searchParams, getDynamicParamFromSegment, metadataContext, workStore);
|
|
return {
|
|
metadata: result,
|
|
error,
|
|
digest: error == null ? void 0 : error.digest
|
|
};
|
|
} catch (notFoundMetadataErr) {
|
|
error = notFoundMetadataErr;
|
|
// In PPR rendering we still need to throw the postpone error.
|
|
// If metadata is postponed, React needs to be aware of the location of error.
|
|
if (serveStreamingMetadata && isPostpone(notFoundMetadataErr)) {
|
|
throw notFoundMetadataErr;
|
|
}
|
|
}
|
|
}
|
|
// In PPR rendering we still need to throw the postpone error.
|
|
// If metadata is postponed, React needs to be aware of the location of error.
|
|
if (serveStreamingMetadata && isPostpone(metadataErr)) {
|
|
throw metadataErr;
|
|
}
|
|
// We don't actually want to error in this component. We will
|
|
// also error in the MetadataOutlet which causes the error to
|
|
// bubble from the right position in the page to be caught by the
|
|
// appropriate boundaries
|
|
return {
|
|
metadata: result,
|
|
error,
|
|
digest: error == null ? void 0 : error.digest
|
|
};
|
|
}
|
|
}
|
|
async function Metadata() {
|
|
const promise = resolveFinalMetadata();
|
|
if (serveStreamingMetadata) {
|
|
return /*#__PURE__*/ _jsx(Suspense, {
|
|
fallback: null,
|
|
children: /*#__PURE__*/ _jsx(AsyncMetadata, {
|
|
promise: promise
|
|
})
|
|
});
|
|
}
|
|
const metadataState = await promise;
|
|
return metadataState.metadata;
|
|
}
|
|
Metadata.displayName = METADATA_BOUNDARY_NAME;
|
|
async function getMetadataReady() {
|
|
// Only warm up metadata() call when it's blocking metadata,
|
|
// otherwise it will be fully managed by AsyncMetadata component.
|
|
if (!serveStreamingMetadata) {
|
|
await metadata();
|
|
}
|
|
return undefined;
|
|
}
|
|
async function getViewportReady() {
|
|
await viewport();
|
|
return undefined;
|
|
}
|
|
function StreamingMetadataOutlet() {
|
|
if (serveStreamingMetadata) {
|
|
return /*#__PURE__*/ _jsx(AsyncMetadataOutlet, {
|
|
promise: resolveFinalMetadata()
|
|
});
|
|
}
|
|
return null;
|
|
}
|
|
return {
|
|
ViewportTree,
|
|
MetadataTree,
|
|
getViewportReady,
|
|
getMetadataReady,
|
|
StreamingMetadataOutlet
|
|
};
|
|
}
|
|
const getResolvedMetadata = cache(getResolvedMetadataImpl);
|
|
async function getResolvedMetadataImpl(tree, searchParams, getDynamicParamFromSegment, metadataContext, workStore, errorType) {
|
|
const errorConvention = errorType === 'redirect' ? undefined : errorType;
|
|
return renderMetadata(tree, searchParams, getDynamicParamFromSegment, metadataContext, workStore, errorConvention);
|
|
}
|
|
const getNotFoundMetadata = cache(getNotFoundMetadataImpl);
|
|
async function getNotFoundMetadataImpl(tree, searchParams, getDynamicParamFromSegment, metadataContext, workStore) {
|
|
const notFoundErrorConvention = 'not-found';
|
|
return renderMetadata(tree, searchParams, getDynamicParamFromSegment, metadataContext, workStore, notFoundErrorConvention);
|
|
}
|
|
const getResolvedViewport = cache(getResolvedViewportImpl);
|
|
async function getResolvedViewportImpl(tree, searchParams, getDynamicParamFromSegment, workStore, errorType) {
|
|
const errorConvention = errorType === 'redirect' ? undefined : errorType;
|
|
return renderViewport(tree, searchParams, getDynamicParamFromSegment, workStore, errorConvention);
|
|
}
|
|
const getNotFoundViewport = cache(getNotFoundViewportImpl);
|
|
async function getNotFoundViewportImpl(tree, searchParams, getDynamicParamFromSegment, workStore) {
|
|
const notFoundErrorConvention = 'not-found';
|
|
return renderViewport(tree, searchParams, getDynamicParamFromSegment, workStore, notFoundErrorConvention);
|
|
}
|
|
async function renderMetadata(tree, searchParams, getDynamicParamFromSegment, metadataContext, workStore, errorConvention) {
|
|
const resolvedMetadata = await resolveMetadata(tree, searchParams, errorConvention, getDynamicParamFromSegment, workStore, metadataContext);
|
|
const elements = createMetadataElements(resolvedMetadata);
|
|
return /*#__PURE__*/ _jsx(_Fragment, {
|
|
children: elements.map((el, index)=>{
|
|
return /*#__PURE__*/ cloneElement(el, {
|
|
key: index
|
|
});
|
|
})
|
|
});
|
|
}
|
|
async function renderViewport(tree, searchParams, getDynamicParamFromSegment, workStore, errorConvention) {
|
|
const resolvedViewport = await resolveViewport(tree, searchParams, errorConvention, getDynamicParamFromSegment, workStore);
|
|
const elements = createViewportElements(resolvedViewport);
|
|
return /*#__PURE__*/ _jsx(_Fragment, {
|
|
children: elements.map((el, index)=>{
|
|
return /*#__PURE__*/ cloneElement(el, {
|
|
key: index
|
|
});
|
|
})
|
|
});
|
|
}
|
|
function createMetadataElements(metadata) {
|
|
return MetaFilter([
|
|
BasicMeta({
|
|
metadata
|
|
}),
|
|
AlternatesMetadata({
|
|
alternates: metadata.alternates
|
|
}),
|
|
ItunesMeta({
|
|
itunes: metadata.itunes
|
|
}),
|
|
FacebookMeta({
|
|
facebook: metadata.facebook
|
|
}),
|
|
PinterestMeta({
|
|
pinterest: metadata.pinterest
|
|
}),
|
|
FormatDetectionMeta({
|
|
formatDetection: metadata.formatDetection
|
|
}),
|
|
VerificationMeta({
|
|
verification: metadata.verification
|
|
}),
|
|
AppleWebAppMeta({
|
|
appleWebApp: metadata.appleWebApp
|
|
}),
|
|
OpenGraphMetadata({
|
|
openGraph: metadata.openGraph
|
|
}),
|
|
TwitterMetadata({
|
|
twitter: metadata.twitter
|
|
}),
|
|
AppLinksMeta({
|
|
appLinks: metadata.appLinks
|
|
}),
|
|
IconsMetadata({
|
|
icons: metadata.icons
|
|
})
|
|
]);
|
|
}
|
|
function createViewportElements(viewport) {
|
|
return MetaFilter([
|
|
ViewportMeta({
|
|
viewport: viewport
|
|
})
|
|
]);
|
|
}
|
|
|
|
//# sourceMappingURL=metadata.js.map
|