@sitecore-jss/sitecore-jss-nextjs 22.9.0-canary.1 → 22.9.0-canary.11
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/cjs/components/ComponentPropsContext.js +2 -2
- package/dist/cjs/editing/editing-data.js +1 -2
- package/dist/cjs/editing/editing-render-middleware.js +3 -2
- package/dist/cjs/editing/feaas-render-middleware.js +2 -2
- package/dist/cjs/middleware/redirects-middleware.js +4 -3
- package/dist/cjs/services/base-graphql-sitemap-service.js +88 -12
- package/dist/cjs/services/graphql-sitemap-service.js +2 -2
- package/dist/esm/editing/editing-render-middleware.js +3 -2
- package/dist/esm/editing/feaas-render-middleware.js +2 -2
- package/dist/esm/middleware/redirects-middleware.js +4 -3
- package/dist/esm/services/base-graphql-sitemap-service.js +86 -10
- package/package.json +25 -25
- package/types/components/ComponentPropsContext.d.ts +0 -1
- package/types/components/Link.d.ts +0 -1
- package/types/components/NextImage.d.ts +0 -1
- package/types/components/Placeholder.d.ts +0 -1
- package/types/editing/editing-render-middleware.d.ts +2 -2
- package/types/editing/render-middleware.d.ts +0 -1
- package/types/services/base-graphql-sitemap-service.d.ts +6 -0
- package/types/sharedTypes/module-factory.d.ts +0 -1
|
@@ -23,7 +23,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.ComponentPropsContext = exports.
|
|
26
|
+
exports.ComponentPropsContext = exports.ComponentPropsReactContext = void 0;
|
|
27
|
+
exports.useComponentProps = useComponentProps;
|
|
27
28
|
const react_1 = __importStar(require("react"));
|
|
28
29
|
/**
|
|
29
30
|
* Component props context which we are using in order to store data fetched on components level (getStaticProps/getServerSideProps)
|
|
@@ -42,6 +43,5 @@ function useComponentProps(componentUid) {
|
|
|
42
43
|
const data = (0, react_1.useContext)(exports.ComponentPropsReactContext);
|
|
43
44
|
return data[componentUid];
|
|
44
45
|
}
|
|
45
|
-
exports.useComponentProps = useComponentProps;
|
|
46
46
|
const ComponentPropsContext = ({ children, value, }) => (react_1.default.createElement(exports.ComponentPropsReactContext.Provider, { value: value }, children));
|
|
47
47
|
exports.ComponentPropsContext = ComponentPropsContext;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isEditingData =
|
|
3
|
+
exports.isEditingData = isEditingData;
|
|
4
4
|
/**
|
|
5
5
|
* @param {EditingData} data
|
|
6
6
|
*/
|
|
@@ -10,4 +10,3 @@ function isEditingData(data) {
|
|
|
10
10
|
data.layoutData !== undefined &&
|
|
11
11
|
data.dictionary !== undefined);
|
|
12
12
|
}
|
|
13
|
-
exports.isEditingData = isEditingData;
|
|
@@ -285,9 +285,10 @@ class MetadataHandler {
|
|
|
285
285
|
});
|
|
286
286
|
res.setHeader('Set-Cookie', modifiedCookies);
|
|
287
287
|
}
|
|
288
|
+
const encodedRoute = encodeURI(query.route);
|
|
288
289
|
const route = ((_c = (_b = this.config).resolvePageUrl) === null || _c === void 0 ? void 0 : _c.call(_b, {
|
|
289
|
-
itemPath:
|
|
290
|
-
})) ||
|
|
290
|
+
itemPath: encodedRoute,
|
|
291
|
+
})) || encodedRoute;
|
|
291
292
|
sitecore_jss_1.debug.editing('editing render middleware end in %dms: redirect %o', Date.now() - startTimestamp, {
|
|
292
293
|
status: 307,
|
|
293
294
|
route,
|
|
@@ -29,7 +29,7 @@ class FEAASRenderMiddleware extends render_middleware_1.RenderMiddlewareBase {
|
|
|
29
29
|
this.config = config;
|
|
30
30
|
this.defaultPageUrl = '/feaas/render';
|
|
31
31
|
this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
32
|
-
var
|
|
32
|
+
var _a;
|
|
33
33
|
const { method, query, headers } = req;
|
|
34
34
|
const startTimestamp = Date.now();
|
|
35
35
|
sitecore_jss_1.debug.editing('feaas render middleware start: %o', {
|
|
@@ -41,7 +41,7 @@ class FEAASRenderMiddleware extends render_middleware_1.RenderMiddlewareBase {
|
|
|
41
41
|
sitecore_jss_1.debug.editing('invalid origin host - set allowed origins in JSS_ALLOWED_ORIGINS environment variable');
|
|
42
42
|
return res
|
|
43
43
|
.status(401)
|
|
44
|
-
.send(`<html><body>Requests from origin ${(
|
|
44
|
+
.send(`<html><body>Requests from origin ${(_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin} are not allowed</body></html>`);
|
|
45
45
|
}
|
|
46
46
|
if (!method || !['GET', 'OPTIONS'].includes(method)) {
|
|
47
47
|
sitecore_jss_1.debug.editing('invalid method - sent %s expected GET,OPTIONS', method);
|
|
@@ -64,7 +64,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
64
64
|
return __awaiter(this, void 0, void 0, function* () {
|
|
65
65
|
const { pathname: incomingURL, search: incomingQS = '' } = this.normalizeUrl(req.nextUrl.clone());
|
|
66
66
|
const locale = this.getLanguage(req);
|
|
67
|
-
const normalizedPath = incomingURL.replace(/\/*$/gi, '');
|
|
67
|
+
const normalizedPath = incomingURL.replace(/\/*$/gi, '').toLowerCase();
|
|
68
68
|
const redirects = yield this.getRedirects(siteName);
|
|
69
69
|
const language = this.getLanguage(req);
|
|
70
70
|
const modifyRedirects = structuredClone(redirects);
|
|
@@ -78,7 +78,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
78
78
|
? redirect.pattern.slice(0, -1).split('?')
|
|
79
79
|
: redirect.pattern.split('?');
|
|
80
80
|
const patternQS = urlArray[1];
|
|
81
|
-
let patternPath = urlArray[0];
|
|
81
|
+
let patternPath = urlArray[0].toLowerCase();
|
|
82
82
|
// nextjs routes are case-sensitive, but locales should be compared case-insensitively
|
|
83
83
|
const patternParts = patternPath.split('/');
|
|
84
84
|
const maybeLocale = patternParts[1].toLowerCase();
|
|
@@ -102,7 +102,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
102
102
|
.replace(/\$\/gi$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
103
103
|
// Redirect pattern matches the full incoming URL with query string present
|
|
104
104
|
matchedQueryString = [
|
|
105
|
-
(0, regex_parser_1.default)(redirect.pattern).test(
|
|
105
|
+
(0, regex_parser_1.default)(redirect.pattern).test(`/${localePath}${incomingQS}`),
|
|
106
106
|
(0, regex_parser_1.default)(redirect.pattern).test(`${normalizedPath}${incomingQS}`),
|
|
107
107
|
].some(Boolean)
|
|
108
108
|
? incomingQS
|
|
@@ -149,6 +149,7 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
149
149
|
if (this.isPrefetch(req)) {
|
|
150
150
|
sitecore_jss_1.debug.redirects('skipped (prefetch)');
|
|
151
151
|
response.headers.set('x-middleware-cache', 'no-cache');
|
|
152
|
+
response.headers.set('Cache-Control', 'no-store, must-revalidate');
|
|
152
153
|
return response;
|
|
153
154
|
}
|
|
154
155
|
site = this.getSite(req, res);
|
|
@@ -9,7 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.BaseGraphQLSitemapService = exports.
|
|
12
|
+
exports.BaseGraphQLSitemapService = exports.siteError = exports.languageError = void 0;
|
|
13
|
+
exports.getSiteEmptyError = getSiteEmptyError;
|
|
13
14
|
const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
|
|
14
15
|
const personalize_1 = require("@sitecore-jss/sitecore-jss/personalize");
|
|
15
16
|
/** @private */
|
|
@@ -22,7 +23,6 @@ exports.siteError = 'The service needs a site name';
|
|
|
22
23
|
function getSiteEmptyError(siteName) {
|
|
23
24
|
return `Site "${siteName}" does not exist or site item tree is missing`;
|
|
24
25
|
}
|
|
25
|
-
exports.getSiteEmptyError = getSiteEmptyError;
|
|
26
26
|
const languageEmptyError = 'The language must be a non-empty string';
|
|
27
27
|
/**
|
|
28
28
|
* GQL query made dynamic based on schema differences between SXP and XM Cloud
|
|
@@ -54,6 +54,9 @@ query ${usesPersonalize ? 'PersonalizeSitemapQuery' : 'DefaultSitemapQuery'}(
|
|
|
54
54
|
}
|
|
55
55
|
results {
|
|
56
56
|
path: routePath
|
|
57
|
+
route {
|
|
58
|
+
displayName
|
|
59
|
+
}
|
|
57
60
|
${usesPersonalize
|
|
58
61
|
? `
|
|
59
62
|
route {
|
|
@@ -80,8 +83,10 @@ class BaseGraphQLSitemapService {
|
|
|
80
83
|
* @param {GraphQLSitemapServiceConfig} options instance
|
|
81
84
|
*/
|
|
82
85
|
constructor(options) {
|
|
86
|
+
var _a;
|
|
83
87
|
this.options = options;
|
|
84
88
|
this._graphQLClient = this.getGraphQLClient();
|
|
89
|
+
this._enableDisplayNameRouting = (_a = options.enableDisplayNameRouting) !== null && _a !== void 0 ? _a : false;
|
|
85
90
|
}
|
|
86
91
|
/**
|
|
87
92
|
* GraphQL client accessible by descendant classes when needed
|
|
@@ -145,19 +150,90 @@ class BaseGraphQLSitemapService {
|
|
|
145
150
|
}
|
|
146
151
|
transformLanguageSitePaths(sitePaths, formatStaticPath, language) {
|
|
147
152
|
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
-
|
|
153
|
+
var _a, _b, _c, _d;
|
|
149
154
|
const aggregatedPaths = [];
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
)
|
|
155
|
+
/**
|
|
156
|
+
* Build a map of the last segment of each path to its encoded display name.
|
|
157
|
+
* This is used later to substitute the final segment with a display name if available.
|
|
158
|
+
*/
|
|
159
|
+
const displayNameMap = new Map();
|
|
160
|
+
if (this._enableDisplayNameRouting) {
|
|
161
|
+
for (const item of sitePaths) {
|
|
162
|
+
if (!item || typeof item.path !== 'string')
|
|
163
|
+
continue;
|
|
164
|
+
const segments = item.path.replace(/^\/|\/$/g, '').split('/');
|
|
165
|
+
const lastSegment = segments[segments.length - 1];
|
|
166
|
+
const displayName = (_a = item.route) === null || _a === void 0 ? void 0 : _a.displayName;
|
|
167
|
+
if (displayName) {
|
|
168
|
+
displayNameMap.set(lastSegment, encodeURIComponent(displayName));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Recursively generate all path combinations using either:
|
|
174
|
+
* - The item name segment (default)
|
|
175
|
+
* - Or the display name (if available in the map)
|
|
176
|
+
*
|
|
177
|
+
* For example: if path is ['about', 'team'] and displayName for 'team' is 'Team-Page',
|
|
178
|
+
* it will generate:
|
|
179
|
+
* - ['about', 'team']
|
|
180
|
+
* - ['about', 'Team-Page']
|
|
181
|
+
* @param {string[]} segments
|
|
182
|
+
*/
|
|
183
|
+
const generateCombinations = (segments) => {
|
|
184
|
+
if (!this._enableDisplayNameRouting) {
|
|
185
|
+
return [segments];
|
|
186
|
+
}
|
|
187
|
+
const results = [];
|
|
188
|
+
const helper = (index, current) => {
|
|
189
|
+
if (index === segments.length) {
|
|
190
|
+
results.push([...current]);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const segment = segments[index];
|
|
194
|
+
const display = displayNameMap.get(segment);
|
|
195
|
+
// Item name segment
|
|
196
|
+
current.push(segment);
|
|
197
|
+
helper(index + 1, current);
|
|
198
|
+
current.pop();
|
|
199
|
+
// Display name segment (if available and different)
|
|
200
|
+
if (display && display !== segment) {
|
|
201
|
+
current.push(display);
|
|
202
|
+
helper(index + 1, current);
|
|
203
|
+
current.pop();
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
helper(0, []);
|
|
207
|
+
return results;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Process each route in the result set to:
|
|
211
|
+
* - Add itemName-based and displayName-based paths
|
|
212
|
+
* - Add personalized variants (if applicable) for each of those paths
|
|
213
|
+
*/
|
|
214
|
+
for (const item of sitePaths) {
|
|
215
|
+
if (!item || typeof item.path !== 'string')
|
|
216
|
+
continue;
|
|
217
|
+
const itemPath = item.path.replace(/^\/|\/$/g, '');
|
|
218
|
+
const segments = itemPath ? itemPath.split('/') : [];
|
|
219
|
+
// Generate all display/item name path combinations
|
|
220
|
+
const allCombinations = generateCombinations(segments);
|
|
221
|
+
// Add plain paths to the aggregated paths list
|
|
222
|
+
for (const combo of allCombinations) {
|
|
223
|
+
aggregatedPaths.push(formatStaticPath(combo, language));
|
|
224
|
+
}
|
|
225
|
+
// Check for personalization variants
|
|
226
|
+
const variantIds = (_d = (_c = (_b = item.route) === null || _b === void 0 ? void 0 : _b.personalization) === null || _c === void 0 ? void 0 : _c.variantIds) === null || _d === void 0 ? void 0 : _d.filter((variantId) => !variantId.includes('_'));
|
|
157
227
|
if (variantIds === null || variantIds === void 0 ? void 0 : variantIds.length) {
|
|
158
|
-
|
|
228
|
+
for (const variantId of variantIds) {
|
|
229
|
+
for (const combo of allCombinations) {
|
|
230
|
+
const rewritePath = (0, personalize_1.getPersonalizedRewrite)('/' + combo.join('/'), [variantId]);
|
|
231
|
+
const variantSegments = rewritePath.replace(/^\/|\/$/g, '').split('/');
|
|
232
|
+
aggregatedPaths.push(formatStaticPath(variantSegments, language));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
159
235
|
}
|
|
160
|
-
}
|
|
236
|
+
}
|
|
161
237
|
return aggregatedPaths;
|
|
162
238
|
});
|
|
163
239
|
}
|
|
@@ -9,7 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.GraphQLSitemapService = exports.
|
|
12
|
+
exports.GraphQLSitemapService = exports.siteError = exports.languageError = void 0;
|
|
13
|
+
exports.getSiteEmptyError = getSiteEmptyError;
|
|
13
14
|
const base_graphql_sitemap_service_1 = require("./base-graphql-sitemap-service");
|
|
14
15
|
/** @private */
|
|
15
16
|
exports.languageError = 'The list of languages cannot be empty';
|
|
@@ -21,7 +22,6 @@ exports.siteError = 'The service needs a site name';
|
|
|
21
22
|
function getSiteEmptyError(siteName) {
|
|
22
23
|
return `Site "${siteName}" does not exist or site item tree is missing`;
|
|
23
24
|
}
|
|
24
|
-
exports.getSiteEmptyError = getSiteEmptyError;
|
|
25
25
|
/**
|
|
26
26
|
* Service that fetches the list of site pages using Sitecore's GraphQL API.
|
|
27
27
|
* Used to handle a single site
|
|
@@ -279,9 +279,10 @@ export class MetadataHandler {
|
|
|
279
279
|
});
|
|
280
280
|
res.setHeader('Set-Cookie', modifiedCookies);
|
|
281
281
|
}
|
|
282
|
+
const encodedRoute = encodeURI(query.route);
|
|
282
283
|
const route = ((_c = (_b = this.config).resolvePageUrl) === null || _c === void 0 ? void 0 : _c.call(_b, {
|
|
283
|
-
itemPath:
|
|
284
|
-
})) ||
|
|
284
|
+
itemPath: encodedRoute,
|
|
285
|
+
})) || encodedRoute;
|
|
285
286
|
debug.editing('editing render middleware end in %dms: redirect %o', Date.now() - startTimestamp, {
|
|
286
287
|
status: 307,
|
|
287
288
|
route,
|
|
@@ -26,7 +26,7 @@ export class FEAASRenderMiddleware extends RenderMiddlewareBase {
|
|
|
26
26
|
this.config = config;
|
|
27
27
|
this.defaultPageUrl = '/feaas/render';
|
|
28
28
|
this.handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
29
|
-
var
|
|
29
|
+
var _a;
|
|
30
30
|
const { method, query, headers } = req;
|
|
31
31
|
const startTimestamp = Date.now();
|
|
32
32
|
debug.editing('feaas render middleware start: %o', {
|
|
@@ -38,7 +38,7 @@ export class FEAASRenderMiddleware extends RenderMiddlewareBase {
|
|
|
38
38
|
debug.editing('invalid origin host - set allowed origins in JSS_ALLOWED_ORIGINS environment variable');
|
|
39
39
|
return res
|
|
40
40
|
.status(401)
|
|
41
|
-
.send(`<html><body>Requests from origin ${(
|
|
41
|
+
.send(`<html><body>Requests from origin ${(_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin} are not allowed</body></html>`);
|
|
42
42
|
}
|
|
43
43
|
if (!method || !['GET', 'OPTIONS'].includes(method)) {
|
|
44
44
|
debug.editing('invalid method - sent %s expected GET,OPTIONS', method);
|
|
@@ -58,7 +58,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
58
58
|
return __awaiter(this, void 0, void 0, function* () {
|
|
59
59
|
const { pathname: incomingURL, search: incomingQS = '' } = this.normalizeUrl(req.nextUrl.clone());
|
|
60
60
|
const locale = this.getLanguage(req);
|
|
61
|
-
const normalizedPath = incomingURL.replace(/\/*$/gi, '');
|
|
61
|
+
const normalizedPath = incomingURL.replace(/\/*$/gi, '').toLowerCase();
|
|
62
62
|
const redirects = yield this.getRedirects(siteName);
|
|
63
63
|
const language = this.getLanguage(req);
|
|
64
64
|
const modifyRedirects = structuredClone(redirects);
|
|
@@ -72,7 +72,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
72
72
|
? redirect.pattern.slice(0, -1).split('?')
|
|
73
73
|
: redirect.pattern.split('?');
|
|
74
74
|
const patternQS = urlArray[1];
|
|
75
|
-
let patternPath = urlArray[0];
|
|
75
|
+
let patternPath = urlArray[0].toLowerCase();
|
|
76
76
|
// nextjs routes are case-sensitive, but locales should be compared case-insensitively
|
|
77
77
|
const patternParts = patternPath.split('/');
|
|
78
78
|
const maybeLocale = patternParts[1].toLowerCase();
|
|
@@ -96,7 +96,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
96
96
|
.replace(/\$\/gi$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
97
97
|
// Redirect pattern matches the full incoming URL with query string present
|
|
98
98
|
matchedQueryString = [
|
|
99
|
-
regexParser(redirect.pattern).test(
|
|
99
|
+
regexParser(redirect.pattern).test(`/${localePath}${incomingQS}`),
|
|
100
100
|
regexParser(redirect.pattern).test(`${normalizedPath}${incomingQS}`),
|
|
101
101
|
].some(Boolean)
|
|
102
102
|
? incomingQS
|
|
@@ -143,6 +143,7 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
143
143
|
if (this.isPrefetch(req)) {
|
|
144
144
|
debug.redirects('skipped (prefetch)');
|
|
145
145
|
response.headers.set('x-middleware-cache', 'no-cache');
|
|
146
|
+
response.headers.set('Cache-Control', 'no-store, must-revalidate');
|
|
146
147
|
return response;
|
|
147
148
|
}
|
|
148
149
|
site = this.getSite(req, res);
|
|
@@ -50,6 +50,9 @@ query ${usesPersonalize ? 'PersonalizeSitemapQuery' : 'DefaultSitemapQuery'}(
|
|
|
50
50
|
}
|
|
51
51
|
results {
|
|
52
52
|
path: routePath
|
|
53
|
+
route {
|
|
54
|
+
displayName
|
|
55
|
+
}
|
|
53
56
|
${usesPersonalize
|
|
54
57
|
? `
|
|
55
58
|
route {
|
|
@@ -76,8 +79,10 @@ export class BaseGraphQLSitemapService {
|
|
|
76
79
|
* @param {GraphQLSitemapServiceConfig} options instance
|
|
77
80
|
*/
|
|
78
81
|
constructor(options) {
|
|
82
|
+
var _a;
|
|
79
83
|
this.options = options;
|
|
80
84
|
this._graphQLClient = this.getGraphQLClient();
|
|
85
|
+
this._enableDisplayNameRouting = (_a = options.enableDisplayNameRouting) !== null && _a !== void 0 ? _a : false;
|
|
81
86
|
}
|
|
82
87
|
/**
|
|
83
88
|
* GraphQL client accessible by descendant classes when needed
|
|
@@ -141,19 +146,90 @@ export class BaseGraphQLSitemapService {
|
|
|
141
146
|
}
|
|
142
147
|
transformLanguageSitePaths(sitePaths, formatStaticPath, language) {
|
|
143
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
-
|
|
149
|
+
var _a, _b, _c, _d;
|
|
145
150
|
const aggregatedPaths = [];
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
151
|
+
/**
|
|
152
|
+
* Build a map of the last segment of each path to its encoded display name.
|
|
153
|
+
* This is used later to substitute the final segment with a display name if available.
|
|
154
|
+
*/
|
|
155
|
+
const displayNameMap = new Map();
|
|
156
|
+
if (this._enableDisplayNameRouting) {
|
|
157
|
+
for (const item of sitePaths) {
|
|
158
|
+
if (!item || typeof item.path !== 'string')
|
|
159
|
+
continue;
|
|
160
|
+
const segments = item.path.replace(/^\/|\/$/g, '').split('/');
|
|
161
|
+
const lastSegment = segments[segments.length - 1];
|
|
162
|
+
const displayName = (_a = item.route) === null || _a === void 0 ? void 0 : _a.displayName;
|
|
163
|
+
if (displayName) {
|
|
164
|
+
displayNameMap.set(lastSegment, encodeURIComponent(displayName));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Recursively generate all path combinations using either:
|
|
170
|
+
* - The item name segment (default)
|
|
171
|
+
* - Or the display name (if available in the map)
|
|
172
|
+
*
|
|
173
|
+
* For example: if path is ['about', 'team'] and displayName for 'team' is 'Team-Page',
|
|
174
|
+
* it will generate:
|
|
175
|
+
* - ['about', 'team']
|
|
176
|
+
* - ['about', 'Team-Page']
|
|
177
|
+
* @param {string[]} segments
|
|
178
|
+
*/
|
|
179
|
+
const generateCombinations = (segments) => {
|
|
180
|
+
if (!this._enableDisplayNameRouting) {
|
|
181
|
+
return [segments];
|
|
182
|
+
}
|
|
183
|
+
const results = [];
|
|
184
|
+
const helper = (index, current) => {
|
|
185
|
+
if (index === segments.length) {
|
|
186
|
+
results.push([...current]);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const segment = segments[index];
|
|
190
|
+
const display = displayNameMap.get(segment);
|
|
191
|
+
// Item name segment
|
|
192
|
+
current.push(segment);
|
|
193
|
+
helper(index + 1, current);
|
|
194
|
+
current.pop();
|
|
195
|
+
// Display name segment (if available and different)
|
|
196
|
+
if (display && display !== segment) {
|
|
197
|
+
current.push(display);
|
|
198
|
+
helper(index + 1, current);
|
|
199
|
+
current.pop();
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
helper(0, []);
|
|
203
|
+
return results;
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Process each route in the result set to:
|
|
207
|
+
* - Add itemName-based and displayName-based paths
|
|
208
|
+
* - Add personalized variants (if applicable) for each of those paths
|
|
209
|
+
*/
|
|
210
|
+
for (const item of sitePaths) {
|
|
211
|
+
if (!item || typeof item.path !== 'string')
|
|
212
|
+
continue;
|
|
213
|
+
const itemPath = item.path.replace(/^\/|\/$/g, '');
|
|
214
|
+
const segments = itemPath ? itemPath.split('/') : [];
|
|
215
|
+
// Generate all display/item name path combinations
|
|
216
|
+
const allCombinations = generateCombinations(segments);
|
|
217
|
+
// Add plain paths to the aggregated paths list
|
|
218
|
+
for (const combo of allCombinations) {
|
|
219
|
+
aggregatedPaths.push(formatStaticPath(combo, language));
|
|
220
|
+
}
|
|
221
|
+
// Check for personalization variants
|
|
222
|
+
const variantIds = (_d = (_c = (_b = item.route) === null || _b === void 0 ? void 0 : _b.personalization) === null || _c === void 0 ? void 0 : _c.variantIds) === null || _d === void 0 ? void 0 : _d.filter((variantId) => !variantId.includes('_'));
|
|
153
223
|
if (variantIds === null || variantIds === void 0 ? void 0 : variantIds.length) {
|
|
154
|
-
|
|
224
|
+
for (const variantId of variantIds) {
|
|
225
|
+
for (const combo of allCombinations) {
|
|
226
|
+
const rewritePath = getPersonalizedRewrite('/' + combo.join('/'), [variantId]);
|
|
227
|
+
const variantSegments = rewritePath.replace(/^\/|\/$/g, '').split('/');
|
|
228
|
+
aggregatedPaths.push(formatStaticPath(variantSegments, language));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
155
231
|
}
|
|
156
|
-
}
|
|
232
|
+
}
|
|
157
233
|
return aggregatedPaths;
|
|
158
234
|
});
|
|
159
235
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitecore-jss/sitecore-jss-nextjs",
|
|
3
|
-
"version": "22.9.0-canary.
|
|
3
|
+
"version": "22.9.0-canary.11",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -32,56 +32,56 @@
|
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@sitecore-cloudsdk/core": "^0.5.1",
|
|
34
34
|
"@sitecore-cloudsdk/personalize": "^0.5.1",
|
|
35
|
-
"@testing-library/dom": "^10.4.
|
|
35
|
+
"@testing-library/dom": "^10.4.1",
|
|
36
36
|
"@testing-library/react": "^16.3.0",
|
|
37
|
-
"@types/chai": "^
|
|
38
|
-
"@types/chai-as-promised": "^
|
|
39
|
-
"@types/chai-string": "^1.4.
|
|
40
|
-
"@types/mocha": "^10.0.
|
|
37
|
+
"@types/chai": "^5.2.2",
|
|
38
|
+
"@types/chai-as-promised": "^8.0.2",
|
|
39
|
+
"@types/chai-string": "^1.4.5",
|
|
40
|
+
"@types/mocha": "^10.0.10",
|
|
41
41
|
"@types/node": "~22.9.0",
|
|
42
|
-
"@types/react": "^19.1.
|
|
43
|
-
"@types/react-dom": "^19.1.
|
|
44
|
-
"@types/sinon": "^
|
|
45
|
-
"@types/sinon-chai": "^
|
|
42
|
+
"@types/react": "^19.1.7",
|
|
43
|
+
"@types/react-dom": "^19.1.7",
|
|
44
|
+
"@types/sinon": "^17.0.4",
|
|
45
|
+
"@types/sinon-chai": "^4.0.0",
|
|
46
46
|
"chai": "^4.3.7",
|
|
47
47
|
"chai-as-promised": "^7.1.1",
|
|
48
|
-
"chai-string": "^1.
|
|
48
|
+
"chai-string": "^1.6.0",
|
|
49
49
|
"chalk": "^4.1.2",
|
|
50
50
|
"cross-fetch": "^3.1.5",
|
|
51
51
|
"del-cli": "^5.0.0",
|
|
52
52
|
"eslint": "^8.56.0",
|
|
53
53
|
"eslint-plugin-react": "^7.37.5",
|
|
54
|
-
"jsdom": "^
|
|
55
|
-
"mocha": "^
|
|
56
|
-
"next": "^15.
|
|
54
|
+
"jsdom": "^26.1.0",
|
|
55
|
+
"mocha": "^11.7.0",
|
|
56
|
+
"next": "^15.4.6",
|
|
57
57
|
"nock": "^13.3.0",
|
|
58
|
-
"nyc": "^
|
|
58
|
+
"nyc": "^17.1.0",
|
|
59
59
|
"react": "^19.1.0",
|
|
60
60
|
"react-dom": "^19.1.0",
|
|
61
|
-
"sinon": "^
|
|
61
|
+
"sinon": "^20.0.0",
|
|
62
62
|
"sinon-chai": "^3.7.0",
|
|
63
63
|
"ts-node": "^10.9.1",
|
|
64
|
-
"typescript": "~5.
|
|
64
|
+
"typescript": "~5.6.3"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@sitecore-cloudsdk/core": "^0.5.
|
|
68
|
-
"@sitecore-cloudsdk/events": "^0.5.
|
|
69
|
-
"@sitecore-cloudsdk/personalize": "^0.5.
|
|
70
|
-
"next": "^15.
|
|
67
|
+
"@sitecore-cloudsdk/core": "^0.5.2",
|
|
68
|
+
"@sitecore-cloudsdk/events": "^0.5.2",
|
|
69
|
+
"@sitecore-cloudsdk/personalize": "^0.5.2",
|
|
70
|
+
"next": "^15.4.6",
|
|
71
71
|
"react": "^19.1.0",
|
|
72
72
|
"react-dom": "^19.1.0"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@sitecore-jss/sitecore-jss": "22.9.0-canary.
|
|
76
|
-
"@sitecore-jss/sitecore-jss-dev-tools": "22.9.0-canary.
|
|
77
|
-
"@sitecore-jss/sitecore-jss-react": "22.9.0-canary.
|
|
75
|
+
"@sitecore-jss/sitecore-jss": "22.9.0-canary.11",
|
|
76
|
+
"@sitecore-jss/sitecore-jss-dev-tools": "22.9.0-canary.11",
|
|
77
|
+
"@sitecore-jss/sitecore-jss-react": "22.9.0-canary.11",
|
|
78
78
|
"@vercel/kv": "^0.2.1",
|
|
79
79
|
"regex-parser": "^2.2.11",
|
|
80
80
|
"sync-disk-cache": "^2.1.0"
|
|
81
81
|
},
|
|
82
82
|
"description": "",
|
|
83
83
|
"types": "types/index.d.ts",
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "04c65d604d67da8021bcede2c38e884556deda56",
|
|
85
85
|
"files": [
|
|
86
86
|
"dist",
|
|
87
87
|
"types",
|
|
@@ -64,12 +64,12 @@ export type EditingRenderMiddlewareChromesConfig = EditingRenderMiddlewareConfig
|
|
|
64
64
|
* This handler is responsible for rendering the page and returning the HTML content that is provided via request.
|
|
65
65
|
*/
|
|
66
66
|
export declare class ChromesHandler extends RenderMiddlewareBase {
|
|
67
|
-
config?:
|
|
67
|
+
config?: EditingRenderMiddlewareChromesConfig | undefined;
|
|
68
68
|
private editingDataService;
|
|
69
69
|
private dataFetcher;
|
|
70
70
|
private resolvePageUrl;
|
|
71
71
|
private resolveServerUrl;
|
|
72
|
-
constructor(config?:
|
|
72
|
+
constructor(config?: EditingRenderMiddlewareChromesConfig | undefined);
|
|
73
73
|
render(req: NextApiRequest, res: NextApiResponse): Promise<void>;
|
|
74
74
|
/**
|
|
75
75
|
* Default page URL resolution.
|
|
@@ -58,6 +58,7 @@ export interface SiteRouteQueryResult<T> {
|
|
|
58
58
|
export type RouteListQueryResult = {
|
|
59
59
|
path: string;
|
|
60
60
|
route?: {
|
|
61
|
+
displayName: string;
|
|
61
62
|
personalization?: {
|
|
62
63
|
variantIds: string[];
|
|
63
64
|
};
|
|
@@ -73,6 +74,10 @@ export interface BaseGraphQLSitemapServiceConfig extends Omit<SiteRouteQueryVari
|
|
|
73
74
|
* Turned off by default.
|
|
74
75
|
*/
|
|
75
76
|
includePersonalizedRoutes?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Gets a flag indicating whether display name routing is enabled.
|
|
79
|
+
*/
|
|
80
|
+
enableDisplayNameRouting?: boolean;
|
|
76
81
|
/**
|
|
77
82
|
* A GraphQL Request Client Factory is a function that accepts configuration and returns an instance of a GraphQLRequestClient.
|
|
78
83
|
* This factory function is used to create and configure GraphQL clients for making GraphQL API requests.
|
|
@@ -97,6 +102,7 @@ export type StaticPath = {
|
|
|
97
102
|
export declare abstract class BaseGraphQLSitemapService {
|
|
98
103
|
options: BaseGraphQLSitemapServiceConfig;
|
|
99
104
|
private _graphQLClient;
|
|
105
|
+
private _enableDisplayNameRouting;
|
|
100
106
|
/**
|
|
101
107
|
* Creates an instance of graphQL sitemap service with the provided options
|
|
102
108
|
* @param {GraphQLSitemapServiceConfig} options instance
|