366 lines
15 KiB
JavaScript
366 lines
15 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
0 && (module.exports = {
|
|
collectMetadata: null,
|
|
resolveMetadata: null,
|
|
accumulateMetadata: null
|
|
});
|
|
function _export(target, all) {
|
|
for(var name in all)Object.defineProperty(target, name, {
|
|
enumerable: true,
|
|
get: all[name]
|
|
});
|
|
}
|
|
_export(exports, {
|
|
collectMetadata: function() {
|
|
return collectMetadata;
|
|
},
|
|
resolveMetadata: function() {
|
|
return resolveMetadata;
|
|
},
|
|
accumulateMetadata: function() {
|
|
return accumulateMetadata;
|
|
}
|
|
});
|
|
const _defaultmetadata = require("./default-metadata");
|
|
const _resolveopengraph = require("./resolvers/resolve-opengraph");
|
|
const _resolvetitle = require("./resolvers/resolve-title");
|
|
const _utils = require("./generate/utils");
|
|
const _clientreference = require("../client-reference");
|
|
const _appdirmodule = require("../../server/lib/app-dir-module");
|
|
const _interopdefault = require("../interop-default");
|
|
const _resolvebasics = require("./resolvers/resolve-basics");
|
|
const _resolveicons = require("./resolvers/resolve-icons");
|
|
const _tracer = require("../../server/lib/trace/tracer");
|
|
const _constants = require("../../server/lib/trace/constants");
|
|
const _constants1 = require("../../shared/lib/constants");
|
|
function mergeStaticMetadata(metadata, staticFilesMetadata, { pathname }) {
|
|
if (!staticFilesMetadata) return;
|
|
const { icon , apple , openGraph , twitter , manifest } = staticFilesMetadata;
|
|
if (icon || apple) {
|
|
metadata.icons = {
|
|
icon: icon || [],
|
|
apple: apple || []
|
|
};
|
|
}
|
|
if (twitter) {
|
|
const resolvedTwitter = (0, _resolveopengraph.resolveTwitter)({
|
|
...metadata.twitter,
|
|
images: twitter
|
|
}, metadata.metadataBase);
|
|
metadata.twitter = resolvedTwitter;
|
|
}
|
|
if (openGraph) {
|
|
const resolvedOpenGraph = (0, _resolveopengraph.resolveOpenGraph)({
|
|
...metadata.openGraph,
|
|
images: openGraph
|
|
}, metadata.metadataBase, {
|
|
pathname
|
|
});
|
|
metadata.openGraph = resolvedOpenGraph;
|
|
}
|
|
if (manifest) {
|
|
metadata.manifest = manifest;
|
|
}
|
|
return metadata;
|
|
}
|
|
// Merge the source metadata into the resolved target metadata.
|
|
function merge({ target , source , staticFilesMetadata , titleTemplates , options }) {
|
|
// If there's override metadata, prefer it otherwise fallback to the default metadata.
|
|
const metadataBase = typeof (source == null ? void 0 : source.metadataBase) !== "undefined" ? source.metadataBase : target.metadataBase;
|
|
for(const key_ in source){
|
|
const key = key_;
|
|
switch(key){
|
|
case "title":
|
|
{
|
|
target.title = (0, _resolvetitle.resolveTitle)(source.title, titleTemplates.title);
|
|
break;
|
|
}
|
|
case "alternates":
|
|
{
|
|
target.alternates = (0, _resolvebasics.resolveAlternates)(source.alternates, metadataBase, options);
|
|
break;
|
|
}
|
|
case "openGraph":
|
|
{
|
|
target.openGraph = (0, _resolveopengraph.resolveOpenGraph)(source.openGraph, metadataBase, options);
|
|
if (target.openGraph) {
|
|
target.openGraph.title = (0, _resolvetitle.resolveTitle)(target.openGraph.title, titleTemplates.openGraph);
|
|
}
|
|
break;
|
|
}
|
|
case "twitter":
|
|
{
|
|
target.twitter = (0, _resolveopengraph.resolveTwitter)(source.twitter, metadataBase);
|
|
if (target.twitter) {
|
|
target.twitter.title = (0, _resolvetitle.resolveTitle)(target.twitter.title, titleTemplates.twitter);
|
|
}
|
|
break;
|
|
}
|
|
case "verification":
|
|
target.verification = (0, _resolvebasics.resolveVerification)(source.verification);
|
|
break;
|
|
case "viewport":
|
|
{
|
|
target.viewport = (0, _resolvebasics.resolveViewport)(source.viewport);
|
|
break;
|
|
}
|
|
case "icons":
|
|
{
|
|
target.icons = (0, _resolveicons.resolveIcons)(source.icons);
|
|
break;
|
|
}
|
|
case "appleWebApp":
|
|
target.appleWebApp = (0, _resolvebasics.resolveAppleWebApp)(source.appleWebApp);
|
|
break;
|
|
case "appLinks":
|
|
target.appLinks = (0, _resolvebasics.resolveAppLinks)(source.appLinks);
|
|
break;
|
|
case "robots":
|
|
{
|
|
target.robots = (0, _resolvebasics.resolveRobots)(source.robots);
|
|
break;
|
|
}
|
|
case "themeColor":
|
|
{
|
|
target.themeColor = (0, _resolvebasics.resolveThemeColor)(source.themeColor);
|
|
break;
|
|
}
|
|
case "archives":
|
|
case "assets":
|
|
case "bookmarks":
|
|
case "keywords":
|
|
{
|
|
target[key] = (0, _utils.resolveAsArrayOrUndefined)(source[key]);
|
|
break;
|
|
}
|
|
case "authors":
|
|
{
|
|
target[key] = (0, _utils.resolveAsArrayOrUndefined)(source.authors);
|
|
break;
|
|
}
|
|
case "itunes":
|
|
{
|
|
target[key] = (0, _resolvebasics.resolveItunes)(source.itunes, metadataBase, options);
|
|
break;
|
|
}
|
|
// directly assign fields that fallback to null
|
|
case "applicationName":
|
|
case "description":
|
|
case "generator":
|
|
case "creator":
|
|
case "publisher":
|
|
case "category":
|
|
case "classification":
|
|
case "referrer":
|
|
case "colorScheme":
|
|
case "formatDetection":
|
|
case "manifest":
|
|
// @ts-ignore TODO: support inferring
|
|
target[key] = source[key] || null;
|
|
break;
|
|
case "other":
|
|
target.other = Object.assign({}, target.other, source.other);
|
|
break;
|
|
case "metadataBase":
|
|
target.metadataBase = metadataBase;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
mergeStaticMetadata(target, staticFilesMetadata, options);
|
|
}
|
|
async function getDefinedMetadata(mod, props, route) {
|
|
// Layer is a client component, we just skip it. It can't have metadata exported.
|
|
// Return early to avoid accessing properties error for client references.
|
|
if ((0, _clientreference.isClientReference)(mod)) {
|
|
return null;
|
|
}
|
|
return (mod.generateMetadata ? (parent)=>(0, _tracer.getTracer)().trace(_constants.ResolveMetadataSpan.generateMetadata, {
|
|
spanName: `generateMetadata ${route}`,
|
|
attributes: {
|
|
"next.page": route
|
|
}
|
|
}, ()=>mod.generateMetadata(props, parent)) : mod.metadata) || null;
|
|
}
|
|
async function collectStaticImagesFiles(metadata, props, type) {
|
|
var _ref;
|
|
if (!(metadata == null ? void 0 : metadata[type])) return undefined;
|
|
const iconPromises = metadata[type].map(async (imageModule)=>(0, _interopdefault.interopDefault)(await imageModule(props)));
|
|
return (iconPromises == null ? void 0 : iconPromises.length) > 0 ? (_ref = await Promise.all(iconPromises)) == null ? void 0 : _ref.flat() : undefined;
|
|
}
|
|
async function resolveStaticMetadata(components, props) {
|
|
const { metadata } = components;
|
|
if (!metadata) return null;
|
|
const [icon, apple, openGraph, twitter] = await Promise.all([
|
|
collectStaticImagesFiles(metadata, props, "icon"),
|
|
collectStaticImagesFiles(metadata, props, "apple"),
|
|
collectStaticImagesFiles(metadata, props, "openGraph"),
|
|
collectStaticImagesFiles(metadata, props, "twitter")
|
|
]);
|
|
const staticMetadata = {
|
|
icon,
|
|
apple,
|
|
openGraph,
|
|
twitter,
|
|
manifest: metadata.manifest
|
|
};
|
|
return staticMetadata;
|
|
}
|
|
async function collectMetadata({ tree , metadataItems: array , props , route }) {
|
|
const [mod, modType] = await (0, _appdirmodule.getLayoutOrPageModule)(tree);
|
|
if (modType) {
|
|
route += `/${modType}`;
|
|
}
|
|
const staticFilesMetadata = await resolveStaticMetadata(tree[2], props);
|
|
const metadataExport = mod ? await getDefinedMetadata(mod, props, route) : null;
|
|
array.push([
|
|
metadataExport,
|
|
staticFilesMetadata
|
|
]);
|
|
}
|
|
async function resolveMetadata({ tree , parentParams , metadataItems , treePrefix =[] , getDynamicParamFromSegment , searchParams }) {
|
|
const [segment, parallelRoutes, { page }] = tree;
|
|
const currentTreePrefix = [
|
|
...treePrefix,
|
|
segment
|
|
];
|
|
const isPage = typeof page !== "undefined";
|
|
// Handle dynamic segment params.
|
|
const segmentParam = getDynamicParamFromSegment(segment);
|
|
/**
|
|
* Create object holding the parent params and current params
|
|
*/ const currentParams = // Handle null case where dynamic param is optional
|
|
segmentParam && segmentParam.value !== null ? {
|
|
...parentParams,
|
|
[segmentParam.param]: segmentParam.value
|
|
} : parentParams;
|
|
const layerProps = {
|
|
params: currentParams,
|
|
...isPage && {
|
|
searchParams
|
|
}
|
|
};
|
|
await collectMetadata({
|
|
tree,
|
|
metadataItems,
|
|
props: layerProps,
|
|
route: currentTreePrefix// __PAGE__ shouldn't be shown in a route
|
|
.filter((s)=>s !== _constants1.PAGE_SEGMENT_KEY).join("/")
|
|
});
|
|
for(const key in parallelRoutes){
|
|
const childTree = parallelRoutes[key];
|
|
await resolveMetadata({
|
|
tree: childTree,
|
|
metadataItems,
|
|
parentParams: currentParams,
|
|
treePrefix: currentTreePrefix,
|
|
searchParams,
|
|
getDynamicParamFromSegment
|
|
});
|
|
}
|
|
return metadataItems;
|
|
}
|
|
const commonOgKeys = [
|
|
"title",
|
|
"description",
|
|
"images"
|
|
];
|
|
function postProcessMetadata(metadata) {
|
|
const { openGraph , twitter } = metadata;
|
|
if (openGraph) {
|
|
var _twitter_title;
|
|
let autoFillProps = {};
|
|
const hasTwTitle = twitter == null ? void 0 : (_twitter_title = twitter.title) == null ? void 0 : _twitter_title.absolute;
|
|
const hasTwDescription = twitter == null ? void 0 : twitter.description;
|
|
const hasTwImages = twitter == null ? void 0 : twitter.images;
|
|
if (!hasTwTitle) autoFillProps.title = openGraph.title;
|
|
if (!hasTwDescription) autoFillProps.description = openGraph.description;
|
|
if (!hasTwImages) autoFillProps.images = openGraph.images;
|
|
if (Object.keys(autoFillProps).length > 0) {
|
|
const partialTwitter = (0, _resolveopengraph.resolveTwitter)(autoFillProps, metadata.metadataBase);
|
|
if (metadata.twitter) {
|
|
metadata.twitter = Object.assign({}, metadata.twitter, {
|
|
...!hasTwTitle && {
|
|
title: partialTwitter == null ? void 0 : partialTwitter.title
|
|
},
|
|
...!hasTwDescription && {
|
|
description: partialTwitter == null ? void 0 : partialTwitter.description
|
|
},
|
|
...!hasTwImages && {
|
|
images: partialTwitter == null ? void 0 : partialTwitter.images
|
|
}
|
|
});
|
|
} else {
|
|
metadata.twitter = partialTwitter;
|
|
}
|
|
}
|
|
}
|
|
return metadata;
|
|
}
|
|
async function accumulateMetadata(metadataItems, options) {
|
|
const resolvedMetadata = (0, _defaultmetadata.createDefaultMetadata)();
|
|
const resolvers = [];
|
|
const generateMetadataResults = [];
|
|
let titleTemplates = {
|
|
title: null,
|
|
twitter: null,
|
|
openGraph: null
|
|
};
|
|
// Loop over all metadata items again, merging synchronously any static object exports,
|
|
// awaiting any static promise exports, and resolving parent metadata and awaiting any generated metadata
|
|
let resolvingIndex = 0;
|
|
for(let i = 0; i < metadataItems.length; i++){
|
|
const [metadataExport, staticFilesMetadata] = metadataItems[i];
|
|
let metadata = null;
|
|
if (typeof metadataExport === "function") {
|
|
if (!resolvers.length) {
|
|
for(let j = i; j < metadataItems.length; j++){
|
|
const [preloadMetadataExport] = metadataItems[j];
|
|
// call each `generateMetadata function concurrently and stash their resolver
|
|
if (typeof preloadMetadataExport === "function") {
|
|
generateMetadataResults.push(preloadMetadataExport(new Promise((resolve)=>{
|
|
resolvers.push(resolve);
|
|
})));
|
|
}
|
|
}
|
|
}
|
|
const resolveParent = resolvers[resolvingIndex];
|
|
const generatedMetadata = generateMetadataResults[resolvingIndex++];
|
|
// In dev we clone and freeze to prevent relying on mutating resolvedMetadata directly.
|
|
// In prod we just pass resolvedMetadata through without any copying.
|
|
const currentResolvedMetadata = process.env.NODE_ENV === "development" ? Object.freeze(require("./clone-metadata").cloneMetadata(resolvedMetadata)) : resolvedMetadata;
|
|
// This resolve should unblock the generateMetadata function if it awaited the parent
|
|
// argument. If it didn't await the parent argument it might already have a value since it was
|
|
// called concurrently. Regardless we await the return value before continuing on to the next layer
|
|
resolveParent(currentResolvedMetadata);
|
|
metadata = generatedMetadata instanceof Promise ? await generatedMetadata : generatedMetadata;
|
|
} else if (metadataExport !== null && typeof metadataExport === "object") {
|
|
// This metadataExport is the object form
|
|
metadata = metadataExport;
|
|
}
|
|
merge({
|
|
options,
|
|
target: resolvedMetadata,
|
|
source: metadata,
|
|
staticFilesMetadata,
|
|
titleTemplates
|
|
});
|
|
// If the layout is the same layer with page, skip the leaf layout and leaf page
|
|
// The leaf layout and page are the last two items
|
|
if (i < metadataItems.length - 2) {
|
|
var _resolvedMetadata_title, _resolvedMetadata_openGraph, _resolvedMetadata_openGraph_title, _resolvedMetadata_twitter, _resolvedMetadata_twitter_title;
|
|
titleTemplates = {
|
|
title: ((_resolvedMetadata_title = resolvedMetadata.title) == null ? void 0 : _resolvedMetadata_title.template) || null,
|
|
openGraph: ((_resolvedMetadata_openGraph = resolvedMetadata.openGraph) == null ? void 0 : (_resolvedMetadata_openGraph_title = _resolvedMetadata_openGraph.title) == null ? void 0 : _resolvedMetadata_openGraph_title.template) || null,
|
|
twitter: ((_resolvedMetadata_twitter = resolvedMetadata.twitter) == null ? void 0 : (_resolvedMetadata_twitter_title = _resolvedMetadata_twitter.title) == null ? void 0 : _resolvedMetadata_twitter_title.template) || null
|
|
};
|
|
}
|
|
}
|
|
return postProcessMetadata(resolvedMetadata);
|
|
}
|
|
|
|
//# sourceMappingURL=resolve-metadata.js.map
|