@cmssy/next 4.0.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +40 -27
- package/dist/index.d.cts +26 -5
- package/dist/index.d.ts +26 -5
- package/dist/index.js +41 -28
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -586,25 +586,29 @@ function createCmssySitemap(config, options = {}) {
|
|
|
586
586
|
const baseUrl = await resolveSeoBaseUrl(config, options.baseUrl);
|
|
587
587
|
const { defaultLocale, locales } = resolveSeoLocales(config, siteConfig);
|
|
588
588
|
const excluded = new Set((options.excludeSlugs ?? []).map(normalizeSlug));
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
locales.map((locale) => [
|
|
599
|
-
locale,
|
|
600
|
-
`${baseUrl}${localizedPath(page.slug, locale, defaultLocale)}`
|
|
601
|
-
])
|
|
602
|
-
)
|
|
603
|
-
};
|
|
589
|
+
const languagesFor = (slug) => locales.length > 1 ? {
|
|
590
|
+
languages: {
|
|
591
|
+
...Object.fromEntries(
|
|
592
|
+
locales.map((locale) => [
|
|
593
|
+
locale,
|
|
594
|
+
`${baseUrl}${localizedPath(slug, locale, defaultLocale)}`
|
|
595
|
+
])
|
|
596
|
+
),
|
|
597
|
+
"x-default": `${baseUrl}${localizedPath(slug, defaultLocale, defaultLocale)}`
|
|
604
598
|
}
|
|
605
|
-
|
|
599
|
+
} : void 0;
|
|
600
|
+
const entries = pages.map((page) => ({ ...page, slug: normalizeSlug(page.slug) })).filter((page) => page.id !== notFoundPageId && !excluded.has(page.slug)).flatMap((page) => {
|
|
601
|
+
const lastModified = page.updatedAt ?? page.publishedAt ?? void 0;
|
|
602
|
+
const alternates = languagesFor(page.slug);
|
|
603
|
+
return locales.map((locale) => ({
|
|
604
|
+
url: `${baseUrl}${localizedPath(page.slug, locale, defaultLocale)}`,
|
|
605
|
+
...lastModified ? { lastModified: new Date(lastModified) } : {},
|
|
606
|
+
...alternates ? { alternates } : {}
|
|
607
|
+
}));
|
|
606
608
|
});
|
|
607
|
-
|
|
609
|
+
if (!options.extra) return entries;
|
|
610
|
+
const extra = typeof options.extra === "function" ? await options.extra({ baseUrl, defaultLocale, locales }) : options.extra;
|
|
611
|
+
return [...entries, ...extra];
|
|
608
612
|
};
|
|
609
613
|
}
|
|
610
614
|
function pick(value, locale, defaultLocale) {
|
|
@@ -618,8 +622,7 @@ async function buildCmssyMetadata(config, path, options = {}) {
|
|
|
618
622
|
org: config.org,
|
|
619
623
|
workspaceSlug: config.workspaceSlug
|
|
620
624
|
};
|
|
621
|
-
const [
|
|
622
|
-
react.fetchPageMeta(clientConfig, path).catch(() => null),
|
|
625
|
+
const [siteConfig, baseUrl] = await Promise.all([
|
|
623
626
|
react.fetchSiteConfig(clientConfig).catch(() => null),
|
|
624
627
|
resolveSeoBaseUrl(config, options.baseUrl)
|
|
625
628
|
]);
|
|
@@ -627,20 +630,30 @@ async function buildCmssyMetadata(config, path, options = {}) {
|
|
|
627
630
|
config,
|
|
628
631
|
siteConfig
|
|
629
632
|
);
|
|
630
|
-
const
|
|
631
|
-
const
|
|
633
|
+
const segments = Array.isArray(path) ? path : path ? path.split("/").filter(Boolean) : void 0;
|
|
634
|
+
const fromPath = react.splitLocaleFromPath(segments, {
|
|
635
|
+
defaultLocale,
|
|
636
|
+
locales: enabledLocales
|
|
637
|
+
});
|
|
638
|
+
const locale = options.locale ?? (fromPath.locale !== defaultLocale ? fromPath.locale : await config.resolveLocale?.() ?? defaultLocale);
|
|
639
|
+
const slug = react.normalizeSlug(fromPath.path);
|
|
640
|
+
const meta = await react.fetchPageMeta(clientConfig, slug).catch(() => null);
|
|
632
641
|
const siteName = pick(siteConfig?.siteName, locale, defaultLocale) || siteConfig?.branding?.brandName || void 0;
|
|
633
642
|
const title = pick(meta?.seoTitle, locale, defaultLocale) || pick(meta?.displayName, locale, defaultLocale) || siteName || "";
|
|
634
643
|
const description = pick(meta?.seoDescription, locale, defaultLocale);
|
|
635
644
|
const keywords = meta?.seoKeywords?.length ? meta.seoKeywords : void 0;
|
|
636
645
|
const image = options.image ?? siteConfig?.branding?.ogImageUrl ?? void 0;
|
|
637
646
|
const canonical = baseUrl ? `${baseUrl}${localizedPath(slug, locale, defaultLocale)}` : void 0;
|
|
638
|
-
const languages = baseUrl && enabledLocales.length > 1 ?
|
|
639
|
-
|
|
640
|
-
l
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
647
|
+
const languages = baseUrl && enabledLocales.length > 1 ? {
|
|
648
|
+
...Object.fromEntries(
|
|
649
|
+
enabledLocales.map((l) => [
|
|
650
|
+
l,
|
|
651
|
+
`${baseUrl}${localizedPath(slug, l, defaultLocale)}`
|
|
652
|
+
])
|
|
653
|
+
),
|
|
654
|
+
// What to serve a reader whose language none of these match.
|
|
655
|
+
"x-default": `${baseUrl}${localizedPath(slug, defaultLocale, defaultLocale)}`
|
|
656
|
+
} : void 0;
|
|
644
657
|
return {
|
|
645
658
|
...baseUrl ? { metadataBase: new URL(baseUrl) } : {},
|
|
646
659
|
...title ? { title } : {},
|
package/dist/index.d.cts
CHANGED
|
@@ -180,9 +180,20 @@ interface CreateCmssyRobotsOptions extends SeoBaseUrlOption {
|
|
|
180
180
|
*/
|
|
181
181
|
declare function createCmssyRobots(config: CmssyNextConfig, options?: CreateCmssyRobotsOptions): () => Promise<MetadataRoute.Robots>;
|
|
182
182
|
|
|
183
|
+
/** What an `extra` resolver needs to build URLs that agree with the page ones. */
|
|
184
|
+
interface CmssySitemapContext {
|
|
185
|
+
baseUrl: string;
|
|
186
|
+
defaultLocale: string;
|
|
187
|
+
locales: string[];
|
|
188
|
+
}
|
|
183
189
|
interface CreateCmssySitemapOptions extends SeoBaseUrlOption {
|
|
184
|
-
/**
|
|
185
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Entries appended to the generated page list - the URLs a workspace's PAGES
|
|
192
|
+
* cannot express, like a product or a category rendered from model records.
|
|
193
|
+
* Pass a resolver to build them at request time; it gets the same baseUrl and
|
|
194
|
+
* locales the page entries use, so the two cannot disagree.
|
|
195
|
+
*/
|
|
196
|
+
extra?: MetadataRoute.Sitemap | ((context: CmssySitemapContext) => MetadataRoute.Sitemap | Promise<MetadataRoute.Sitemap>);
|
|
186
197
|
/**
|
|
187
198
|
* Additional page slugs to omit. The workspace's configured 404 page
|
|
188
199
|
* (Settings → 404 page) is excluded automatically via its id, so this is
|
|
@@ -206,6 +217,12 @@ interface BuildCmssyMetadataOptions extends SeoBaseUrlOption {
|
|
|
206
217
|
ogType?: string;
|
|
207
218
|
/** Twitter card. Defaults to "summary_large_image" when an image exists. */
|
|
208
219
|
twitterCard?: "summary" | "summary_large_image";
|
|
220
|
+
/**
|
|
221
|
+
* The language to render metadata in. Only needed when the language does not
|
|
222
|
+
* live in the URL (a per-domain or cookie strategy); with a locale prefix the
|
|
223
|
+
* path already says it.
|
|
224
|
+
*/
|
|
225
|
+
locale?: string;
|
|
209
226
|
}
|
|
210
227
|
/**
|
|
211
228
|
* Builds complete Next.js `Metadata` for a cmssy page from its SEO fields and
|
|
@@ -213,10 +230,14 @@ interface BuildCmssyMetadataOptions extends SeoBaseUrlOption {
|
|
|
213
230
|
* `hreflang` alternates, and Open Graph / Twitter cards (with the branding OG
|
|
214
231
|
* image). Use in a route's `generateMetadata`:
|
|
215
232
|
*
|
|
216
|
-
* export const generateMetadata = ({ params }) =>
|
|
233
|
+
* export const generateMetadata = async ({ params }) =>
|
|
217
234
|
* buildCmssyMetadata(cmssy, (await params).path);
|
|
218
235
|
*
|
|
219
|
-
*
|
|
236
|
+
* Pass the catch-all segments **as routed**, locale prefix and all: the prefix
|
|
237
|
+
* is what says which language this page is. Stripping it first (and leaving the
|
|
238
|
+
* language to `config.resolveLocale`) is how every localized page ends up with
|
|
239
|
+
* the default language's title - and a canonical pointing at the default
|
|
240
|
+
* language's URL, which tells Google the translation is a duplicate.
|
|
220
241
|
*/
|
|
221
242
|
declare function buildCmssyMetadata(config: CmssyNextConfig, path?: string | string[], options?: BuildCmssyMetadataOptions): Promise<Metadata>;
|
|
222
243
|
|
|
@@ -356,4 +377,4 @@ declare class CmssyWebhookError extends Error {
|
|
|
356
377
|
*/
|
|
357
378
|
declare function verifyCmssyWebhook(options: VerifyCmssyWebhookOptions): CmssyWebhookEvent;
|
|
358
379
|
|
|
359
|
-
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_PATH_PREFIX, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, cmssyEditRewrite, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyEditMiddleware, createCmssyEditPage, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
|
380
|
+
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_PATH_PREFIX, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, type CmssySitemapContext, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, cmssyEditRewrite, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyEditMiddleware, createCmssyEditPage, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
package/dist/index.d.ts
CHANGED
|
@@ -180,9 +180,20 @@ interface CreateCmssyRobotsOptions extends SeoBaseUrlOption {
|
|
|
180
180
|
*/
|
|
181
181
|
declare function createCmssyRobots(config: CmssyNextConfig, options?: CreateCmssyRobotsOptions): () => Promise<MetadataRoute.Robots>;
|
|
182
182
|
|
|
183
|
+
/** What an `extra` resolver needs to build URLs that agree with the page ones. */
|
|
184
|
+
interface CmssySitemapContext {
|
|
185
|
+
baseUrl: string;
|
|
186
|
+
defaultLocale: string;
|
|
187
|
+
locales: string[];
|
|
188
|
+
}
|
|
183
189
|
interface CreateCmssySitemapOptions extends SeoBaseUrlOption {
|
|
184
|
-
/**
|
|
185
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Entries appended to the generated page list - the URLs a workspace's PAGES
|
|
192
|
+
* cannot express, like a product or a category rendered from model records.
|
|
193
|
+
* Pass a resolver to build them at request time; it gets the same baseUrl and
|
|
194
|
+
* locales the page entries use, so the two cannot disagree.
|
|
195
|
+
*/
|
|
196
|
+
extra?: MetadataRoute.Sitemap | ((context: CmssySitemapContext) => MetadataRoute.Sitemap | Promise<MetadataRoute.Sitemap>);
|
|
186
197
|
/**
|
|
187
198
|
* Additional page slugs to omit. The workspace's configured 404 page
|
|
188
199
|
* (Settings → 404 page) is excluded automatically via its id, so this is
|
|
@@ -206,6 +217,12 @@ interface BuildCmssyMetadataOptions extends SeoBaseUrlOption {
|
|
|
206
217
|
ogType?: string;
|
|
207
218
|
/** Twitter card. Defaults to "summary_large_image" when an image exists. */
|
|
208
219
|
twitterCard?: "summary" | "summary_large_image";
|
|
220
|
+
/**
|
|
221
|
+
* The language to render metadata in. Only needed when the language does not
|
|
222
|
+
* live in the URL (a per-domain or cookie strategy); with a locale prefix the
|
|
223
|
+
* path already says it.
|
|
224
|
+
*/
|
|
225
|
+
locale?: string;
|
|
209
226
|
}
|
|
210
227
|
/**
|
|
211
228
|
* Builds complete Next.js `Metadata` for a cmssy page from its SEO fields and
|
|
@@ -213,10 +230,14 @@ interface BuildCmssyMetadataOptions extends SeoBaseUrlOption {
|
|
|
213
230
|
* `hreflang` alternates, and Open Graph / Twitter cards (with the branding OG
|
|
214
231
|
* image). Use in a route's `generateMetadata`:
|
|
215
232
|
*
|
|
216
|
-
* export const generateMetadata = ({ params }) =>
|
|
233
|
+
* export const generateMetadata = async ({ params }) =>
|
|
217
234
|
* buildCmssyMetadata(cmssy, (await params).path);
|
|
218
235
|
*
|
|
219
|
-
*
|
|
236
|
+
* Pass the catch-all segments **as routed**, locale prefix and all: the prefix
|
|
237
|
+
* is what says which language this page is. Stripping it first (and leaving the
|
|
238
|
+
* language to `config.resolveLocale`) is how every localized page ends up with
|
|
239
|
+
* the default language's title - and a canonical pointing at the default
|
|
240
|
+
* language's URL, which tells Google the translation is a duplicate.
|
|
220
241
|
*/
|
|
221
242
|
declare function buildCmssyMetadata(config: CmssyNextConfig, path?: string | string[], options?: BuildCmssyMetadataOptions): Promise<Metadata>;
|
|
222
243
|
|
|
@@ -356,4 +377,4 @@ declare class CmssyWebhookError extends Error {
|
|
|
356
377
|
*/
|
|
357
378
|
declare function verifyCmssyWebhook(options: VerifyCmssyWebhookOptions): CmssyWebhookEvent;
|
|
358
379
|
|
|
359
|
-
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_PATH_PREFIX, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, cmssyEditRewrite, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyEditMiddleware, createCmssyEditPage, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
|
380
|
+
export { type BuildCmssyMetadataOptions, CMSSY_CART_COOKIE, CMSSY_EDIT_HEADER, CMSSY_EDIT_PATH_PREFIX, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_SECRET_QUERY_PARAM, CMSSY_SESSION_COOKIE, type CmssyAuthMiddleware, type CmssyAuthRouteHandlers, type CmssyCartRouteHandlers, type CmssyCspOptions, type CmssyDraftRouteConfig, type CmssyEditorProps, type CmssyEnvConfig, type CmssyNextConfig, type CmssyOrdersRouteHandlers, type CmssySitemapContext, CmssyWebhookError, type CreateCmssyNotFoundOptions, type CreateCmssyPageOptions, type CreateCmssyRobotsOptions, type CreateCmssySitemapOptions, DEFAULT_CMSSY_EDITOR_ORIGINS, SESSION_MAX_AGE_SECONDS, applyCmssyCsp, assertAuthConfig, buildCmssyMetadata, cmssyCspHeaders, cmssyEditRewrite, createCmssyAuthMiddleware, createCmssyAuthRoute, createCmssyCartRoute, createCmssyEditMiddleware, createCmssyEditPage, createCmssyLocaleMiddleware, createCmssyNotFound, createCmssyOrdersRoute, createCmssyPage, createCmssyRobots, createCmssySitemap, createDraftRoute, defineCmssyConfig, fetchOrderByToken, fetchProduct, fetchProducts, getCmssyAccessToken, getCmssyLocale, getCmssyUser, isAccessExpired, isCmssyEditMode, isCmssyEditRequest, localeForPathname, openSession, resolveEditorOrigin, resolveLocaleFromPathname, sealSession, sessionCookieOptions, splitCmssyLocale, verifyCmssyWebhook };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { headers, draftMode, cookies } from 'next/headers';
|
|
2
2
|
import { notFound, redirect } from 'next/navigation';
|
|
3
|
-
import { createCmssyClient, resolveSiteLocales, splitLocaleFromPath, fetchPage, resolveForms, CmssyServerPage, fetchSiteConfig, fetchPageById, fetchPages,
|
|
3
|
+
import { createCmssyClient, resolveSiteLocales, splitLocaleFromPath, fetchPage, resolveForms, CmssyServerPage, fetchSiteConfig, fetchPageById, fetchPages, normalizeSlug as normalizeSlug$1, fetchPageMeta, resolveWorkspaceId, graphqlRequest, resolveApiUrl } from '@cmssy/react';
|
|
4
4
|
export { DEFAULT_CMSSY_API_URL, evaluateFieldConditionGroup, resolveApiUrl } from '@cmssy/react';
|
|
5
5
|
import { CmssyLocaleProvider } from '@cmssy/react/client';
|
|
6
6
|
import { EncryptJWT, jwtDecrypt } from 'jose';
|
|
@@ -585,25 +585,29 @@ function createCmssySitemap(config, options = {}) {
|
|
|
585
585
|
const baseUrl = await resolveSeoBaseUrl(config, options.baseUrl);
|
|
586
586
|
const { defaultLocale, locales } = resolveSeoLocales(config, siteConfig);
|
|
587
587
|
const excluded = new Set((options.excludeSlugs ?? []).map(normalizeSlug));
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
locales.map((locale) => [
|
|
598
|
-
locale,
|
|
599
|
-
`${baseUrl}${localizedPath(page.slug, locale, defaultLocale)}`
|
|
600
|
-
])
|
|
601
|
-
)
|
|
602
|
-
};
|
|
588
|
+
const languagesFor = (slug) => locales.length > 1 ? {
|
|
589
|
+
languages: {
|
|
590
|
+
...Object.fromEntries(
|
|
591
|
+
locales.map((locale) => [
|
|
592
|
+
locale,
|
|
593
|
+
`${baseUrl}${localizedPath(slug, locale, defaultLocale)}`
|
|
594
|
+
])
|
|
595
|
+
),
|
|
596
|
+
"x-default": `${baseUrl}${localizedPath(slug, defaultLocale, defaultLocale)}`
|
|
603
597
|
}
|
|
604
|
-
|
|
598
|
+
} : void 0;
|
|
599
|
+
const entries = pages.map((page) => ({ ...page, slug: normalizeSlug(page.slug) })).filter((page) => page.id !== notFoundPageId && !excluded.has(page.slug)).flatMap((page) => {
|
|
600
|
+
const lastModified = page.updatedAt ?? page.publishedAt ?? void 0;
|
|
601
|
+
const alternates = languagesFor(page.slug);
|
|
602
|
+
return locales.map((locale) => ({
|
|
603
|
+
url: `${baseUrl}${localizedPath(page.slug, locale, defaultLocale)}`,
|
|
604
|
+
...lastModified ? { lastModified: new Date(lastModified) } : {},
|
|
605
|
+
...alternates ? { alternates } : {}
|
|
606
|
+
}));
|
|
605
607
|
});
|
|
606
|
-
|
|
608
|
+
if (!options.extra) return entries;
|
|
609
|
+
const extra = typeof options.extra === "function" ? await options.extra({ baseUrl, defaultLocale, locales }) : options.extra;
|
|
610
|
+
return [...entries, ...extra];
|
|
607
611
|
};
|
|
608
612
|
}
|
|
609
613
|
function pick(value, locale, defaultLocale) {
|
|
@@ -617,8 +621,7 @@ async function buildCmssyMetadata(config, path, options = {}) {
|
|
|
617
621
|
org: config.org,
|
|
618
622
|
workspaceSlug: config.workspaceSlug
|
|
619
623
|
};
|
|
620
|
-
const [
|
|
621
|
-
fetchPageMeta(clientConfig, path).catch(() => null),
|
|
624
|
+
const [siteConfig, baseUrl] = await Promise.all([
|
|
622
625
|
fetchSiteConfig(clientConfig).catch(() => null),
|
|
623
626
|
resolveSeoBaseUrl(config, options.baseUrl)
|
|
624
627
|
]);
|
|
@@ -626,20 +629,30 @@ async function buildCmssyMetadata(config, path, options = {}) {
|
|
|
626
629
|
config,
|
|
627
630
|
siteConfig
|
|
628
631
|
);
|
|
629
|
-
const
|
|
630
|
-
const
|
|
632
|
+
const segments = Array.isArray(path) ? path : path ? path.split("/").filter(Boolean) : void 0;
|
|
633
|
+
const fromPath = splitLocaleFromPath(segments, {
|
|
634
|
+
defaultLocale,
|
|
635
|
+
locales: enabledLocales
|
|
636
|
+
});
|
|
637
|
+
const locale = options.locale ?? (fromPath.locale !== defaultLocale ? fromPath.locale : await config.resolveLocale?.() ?? defaultLocale);
|
|
638
|
+
const slug = normalizeSlug$1(fromPath.path);
|
|
639
|
+
const meta = await fetchPageMeta(clientConfig, slug).catch(() => null);
|
|
631
640
|
const siteName = pick(siteConfig?.siteName, locale, defaultLocale) || siteConfig?.branding?.brandName || void 0;
|
|
632
641
|
const title = pick(meta?.seoTitle, locale, defaultLocale) || pick(meta?.displayName, locale, defaultLocale) || siteName || "";
|
|
633
642
|
const description = pick(meta?.seoDescription, locale, defaultLocale);
|
|
634
643
|
const keywords = meta?.seoKeywords?.length ? meta.seoKeywords : void 0;
|
|
635
644
|
const image = options.image ?? siteConfig?.branding?.ogImageUrl ?? void 0;
|
|
636
645
|
const canonical = baseUrl ? `${baseUrl}${localizedPath(slug, locale, defaultLocale)}` : void 0;
|
|
637
|
-
const languages = baseUrl && enabledLocales.length > 1 ?
|
|
638
|
-
|
|
639
|
-
l
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
646
|
+
const languages = baseUrl && enabledLocales.length > 1 ? {
|
|
647
|
+
...Object.fromEntries(
|
|
648
|
+
enabledLocales.map((l) => [
|
|
649
|
+
l,
|
|
650
|
+
`${baseUrl}${localizedPath(slug, l, defaultLocale)}`
|
|
651
|
+
])
|
|
652
|
+
),
|
|
653
|
+
// What to serve a reader whose language none of these match.
|
|
654
|
+
"x-default": `${baseUrl}${localizedPath(slug, defaultLocale, defaultLocale)}`
|
|
655
|
+
} : void 0;
|
|
643
656
|
return {
|
|
644
657
|
...baseUrl ? { metadataBase: new URL(baseUrl) } : {},
|
|
645
658
|
...title ? { title } : {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmssy/next",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Next.js App Router bindings for cmssy headless sites (createCmssyPage + draft preview)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cmssy",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"dist"
|
|
42
42
|
],
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"@cmssy/react": "^4.0
|
|
44
|
+
"@cmssy/react": "^4.2.0",
|
|
45
45
|
"next": ">=15",
|
|
46
46
|
"react": "^18.2.0 || ^19.0.0",
|
|
47
47
|
"react-dom": "^18.2.0 || ^19.0.0"
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"tsup": "^8.3.0",
|
|
56
56
|
"typescript": "^5.6.0",
|
|
57
57
|
"vitest": "^2.1.0",
|
|
58
|
-
"@cmssy/react": "4.0
|
|
58
|
+
"@cmssy/react": "4.2.0"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"jose": "^6.2.3",
|