123 lines
4.7 KiB
JavaScript
123 lines
4.7 KiB
JavaScript
import React from "react";
|
|
import { AppleWebAppMeta, FormatDetectionMeta, ItunesMeta, BasicMetadata, VerificationMeta } from "./generate/basic";
|
|
import { AlternatesMetadata } from "./generate/alternate";
|
|
import { OpenGraphMetadata, TwitterMetadata, AppLinksMeta } from "./generate/opengraph";
|
|
import { IconsMetadata } from "./generate/icons";
|
|
import { resolveMetadata } from "./resolve-metadata";
|
|
import { MetaFilter } from "./generate/meta";
|
|
import { createDefaultMetadata } from "./default-metadata";
|
|
import { isNotFoundError } from "../../client/components/not-found";
|
|
// 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, searchParams, getDynamicParamFromSegment, appUsingSizeAdjustment, errorType }) {
|
|
const metadataContext = {
|
|
pathname
|
|
};
|
|
let resolve;
|
|
// Only use promise.resolve here to avoid unhandled rejections
|
|
const metadataErrorResolving = new Promise((res)=>{
|
|
resolve = res;
|
|
});
|
|
async function MetadataTree() {
|
|
const defaultMetadata = createDefaultMetadata();
|
|
let metadata = defaultMetadata;
|
|
let error;
|
|
const errorMetadataItem = [
|
|
null,
|
|
null
|
|
];
|
|
const errorConvention = errorType === "redirect" ? undefined : errorType;
|
|
const [resolvedMetadata, resolvedError] = await resolveMetadata({
|
|
tree,
|
|
parentParams: {},
|
|
metadataItems: [],
|
|
errorMetadataItem,
|
|
searchParams,
|
|
getDynamicParamFromSegment,
|
|
errorConvention,
|
|
metadataContext
|
|
});
|
|
if (!resolvedError) {
|
|
metadata = resolvedMetadata;
|
|
resolve(undefined);
|
|
} else {
|
|
error = resolvedError;
|
|
// If the error triggers in initial metadata resolving, re-resolve with proper error type.
|
|
// They'll be saved for flight data, when hydrates, it will replaces the SSR'd metadata with this.
|
|
// for not-found error: resolve not-found metadata
|
|
if (!errorType && isNotFoundError(resolvedError)) {
|
|
const [notFoundMetadata, notFoundMetadataError] = await resolveMetadata({
|
|
tree,
|
|
parentParams: {},
|
|
metadataItems: [],
|
|
errorMetadataItem,
|
|
searchParams,
|
|
getDynamicParamFromSegment,
|
|
errorConvention: "not-found",
|
|
metadataContext
|
|
});
|
|
metadata = notFoundMetadata;
|
|
error = notFoundMetadataError || error;
|
|
}
|
|
resolve(error);
|
|
}
|
|
const elements = MetaFilter([
|
|
BasicMetadata({
|
|
metadata
|
|
}),
|
|
AlternatesMetadata({
|
|
alternates: metadata.alternates
|
|
}),
|
|
ItunesMeta({
|
|
itunes: metadata.itunes
|
|
}),
|
|
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
|
|
})
|
|
]);
|
|
if (appUsingSizeAdjustment) elements.push(/*#__PURE__*/ React.createElement("meta", {
|
|
name: "next-size-adjust"
|
|
}));
|
|
return /*#__PURE__*/ React.createElement(React.Fragment, null, elements.map((el, index)=>{
|
|
return /*#__PURE__*/ React.cloneElement(el, {
|
|
key: index
|
|
});
|
|
}));
|
|
}
|
|
async function MetadataOutlet() {
|
|
const error = await metadataErrorResolving;
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
return null;
|
|
}
|
|
// @ts-expect-error async server components
|
|
return [
|
|
MetadataTree,
|
|
MetadataOutlet
|
|
];
|
|
}
|
|
|
|
//# sourceMappingURL=metadata.js.map
|