87 lines
2.9 KiB
JavaScript
87 lines
2.9 KiB
JavaScript
import { buildLocalizedPath } from '../i18n/index.js';
|
|
import { composeTitle } from './composeTitle.js';
|
|
import { buildHreflangAlternates } from './hreflang.js';
|
|
/**
|
|
* Assembles a Next.js-compatible Metadata object from document SEO fields and
|
|
* site-level data. Locale-aware: canonical points at the current locale's
|
|
* path, and hreflang alternates cover every locale the document exists in.
|
|
*
|
|
* Designed for use inside Next.js `generateMetadata`. The caller resolves the
|
|
* pieces (meta group, site name, image URL, localized slugs) and passes them
|
|
* in — the plugin composes, it doesn't fetch.
|
|
*/ export function buildMetadata({ baseUrl, config, homeSlug = 'home', imageUrl, locale, meta, order, pageTitle, prefix, query, separator, siteName, slugs }) {
|
|
// Title source priority: titleOverride (exact, wins outright) > meta.title
|
|
// (SEO title an editor set) > pageTitle (the document's own name). This means
|
|
// a page with no SEO title still shows its name (e.g. 'Sprzątanie biur')
|
|
// composed with the site name, instead of just the site name or a blank.
|
|
const override = meta?.titleOverride?.trim();
|
|
const resolvedPageTitle = meta?.title?.trim() || pageTitle?.trim() || undefined;
|
|
const title = override || composeTitle({
|
|
order,
|
|
pageTitle: resolvedPageTitle,
|
|
separator,
|
|
siteName
|
|
});
|
|
const description = meta?.description?.trim() || undefined;
|
|
const origin = baseUrl?.replace(/\/$/, '') ?? '';
|
|
const suffix = query ?? '';
|
|
const currentPath = buildLocalizedPath({
|
|
config,
|
|
homeSlug,
|
|
locale,
|
|
prefix,
|
|
slugs
|
|
});
|
|
const canonical = currentPath ? `${origin}${currentPath}${suffix}` : undefined;
|
|
const languages = buildHreflangAlternates({
|
|
baseUrl,
|
|
config,
|
|
homeSlug,
|
|
prefix,
|
|
slugs
|
|
});
|
|
if (suffix) {
|
|
for (const code of Object.keys(languages)){
|
|
languages[code] = `${languages[code]}${suffix}`;
|
|
}
|
|
}
|
|
const images = imageUrl ? [
|
|
{
|
|
url: imageUrl
|
|
}
|
|
] : undefined;
|
|
return {
|
|
title,
|
|
...description && {
|
|
description
|
|
},
|
|
alternates: {
|
|
...canonical && {
|
|
canonical
|
|
},
|
|
...Object.keys(languages).length > 0 && {
|
|
languages
|
|
}
|
|
},
|
|
openGraph: {
|
|
title,
|
|
...description && {
|
|
description
|
|
},
|
|
...images && {
|
|
images
|
|
},
|
|
locale
|
|
},
|
|
// noindex → tell search engines to exclude the page but still follow links
|
|
// (authority flows through). For legal/thin/search-result pages.
|
|
...meta?.noindex ? {
|
|
robots: {
|
|
follow: true,
|
|
index: false
|
|
}
|
|
} : {}
|
|
};
|
|
}
|
|
|
|
//# sourceMappingURL=buildMetadata.js.map
|