@justanarthur/payload-www 0.1.2 → 0.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/README.md +2 -1
- package/dist/collections.d.ts +31 -2
- package/dist/collections.js +30 -11
- package/dist/config.d.ts +8 -0
- package/dist/config.js +37 -15
- package/dist/core-fields.d.ts +8 -0
- package/dist/core-fields.js +5 -1
- package/dist/data-collections.d.ts +31 -2
- package/dist/data-collections.js +30 -11
- package/dist/data-test.js +37 -15
- package/dist/fields.d.ts +8 -0
- package/dist/fields.js +5 -1
- package/dist/globals.d.ts +23 -2
- package/dist/globals.js +21 -7
- package/dist/pages.d.ts +14 -1
- package/dist/pages.js +8 -8
- package/dist/render-pages.d.ts +14 -1
- package/dist/render-pages.js +8 -8
- package/dist/render-utils.d.ts +8 -0
- package/dist/render-utils.js +4 -2
- package/dist/server.d.ts +65 -7
- package/dist/server.js +45 -23
- package/dist/test.js +37 -15
- package/dist/with-www-config.d.ts +8 -0
- package/dist/with-www-config.js +37 -15
- package/package.json +1 -1
package/dist/data-test.js
CHANGED
|
@@ -201,20 +201,25 @@ var createPagesCollection = (blocks, options = {}) => {
|
|
|
201
201
|
renderPath = PAGES_RENDER_PATH,
|
|
202
202
|
slug: collectionSlug = PAGES_SLUG2,
|
|
203
203
|
localePrefix,
|
|
204
|
-
defaultLocale
|
|
204
|
+
defaultLocale,
|
|
205
|
+
nested = false
|
|
205
206
|
} = options;
|
|
207
|
+
const slugPattern = nested ? /^[a-z0-9_-]+$/ : /^[a-z0-9-]+$/;
|
|
206
208
|
const slugField = {
|
|
207
209
|
name: "slug",
|
|
208
210
|
type: "text",
|
|
209
211
|
required: true,
|
|
210
212
|
unique: true,
|
|
211
213
|
index: true,
|
|
212
|
-
admin: {
|
|
214
|
+
admin: {
|
|
215
|
+
position: "sidebar",
|
|
216
|
+
...nested ? { description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`." } : {}
|
|
217
|
+
},
|
|
213
218
|
validate: (value) => {
|
|
214
219
|
if (typeof value !== "string")
|
|
215
220
|
return "Slug must be a string";
|
|
216
|
-
if (value !== "" &&
|
|
217
|
-
return "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
221
|
+
if (value !== "" && !slugPattern.test(value)) {
|
|
222
|
+
return nested ? "Slug must be lowercase, with hyphens or the `_` nesting divider (no spaces or other special characters)" : "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
218
223
|
}
|
|
219
224
|
return true;
|
|
220
225
|
}
|
|
@@ -426,7 +431,8 @@ var link = (options = {}) => {
|
|
|
426
431
|
disableLabel = false,
|
|
427
432
|
relationTo = [PAGES_SLUG],
|
|
428
433
|
localized = false,
|
|
429
|
-
overrides = {}
|
|
434
|
+
overrides = {},
|
|
435
|
+
extraFields = []
|
|
430
436
|
} = options;
|
|
431
437
|
const result = {
|
|
432
438
|
name: "link",
|
|
@@ -503,6 +509,9 @@ var link = (options = {}) => {
|
|
|
503
509
|
options: opts
|
|
504
510
|
});
|
|
505
511
|
}
|
|
512
|
+
if (extraFields.length) {
|
|
513
|
+
result.fields.push(...extraFields);
|
|
514
|
+
}
|
|
506
515
|
return { ...result, ...overrides };
|
|
507
516
|
};
|
|
508
517
|
|
|
@@ -522,17 +531,22 @@ function createRevalidateGlobalHook(slug) {
|
|
|
522
531
|
|
|
523
532
|
// src/data/collections/globals/Header/config.ts
|
|
524
533
|
var createHeaderGlobal = (options = {}) => {
|
|
525
|
-
const {
|
|
534
|
+
const {
|
|
535
|
+
renderPath = HEADER_RENDER_PATH,
|
|
536
|
+
linkRelationTo = [PAGES_SLUG],
|
|
537
|
+
navColumnLinkFields = [],
|
|
538
|
+
navItemLinkFields = []
|
|
539
|
+
} = options;
|
|
526
540
|
const navColumnBlock = {
|
|
527
541
|
slug: "navColumn",
|
|
528
542
|
fields: [
|
|
529
543
|
{ name: "title", type: "text", required: true, localized: true },
|
|
530
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
544
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
531
545
|
]
|
|
532
546
|
};
|
|
533
547
|
const navItemBlock = {
|
|
534
548
|
slug: "navItem",
|
|
535
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
549
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
536
550
|
};
|
|
537
551
|
return {
|
|
538
552
|
slug: "header",
|
|
@@ -554,17 +568,22 @@ var createHeaderGlobal = (options = {}) => {
|
|
|
554
568
|
|
|
555
569
|
// src/data/collections/globals/Footer/config.ts
|
|
556
570
|
var createFooterGlobal = (options = {}) => {
|
|
557
|
-
const {
|
|
571
|
+
const {
|
|
572
|
+
renderPath = FOOTER_RENDER_PATH,
|
|
573
|
+
linkRelationTo = [PAGES_SLUG],
|
|
574
|
+
navColumnLinkFields = [],
|
|
575
|
+
navItemLinkFields = []
|
|
576
|
+
} = options;
|
|
558
577
|
const navColumnBlock = {
|
|
559
578
|
slug: "navColumn",
|
|
560
579
|
fields: [
|
|
561
580
|
{ name: "title", type: "text", required: true, localized: true },
|
|
562
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
581
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
563
582
|
]
|
|
564
583
|
};
|
|
565
584
|
const navItemBlock = {
|
|
566
585
|
slug: "navItem",
|
|
567
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
586
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
568
587
|
};
|
|
569
588
|
return {
|
|
570
589
|
slug: "footer",
|
|
@@ -762,6 +781,7 @@ function createSitemapFile(options) {
|
|
|
762
781
|
const collectionDefaults = options.perCollection?.[collectionSlug] ?? {};
|
|
763
782
|
const urlPrefix = (options.urlPrefixes?.[collectionSlug] ?? "").replace(/\/$/, "");
|
|
764
783
|
const siteUrl = options.getServerSideURL().replace(/\/$/, "");
|
|
784
|
+
const isNested = options.nested?.[collectionSlug] ?? false;
|
|
765
785
|
for (const locale of activeLocales) {
|
|
766
786
|
const docs = await queryAllDocs({
|
|
767
787
|
collectionSlug,
|
|
@@ -777,13 +797,14 @@ function createSitemapFile(options) {
|
|
|
777
797
|
if (seen.has(dedupeKey))
|
|
778
798
|
continue;
|
|
779
799
|
seen.add(dedupeKey);
|
|
780
|
-
const
|
|
800
|
+
const slugPath = isNested ? storedSlug.replaceAll("_", "/") : storedSlug;
|
|
801
|
+
const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${slugPath}`;
|
|
781
802
|
const languages = await buildHreflangAlternates({
|
|
782
803
|
siteUrl,
|
|
783
804
|
locale,
|
|
784
805
|
urlPrefix,
|
|
785
806
|
storedSlug,
|
|
786
|
-
nested:
|
|
807
|
+
nested: isNested,
|
|
787
808
|
homeSlug: "",
|
|
788
809
|
defaultLocale,
|
|
789
810
|
locales: activeLocales,
|
|
@@ -814,7 +835,7 @@ function createSitemapFile(options) {
|
|
|
814
835
|
}
|
|
815
836
|
// src/config/createWWWConfig.ts
|
|
816
837
|
function createWWWConfig(options) {
|
|
817
|
-
const { locales, routing, blocks, linkRelationTo, registerPosts = true, defaultPlugins } = options;
|
|
838
|
+
const { locales, routing, blocks, linkRelationTo, registerPosts = true, nested = false, defaultPlugins } = options;
|
|
818
839
|
const defaultLocale = routing?.defaultLocale ?? locales[0] ?? "";
|
|
819
840
|
const localePrefixMode = (() => {
|
|
820
841
|
const raw = routing?.localePrefix;
|
|
@@ -827,7 +848,8 @@ function createWWWConfig(options) {
|
|
|
827
848
|
}
|
|
828
849
|
const buildPagesCollection = () => createPagesCollection(blocks, {
|
|
829
850
|
localePrefix: localePrefixMode,
|
|
830
|
-
defaultLocale
|
|
851
|
+
defaultLocale,
|
|
852
|
+
nested
|
|
831
853
|
});
|
|
832
854
|
const buildPostsCollection = () => createPostsCollection({
|
|
833
855
|
localePrefix: localePrefixMode,
|
package/dist/fields.d.ts
CHANGED
|
@@ -20,6 +20,14 @@ type LinkOptions = {
|
|
|
20
20
|
overrides?: Partial<GroupField>;
|
|
21
21
|
/** Legacy alias for the host's custom field overrides. */
|
|
22
22
|
linkOverrides?: Partial<GroupField>;
|
|
23
|
+
/**
|
|
24
|
+
* Extra fields appended to the link group — e.g. a `description`
|
|
25
|
+
* text field or a `navHover` group for a mega-menu. Lets hosts
|
|
26
|
+
* extend the nav link schema without re-implementing the whole
|
|
27
|
+
* `link` field. Appended after the standard type/label/appearance
|
|
28
|
+
* fields.
|
|
29
|
+
*/
|
|
30
|
+
extraFields?: Field[];
|
|
23
31
|
};
|
|
24
32
|
declare const link: (options?: LinkOptions) => Field;
|
|
25
33
|
import { Field as Field2 } from "payload";
|
package/dist/fields.js
CHANGED
|
@@ -36,7 +36,8 @@ var link = (options = {}) => {
|
|
|
36
36
|
disableLabel = false,
|
|
37
37
|
relationTo = [PAGES_SLUG],
|
|
38
38
|
localized = false,
|
|
39
|
-
overrides = {}
|
|
39
|
+
overrides = {},
|
|
40
|
+
extraFields = []
|
|
40
41
|
} = options;
|
|
41
42
|
const result = {
|
|
42
43
|
name: "link",
|
|
@@ -113,6 +114,9 @@ var link = (options = {}) => {
|
|
|
113
114
|
options: opts
|
|
114
115
|
});
|
|
115
116
|
}
|
|
117
|
+
if (extraFields.length) {
|
|
118
|
+
result.fields.push(...extraFields);
|
|
119
|
+
}
|
|
116
120
|
return { ...result, ...overrides };
|
|
117
121
|
};
|
|
118
122
|
|
package/dist/globals.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GlobalConfig } from "payload";
|
|
1
|
+
import { Field, GlobalConfig } from "payload";
|
|
2
2
|
type CreateHeaderGlobalOptions = {
|
|
3
3
|
/**
|
|
4
4
|
* Optional override for the `custom.path` Payload uses to resolve
|
|
@@ -12,6 +12,17 @@ type CreateHeaderGlobalOptions = {
|
|
|
12
12
|
* different list when your host has additional linkable collections.
|
|
13
13
|
*/
|
|
14
14
|
linkRelationTo?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Extra fields appended to each `navColumn` link — e.g. a
|
|
17
|
+
* `description` text field or a `navHover` group for a mega-menu.
|
|
18
|
+
* Lets hosts enrich the column-link schema without redefining the
|
|
19
|
+
* whole nav.
|
|
20
|
+
*/
|
|
21
|
+
navColumnLinkFields?: Field[];
|
|
22
|
+
/**
|
|
23
|
+
* Extra fields appended to each top-level `navItem` link.
|
|
24
|
+
*/
|
|
25
|
+
navItemLinkFields?: Field[];
|
|
15
26
|
};
|
|
16
27
|
/**
|
|
17
28
|
* Build the Header global. The lib's default shape: a `nav` blocks
|
|
@@ -19,7 +30,7 @@ type CreateHeaderGlobalOptions = {
|
|
|
19
30
|
* and `navItem` (a single link).
|
|
20
31
|
*/
|
|
21
32
|
declare const createHeaderGlobal: (options?: CreateHeaderGlobalOptions) => GlobalConfig;
|
|
22
|
-
import { GlobalConfig as GlobalConfig2 } from "payload";
|
|
33
|
+
import { Field as Field2, GlobalConfig as GlobalConfig2 } from "payload";
|
|
23
34
|
type CreateFooterGlobalOptions = {
|
|
24
35
|
/**
|
|
25
36
|
* Optional override for the `custom.path` Payload uses to resolve
|
|
@@ -33,6 +44,16 @@ type CreateFooterGlobalOptions = {
|
|
|
33
44
|
* different list when your host has additional linkable collections.
|
|
34
45
|
*/
|
|
35
46
|
linkRelationTo?: string[];
|
|
47
|
+
/**
|
|
48
|
+
* Extra fields appended to each `navColumn` link — e.g. a
|
|
49
|
+
* `description` text field. Lets hosts enrich the column-link
|
|
50
|
+
* schema without redefining the whole nav.
|
|
51
|
+
*/
|
|
52
|
+
navColumnLinkFields?: Field2[];
|
|
53
|
+
/**
|
|
54
|
+
* Extra fields appended to each top-level `navItem` link.
|
|
55
|
+
*/
|
|
56
|
+
navItemLinkFields?: Field2[];
|
|
36
57
|
};
|
|
37
58
|
/**
|
|
38
59
|
* Build the Footer global. The lib's default shape mirrors the
|
package/dist/globals.js
CHANGED
|
@@ -36,7 +36,8 @@ var link = (options = {}) => {
|
|
|
36
36
|
disableLabel = false,
|
|
37
37
|
relationTo = [PAGES_SLUG],
|
|
38
38
|
localized = false,
|
|
39
|
-
overrides = {}
|
|
39
|
+
overrides = {},
|
|
40
|
+
extraFields = []
|
|
40
41
|
} = options;
|
|
41
42
|
const result = {
|
|
42
43
|
name: "link",
|
|
@@ -113,6 +114,9 @@ var link = (options = {}) => {
|
|
|
113
114
|
options: opts
|
|
114
115
|
});
|
|
115
116
|
}
|
|
117
|
+
if (extraFields.length) {
|
|
118
|
+
result.fields.push(...extraFields);
|
|
119
|
+
}
|
|
116
120
|
return { ...result, ...overrides };
|
|
117
121
|
};
|
|
118
122
|
|
|
@@ -157,17 +161,22 @@ function createRevalidateGlobalHook(slug) {
|
|
|
157
161
|
|
|
158
162
|
// src/data/collections/globals/Header/config.ts
|
|
159
163
|
var createHeaderGlobal = (options = {}) => {
|
|
160
|
-
const {
|
|
164
|
+
const {
|
|
165
|
+
renderPath = HEADER_RENDER_PATH,
|
|
166
|
+
linkRelationTo = [PAGES_SLUG],
|
|
167
|
+
navColumnLinkFields = [],
|
|
168
|
+
navItemLinkFields = []
|
|
169
|
+
} = options;
|
|
161
170
|
const navColumnBlock = {
|
|
162
171
|
slug: "navColumn",
|
|
163
172
|
fields: [
|
|
164
173
|
{ name: "title", type: "text", required: true, localized: true },
|
|
165
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
174
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
166
175
|
]
|
|
167
176
|
};
|
|
168
177
|
const navItemBlock = {
|
|
169
178
|
slug: "navItem",
|
|
170
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
179
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
171
180
|
};
|
|
172
181
|
return {
|
|
173
182
|
slug: "header",
|
|
@@ -189,17 +198,22 @@ var createHeaderGlobal = (options = {}) => {
|
|
|
189
198
|
|
|
190
199
|
// src/data/collections/globals/Footer/config.ts
|
|
191
200
|
var createFooterGlobal = (options = {}) => {
|
|
192
|
-
const {
|
|
201
|
+
const {
|
|
202
|
+
renderPath = FOOTER_RENDER_PATH,
|
|
203
|
+
linkRelationTo = [PAGES_SLUG],
|
|
204
|
+
navColumnLinkFields = [],
|
|
205
|
+
navItemLinkFields = []
|
|
206
|
+
} = options;
|
|
193
207
|
const navColumnBlock = {
|
|
194
208
|
slug: "navColumn",
|
|
195
209
|
fields: [
|
|
196
210
|
{ name: "title", type: "text", required: true, localized: true },
|
|
197
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
211
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
198
212
|
]
|
|
199
213
|
};
|
|
200
214
|
const navItemBlock = {
|
|
201
215
|
slug: "navItem",
|
|
202
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
216
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
203
217
|
};
|
|
204
218
|
return {
|
|
205
219
|
slug: "footer",
|
package/dist/pages.d.ts
CHANGED
|
@@ -207,6 +207,19 @@ type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
|
|
|
207
207
|
* defined your own Server Component for the collection.
|
|
208
208
|
*/
|
|
209
209
|
renderPath?: string;
|
|
210
|
+
/**
|
|
211
|
+
* Enable nested (hierarchical) slugs. When `true`, the catch-all
|
|
212
|
+
* `[...slug]` segments are joined with the `_` divider to form the
|
|
213
|
+
* stored slug (URL `/about/us` ⇄ stored `about_us`), URL paths and
|
|
214
|
+
* hreflang alternates are expanded back to `/about/us`, and
|
|
215
|
+
* `generateStaticParams` emits multi-segment params. When `false`
|
|
216
|
+
* (the default) only the first URL segment is used — flat slugs.
|
|
217
|
+
*
|
|
218
|
+
* Pair with `createPagesCollection({ nested: true })` (or
|
|
219
|
+
* `createWWWConfig({ nested: true })`) so the collection's slug
|
|
220
|
+
* validation accepts the `_` divider.
|
|
221
|
+
*/
|
|
222
|
+
nested?: boolean;
|
|
210
223
|
};
|
|
211
224
|
type CreateCollectionPageExportsDeps<S extends string> = {
|
|
212
225
|
/**
|
|
@@ -285,7 +298,7 @@ type CreateCollectionPageExportsDeps<S extends string> = {
|
|
|
285
298
|
* { generateMetadata, generateStaticParams }
|
|
286
299
|
* Page
|
|
287
300
|
*/
|
|
288
|
-
declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
|
|
301
|
+
declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath, nested }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
|
|
289
302
|
default: (props: {
|
|
290
303
|
params: Promise<{
|
|
291
304
|
locale?: string;
|
package/dist/pages.js
CHANGED
|
@@ -687,7 +687,8 @@ function createCollectionPageExports({
|
|
|
687
687
|
config: configPromise,
|
|
688
688
|
routing,
|
|
689
689
|
importMap: importMapArg,
|
|
690
|
-
renderPath
|
|
690
|
+
renderPath,
|
|
691
|
+
nested = false
|
|
691
692
|
}, deps, options = {}) {
|
|
692
693
|
const importMap = importMapArg ?? {};
|
|
693
694
|
const { jsonLd: jsonLdOption = true, changefreq = "weekly", priority = 0.5, websiteName } = options;
|
|
@@ -706,7 +707,7 @@ function createCollectionPageExports({
|
|
|
706
707
|
const defaultRenderPath = slug === POSTS_SLUG ? POSTS_RENDER_PATH : PAGES_RENDER_PATH;
|
|
707
708
|
const localePrefixMode = typeof routing.localePrefix === "string" ? routing.localePrefix : routing.localePrefix?.mode ?? "always";
|
|
708
709
|
const buildLocalePath = (locale, storedSlug) => {
|
|
709
|
-
const urlPath = getUrlPath(storedSlug,
|
|
710
|
+
const urlPath = getUrlPath(storedSlugToSegments(storedSlug, nested), nested, HOME_SLUG);
|
|
710
711
|
if (localePrefixMode === "never")
|
|
711
712
|
return urlPath;
|
|
712
713
|
if (localePrefixMode === "as-needed" && locale === defaultLocale)
|
|
@@ -731,7 +732,7 @@ function createCollectionPageExports({
|
|
|
731
732
|
locale,
|
|
732
733
|
urlPrefix: "",
|
|
733
734
|
storedSlug,
|
|
734
|
-
nested
|
|
735
|
+
nested,
|
|
735
736
|
homeSlug: HOME_SLUG,
|
|
736
737
|
defaultLocale,
|
|
737
738
|
locales,
|
|
@@ -756,7 +757,7 @@ function createCollectionPageExports({
|
|
|
756
757
|
setRequestLocale(locale);
|
|
757
758
|
const { draftMode } = await import("next/headers");
|
|
758
759
|
const { isEnabled: draft } = await draftMode();
|
|
759
|
-
const storedSlug = segmentsToStoredSlug(slugSegments,
|
|
760
|
+
const storedSlug = segmentsToStoredSlug(slugSegments, nested);
|
|
760
761
|
const doc = await fetchDoc(locale, storedSlug, draft);
|
|
761
762
|
if (!doc) {
|
|
762
763
|
const { notFound } = await import("next/navigation");
|
|
@@ -779,7 +780,6 @@ function createCollectionPageExports({
|
|
|
779
780
|
});
|
|
780
781
|
const jsonLdNodes = doc ? await generateJsonLd(slugSegments, doc, locale) : [];
|
|
781
782
|
const { alternates: hreflangAlternates, canonical } = await resolveHreflangAlternates(locale, storedSlug);
|
|
782
|
-
console.log("render", { render, doc });
|
|
783
783
|
const inner = /* @__PURE__ */ jsxs5(Fragment6, {
|
|
784
784
|
children: [
|
|
785
785
|
jsonLdNodes.map(({ id, schema }) => /* @__PURE__ */ jsx8("script", {
|
|
@@ -829,7 +829,7 @@ function createCollectionPageExports({
|
|
|
829
829
|
const locale = typeof incomingLocale === "string" ? incomingLocale : defaultLocale;
|
|
830
830
|
if (!locales.includes(locale))
|
|
831
831
|
return { title: "Not found", robots: { index: false, follow: false } };
|
|
832
|
-
const storedSlug = segmentsToStoredSlug(slugSegments,
|
|
832
|
+
const storedSlug = segmentsToStoredSlug(slugSegments, nested);
|
|
833
833
|
const doc = await fetchDoc(locale, storedSlug);
|
|
834
834
|
if (!doc)
|
|
835
835
|
return { title: "Not found", robots: { index: false, follow: false } };
|
|
@@ -853,7 +853,7 @@ function createCollectionPageExports({
|
|
|
853
853
|
if (jsonLdOption === false || !doc)
|
|
854
854
|
return [];
|
|
855
855
|
const siteUrl = getServerSideURL();
|
|
856
|
-
const storedSlug = segmentsToStoredSlug(slugSegments,
|
|
856
|
+
const storedSlug = segmentsToStoredSlug(slugSegments, nested);
|
|
857
857
|
const urlPath = buildLocalePath(locale, storedSlug);
|
|
858
858
|
const canonical = `${siteUrl}${urlPath}`;
|
|
859
859
|
const entries = Array.isArray(jsonLdOption) ? jsonLdOption : metadataType === "article" ? [{ type: "article" }] : [{ type: "website" }];
|
|
@@ -924,7 +924,7 @@ function createCollectionPageExports({
|
|
|
924
924
|
const slugVal = doc.slug;
|
|
925
925
|
if (typeof slugVal !== "string" || slugVal === "")
|
|
926
926
|
continue;
|
|
927
|
-
const segments = storedSlugToSegments(slugVal,
|
|
927
|
+
const segments = storedSlugToSegments(slugVal, nested);
|
|
928
928
|
params.push({ slug: Array.isArray(segments) ? segments : [segments], locale });
|
|
929
929
|
}
|
|
930
930
|
}
|
package/dist/render-pages.d.ts
CHANGED
|
@@ -130,6 +130,19 @@ type CreateCollectionPageExportsArgs<S extends string = "pages"> = {
|
|
|
130
130
|
* defined your own Server Component for the collection.
|
|
131
131
|
*/
|
|
132
132
|
renderPath?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Enable nested (hierarchical) slugs. When `true`, the catch-all
|
|
135
|
+
* `[...slug]` segments are joined with the `_` divider to form the
|
|
136
|
+
* stored slug (URL `/about/us` ⇄ stored `about_us`), URL paths and
|
|
137
|
+
* hreflang alternates are expanded back to `/about/us`, and
|
|
138
|
+
* `generateStaticParams` emits multi-segment params. When `false`
|
|
139
|
+
* (the default) only the first URL segment is used — flat slugs.
|
|
140
|
+
*
|
|
141
|
+
* Pair with `createPagesCollection({ nested: true })` (or
|
|
142
|
+
* `createWWWConfig({ nested: true })`) so the collection's slug
|
|
143
|
+
* validation accepts the `_` divider.
|
|
144
|
+
*/
|
|
145
|
+
nested?: boolean;
|
|
133
146
|
};
|
|
134
147
|
type CreateCollectionPageExportsDeps<S extends string> = {
|
|
135
148
|
/**
|
|
@@ -208,7 +221,7 @@ type CreateCollectionPageExportsDeps<S extends string> = {
|
|
|
208
221
|
* { generateMetadata, generateStaticParams }
|
|
209
222
|
* Page
|
|
210
223
|
*/
|
|
211
|
-
declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
|
|
224
|
+
declare function createCollectionPageExports<S extends string = "pages">({ slug, config: configPromise, routing, importMap: importMapArg, renderPath, nested }: CreateCollectionPageExportsArgs<S>, deps: CreateCollectionPageExportsDeps<S>, options?: MetadataOptions): {
|
|
212
225
|
default: (props: {
|
|
213
226
|
params: Promise<{
|
|
214
227
|
locale?: string;
|
package/dist/render-pages.js
CHANGED
|
@@ -571,7 +571,8 @@ function createCollectionPageExports({
|
|
|
571
571
|
config: configPromise,
|
|
572
572
|
routing,
|
|
573
573
|
importMap: importMapArg,
|
|
574
|
-
renderPath
|
|
574
|
+
renderPath,
|
|
575
|
+
nested = false
|
|
575
576
|
}, deps, options = {}) {
|
|
576
577
|
const importMap = importMapArg ?? {};
|
|
577
578
|
const { jsonLd: jsonLdOption = true, changefreq = "weekly", priority = 0.5, websiteName } = options;
|
|
@@ -590,7 +591,7 @@ function createCollectionPageExports({
|
|
|
590
591
|
const defaultRenderPath = slug === POSTS_SLUG ? POSTS_RENDER_PATH : PAGES_RENDER_PATH;
|
|
591
592
|
const localePrefixMode = typeof routing.localePrefix === "string" ? routing.localePrefix : routing.localePrefix?.mode ?? "always";
|
|
592
593
|
const buildLocalePath = (locale, storedSlug) => {
|
|
593
|
-
const urlPath = getUrlPath(storedSlug,
|
|
594
|
+
const urlPath = getUrlPath(storedSlugToSegments(storedSlug, nested), nested, HOME_SLUG);
|
|
594
595
|
if (localePrefixMode === "never")
|
|
595
596
|
return urlPath;
|
|
596
597
|
if (localePrefixMode === "as-needed" && locale === defaultLocale)
|
|
@@ -615,7 +616,7 @@ function createCollectionPageExports({
|
|
|
615
616
|
locale,
|
|
616
617
|
urlPrefix: "",
|
|
617
618
|
storedSlug,
|
|
618
|
-
nested
|
|
619
|
+
nested,
|
|
619
620
|
homeSlug: HOME_SLUG,
|
|
620
621
|
defaultLocale,
|
|
621
622
|
locales,
|
|
@@ -640,7 +641,7 @@ function createCollectionPageExports({
|
|
|
640
641
|
setRequestLocale(locale);
|
|
641
642
|
const { draftMode } = await import("next/headers");
|
|
642
643
|
const { isEnabled: draft } = await draftMode();
|
|
643
|
-
const storedSlug = segmentsToStoredSlug(slugSegments,
|
|
644
|
+
const storedSlug = segmentsToStoredSlug(slugSegments, nested);
|
|
644
645
|
const doc = await fetchDoc(locale, storedSlug, draft);
|
|
645
646
|
if (!doc) {
|
|
646
647
|
const { notFound } = await import("next/navigation");
|
|
@@ -663,7 +664,6 @@ function createCollectionPageExports({
|
|
|
663
664
|
});
|
|
664
665
|
const jsonLdNodes = doc ? await generateJsonLd(slugSegments, doc, locale) : [];
|
|
665
666
|
const { alternates: hreflangAlternates, canonical } = await resolveHreflangAlternates(locale, storedSlug);
|
|
666
|
-
console.log("render", { render, doc });
|
|
667
667
|
const inner = /* @__PURE__ */ jsxs3(Fragment4, {
|
|
668
668
|
children: [
|
|
669
669
|
jsonLdNodes.map(({ id, schema }) => /* @__PURE__ */ jsx6("script", {
|
|
@@ -713,7 +713,7 @@ function createCollectionPageExports({
|
|
|
713
713
|
const locale = typeof incomingLocale === "string" ? incomingLocale : defaultLocale;
|
|
714
714
|
if (!locales.includes(locale))
|
|
715
715
|
return { title: "Not found", robots: { index: false, follow: false } };
|
|
716
|
-
const storedSlug = segmentsToStoredSlug(slugSegments,
|
|
716
|
+
const storedSlug = segmentsToStoredSlug(slugSegments, nested);
|
|
717
717
|
const doc = await fetchDoc(locale, storedSlug);
|
|
718
718
|
if (!doc)
|
|
719
719
|
return { title: "Not found", robots: { index: false, follow: false } };
|
|
@@ -737,7 +737,7 @@ function createCollectionPageExports({
|
|
|
737
737
|
if (jsonLdOption === false || !doc)
|
|
738
738
|
return [];
|
|
739
739
|
const siteUrl = getServerSideURL();
|
|
740
|
-
const storedSlug = segmentsToStoredSlug(slugSegments,
|
|
740
|
+
const storedSlug = segmentsToStoredSlug(slugSegments, nested);
|
|
741
741
|
const urlPath = buildLocalePath(locale, storedSlug);
|
|
742
742
|
const canonical = `${siteUrl}${urlPath}`;
|
|
743
743
|
const entries = Array.isArray(jsonLdOption) ? jsonLdOption : metadataType === "article" ? [{ type: "article" }] : [{ type: "website" }];
|
|
@@ -808,7 +808,7 @@ function createCollectionPageExports({
|
|
|
808
808
|
const slugVal = doc.slug;
|
|
809
809
|
if (typeof slugVal !== "string" || slugVal === "")
|
|
810
810
|
continue;
|
|
811
|
-
const segments = storedSlugToSegments(slugVal,
|
|
811
|
+
const segments = storedSlugToSegments(slugVal, nested);
|
|
812
812
|
params.push({ slug: Array.isArray(segments) ? segments : [segments], locale });
|
|
813
813
|
}
|
|
814
814
|
}
|
package/dist/render-utils.d.ts
CHANGED
|
@@ -89,6 +89,14 @@ type CreateSitemapFileOptions = {
|
|
|
89
89
|
priority?: number;
|
|
90
90
|
changefreq?: "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
91
91
|
}>;
|
|
92
|
+
/**
|
|
93
|
+
* Per-collection nested-slug flag. When a collection is marked
|
|
94
|
+
* `true`, its stored `about_us` slug is expanded into the
|
|
95
|
+
* `/about/us` URL path (and hreflang alternates), matching a
|
|
96
|
+
* `createCollectionPageExports({ nested: true })` route. Defaults
|
|
97
|
+
* to `false` (flat slugs) for every collection.
|
|
98
|
+
*/
|
|
99
|
+
nested?: Record<string, boolean>;
|
|
92
100
|
};
|
|
93
101
|
/**
|
|
94
102
|
* A Next.js sitemap function for the host's
|
package/dist/render-utils.js
CHANGED
|
@@ -279,6 +279,7 @@ function createSitemapFile(options) {
|
|
|
279
279
|
const collectionDefaults = options.perCollection?.[collectionSlug] ?? {};
|
|
280
280
|
const urlPrefix = (options.urlPrefixes?.[collectionSlug] ?? "").replace(/\/$/, "");
|
|
281
281
|
const siteUrl = options.getServerSideURL().replace(/\/$/, "");
|
|
282
|
+
const isNested = options.nested?.[collectionSlug] ?? false;
|
|
282
283
|
for (const locale of activeLocales) {
|
|
283
284
|
const docs = await queryAllDocs({
|
|
284
285
|
collectionSlug,
|
|
@@ -294,13 +295,14 @@ function createSitemapFile(options) {
|
|
|
294
295
|
if (seen.has(dedupeKey))
|
|
295
296
|
continue;
|
|
296
297
|
seen.add(dedupeKey);
|
|
297
|
-
const
|
|
298
|
+
const slugPath = isNested ? storedSlug.replaceAll("_", "/") : storedSlug;
|
|
299
|
+
const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${slugPath}`;
|
|
298
300
|
const languages = await buildHreflangAlternates({
|
|
299
301
|
siteUrl,
|
|
300
302
|
locale,
|
|
301
303
|
urlPrefix,
|
|
302
304
|
storedSlug,
|
|
303
|
-
nested:
|
|
305
|
+
nested: isNested,
|
|
304
306
|
homeSlug: "",
|
|
305
307
|
defaultLocale,
|
|
306
308
|
locales: activeLocales,
|