@sitecore-jss/sitecore-jss-nextjs 22.6.0-canary.1 → 22.6.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/Link.js +3 -2
- package/dist/cjs/middleware/redirects-middleware.js +78 -71
- package/dist/esm/components/Link.js +3 -2
- package/dist/esm/middleware/redirects-middleware.js +78 -71
- package/package.json +5 -5
- package/types/components/Link.d.ts +5 -0
- package/types/middleware/redirects-middleware.d.ts +14 -5
|
@@ -67,14 +67,15 @@ exports.Link = (0, react_1.forwardRef)((props, ref) => {
|
|
|
67
67
|
const isFileUrl = FILE_EXTENSION_MATCHER.test(href);
|
|
68
68
|
// determine if a link is a route or not. File extensions are not routes and should not be pre-fetched.
|
|
69
69
|
if (isMatching && !isFileUrl) {
|
|
70
|
-
return (react_1.default.createElement(link_1.default, Object.assign({ href: { pathname: href, query: querystring, hash: anchor }, key: "link", locale: false, title: value.title, target: value.target, className: value.class }, htmlLinkProps, { ref: ref }),
|
|
70
|
+
return (react_1.default.createElement(link_1.default, Object.assign({ href: { pathname: href, query: querystring, hash: anchor }, key: "link", locale: false, title: value.title, target: value.target, className: value.class, prefetch: props.prefetch }, htmlLinkProps, { ref: ref }),
|
|
71
71
|
text,
|
|
72
72
|
children));
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
// prevent passing internalLinkMatcher as it is an invalid DOM element prop
|
|
75
|
+
// prevent passing internalLinkMatcher or prefetch as it is an invalid DOM element prop
|
|
76
76
|
const reactLinkProps = Object.assign({}, props);
|
|
77
77
|
delete reactLinkProps.internalLinkMatcher;
|
|
78
|
+
delete reactLinkProps.prefetch;
|
|
78
79
|
return react_1.default.createElement(sitecore_jss_react_1.Link, Object.assign({}, reactLinkProps, { ref: ref }));
|
|
79
80
|
});
|
|
80
81
|
exports.Link.displayName = 'NextLink';
|
|
@@ -32,7 +32,84 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
32
32
|
constructor(config) {
|
|
33
33
|
super(config);
|
|
34
34
|
this.config = config;
|
|
35
|
-
|
|
35
|
+
// NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
|
|
36
|
+
// (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
|
|
37
|
+
this.redirectsService = new site_1.GraphQLRedirectsService(Object.assign(Object.assign({}, config), { fetch: fetch }));
|
|
38
|
+
this.locales = config.locales;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Gets the Next.js middleware handler with error handling
|
|
42
|
+
* @returns route handler
|
|
43
|
+
*/
|
|
44
|
+
getHandler() {
|
|
45
|
+
return (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
try {
|
|
47
|
+
return this.processRedirectRequest(req, res);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.log('Redirect middleware failed:');
|
|
51
|
+
console.log(error);
|
|
52
|
+
return res || server_1.NextResponse.next();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Method returns RedirectInfo when matches
|
|
58
|
+
* @param {NextRequest} req request
|
|
59
|
+
* @param {string} siteName site name
|
|
60
|
+
* @returns Promise<RedirectInfo | undefined> The redirect info or undefined if no redirect is found
|
|
61
|
+
* @protected
|
|
62
|
+
*/
|
|
63
|
+
getExistsRedirect(req, siteName) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
const { pathname: targetURL, search: targetQS = '', locale } = this.normalizeUrl(req.nextUrl.clone());
|
|
66
|
+
const normalizedPath = targetURL.replace(/\/*$/gi, '');
|
|
67
|
+
const redirects = yield this.redirectsService.fetchRedirects(siteName);
|
|
68
|
+
const language = this.getLanguage(req);
|
|
69
|
+
const modifyRedirects = structuredClone(redirects);
|
|
70
|
+
let matchedQueryString;
|
|
71
|
+
return modifyRedirects.length
|
|
72
|
+
? modifyRedirects.find((redirect) => {
|
|
73
|
+
var _a;
|
|
74
|
+
if ((0, utils_1.isRegexOrUrl)(redirect.pattern) === 'url') {
|
|
75
|
+
const parseUrlPattern = redirect.pattern.endsWith('/')
|
|
76
|
+
? redirect.pattern.slice(0, -1).split('?')
|
|
77
|
+
: redirect.pattern.split('?');
|
|
78
|
+
return ((parseUrlPattern[0] === normalizedPath ||
|
|
79
|
+
parseUrlPattern[0] === `/${locale}${normalizedPath}`) &&
|
|
80
|
+
(0, utils_1.areURLSearchParamsEqual)(new URLSearchParams((_a = parseUrlPattern[1]) !== null && _a !== void 0 ? _a : ''), new URLSearchParams(targetQS)));
|
|
81
|
+
}
|
|
82
|
+
// Modify the redirect pattern to ignore the language prefix in the path
|
|
83
|
+
// And escapes non-special "?" characters in a string or regex.
|
|
84
|
+
redirect.pattern = (0, utils_1.escapeNonSpecialQuestionMarks)(redirect.pattern.replace(new RegExp(`^[^]?/${language}/`, 'gi'), ''));
|
|
85
|
+
// Prepare the redirect pattern as a regular expression, making it more flexible for matching URLs
|
|
86
|
+
redirect.pattern = `/^\/${redirect.pattern
|
|
87
|
+
.replace(/^\/|\/$/g, '') // Removes leading and trailing slashes
|
|
88
|
+
.replace(/^\^\/|\/\$$/g, '') // Removes unnecessary start (^) and end ($) anchors
|
|
89
|
+
.replace(/^\^|\$$/g, '') // Further cleans up anchors
|
|
90
|
+
.replace(/\$\/gi$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
91
|
+
matchedQueryString = [
|
|
92
|
+
(0, regex_parser_1.default)(redirect.pattern).test(`${normalizedPath}${targetQS}`),
|
|
93
|
+
(0, regex_parser_1.default)(redirect.pattern).test(`/${locale}${normalizedPath}${targetQS}`),
|
|
94
|
+
].some(Boolean)
|
|
95
|
+
? targetQS
|
|
96
|
+
: undefined;
|
|
97
|
+
// Save the matched query string (if found) into the redirect object
|
|
98
|
+
redirect.matchedQueryString = matchedQueryString || '';
|
|
99
|
+
return (!!((0, regex_parser_1.default)(redirect.pattern).test(targetURL) ||
|
|
100
|
+
(0, regex_parser_1.default)(redirect.pattern).test(`/${req.nextUrl.locale}${targetURL}`) ||
|
|
101
|
+
matchedQueryString) && (redirect.locale ? redirect.locale.toLowerCase() === locale.toLowerCase() : true));
|
|
102
|
+
})
|
|
103
|
+
: undefined;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* @param {NextRequest} req request
|
|
108
|
+
* @param {Response} res response
|
|
109
|
+
* @returns {Promise<NextResponse>} The redirect response.
|
|
110
|
+
*/
|
|
111
|
+
processRedirectRequest(req, res) {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
113
|
const pathname = req.nextUrl.pathname;
|
|
37
114
|
const language = this.getLanguage(req);
|
|
38
115
|
const hostname = this.getHostHeader(req) || this.defaultHostname;
|
|
@@ -129,76 +206,6 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
|
|
|
129
206
|
});
|
|
130
207
|
return response;
|
|
131
208
|
});
|
|
132
|
-
// NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
|
|
133
|
-
// (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
|
|
134
|
-
this.redirectsService = new site_1.GraphQLRedirectsService(Object.assign(Object.assign({}, config), { fetch: fetch }));
|
|
135
|
-
this.locales = config.locales;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Gets the Next.js middleware handler with error handling
|
|
139
|
-
* @returns route handler
|
|
140
|
-
*/
|
|
141
|
-
getHandler() {
|
|
142
|
-
return (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
143
|
-
try {
|
|
144
|
-
return yield this.handler(req, res);
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
console.log('Redirect middleware failed:');
|
|
148
|
-
console.log(error);
|
|
149
|
-
return res || server_1.NextResponse.next();
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Method returns RedirectInfo when matches
|
|
155
|
-
* @param {NextRequest} req request
|
|
156
|
-
* @param {string} siteName site name
|
|
157
|
-
* @returns Promise<RedirectInfo | undefined>
|
|
158
|
-
* @private
|
|
159
|
-
*/
|
|
160
|
-
getExistsRedirect(req, siteName) {
|
|
161
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
162
|
-
const { pathname: targetURL, search: targetQS = '', locale } = this.normalizeUrl(req.nextUrl.clone());
|
|
163
|
-
const normalizedPath = targetURL.replace(/\/*$/gi, '');
|
|
164
|
-
const redirects = yield this.redirectsService.fetchRedirects(siteName);
|
|
165
|
-
const language = this.getLanguage(req);
|
|
166
|
-
const modifyRedirects = structuredClone(redirects);
|
|
167
|
-
let matchedQueryString;
|
|
168
|
-
return modifyRedirects.length
|
|
169
|
-
? modifyRedirects.find((redirect) => {
|
|
170
|
-
var _a;
|
|
171
|
-
if ((0, utils_1.isRegexOrUrl)(redirect.pattern) === 'url') {
|
|
172
|
-
const parseUrlPattern = redirect.pattern.endsWith('/')
|
|
173
|
-
? redirect.pattern.slice(0, -1).split('?')
|
|
174
|
-
: redirect.pattern.split('?');
|
|
175
|
-
return ((parseUrlPattern[0] === normalizedPath ||
|
|
176
|
-
parseUrlPattern[0] === `/${locale}${normalizedPath}`) &&
|
|
177
|
-
(0, utils_1.areURLSearchParamsEqual)(new URLSearchParams((_a = parseUrlPattern[1]) !== null && _a !== void 0 ? _a : ''), new URLSearchParams(targetQS)));
|
|
178
|
-
}
|
|
179
|
-
// Modify the redirect pattern to ignore the language prefix in the path
|
|
180
|
-
// And escapes non-special "?" characters in a string or regex.
|
|
181
|
-
redirect.pattern = (0, utils_1.escapeNonSpecialQuestionMarks)(redirect.pattern.replace(new RegExp(`^[^]?/${language}/`, 'gi'), ''));
|
|
182
|
-
// Prepare the redirect pattern as a regular expression, making it more flexible for matching URLs
|
|
183
|
-
redirect.pattern = `/^\/${redirect.pattern
|
|
184
|
-
.replace(/^\/|\/$/g, '') // Removes leading and trailing slashes
|
|
185
|
-
.replace(/^\^\/|\/\$$/g, '') // Removes unnecessary start (^) and end ($) anchors
|
|
186
|
-
.replace(/^\^|\$$/g, '') // Further cleans up anchors
|
|
187
|
-
.replace(/\$\/gi$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
188
|
-
matchedQueryString = [
|
|
189
|
-
(0, regex_parser_1.default)(redirect.pattern).test(`${normalizedPath}${targetQS}`),
|
|
190
|
-
(0, regex_parser_1.default)(redirect.pattern).test(`/${locale}${normalizedPath}${targetQS}`),
|
|
191
|
-
].some(Boolean)
|
|
192
|
-
? targetQS
|
|
193
|
-
: undefined;
|
|
194
|
-
// Save the matched query string (if found) into the redirect object
|
|
195
|
-
redirect.matchedQueryString = matchedQueryString || '';
|
|
196
|
-
return (!!((0, regex_parser_1.default)(redirect.pattern).test(targetURL) ||
|
|
197
|
-
(0, regex_parser_1.default)(redirect.pattern).test(`/${req.nextUrl.locale}${targetURL}`) ||
|
|
198
|
-
matchedQueryString) && (redirect.locale ? redirect.locale.toLowerCase() === locale.toLowerCase() : true));
|
|
199
|
-
})
|
|
200
|
-
: undefined;
|
|
201
|
-
});
|
|
202
209
|
}
|
|
203
210
|
/**
|
|
204
211
|
* When a user clicks on a link generated by the Link component from next/link,
|
|
@@ -38,14 +38,15 @@ export const Link = forwardRef((props, ref) => {
|
|
|
38
38
|
const isFileUrl = FILE_EXTENSION_MATCHER.test(href);
|
|
39
39
|
// determine if a link is a route or not. File extensions are not routes and should not be pre-fetched.
|
|
40
40
|
if (isMatching && !isFileUrl) {
|
|
41
|
-
return (React.createElement(NextLink, Object.assign({ href: { pathname: href, query: querystring, hash: anchor }, key: "link", locale: false, title: value.title, target: value.target, className: value.class }, htmlLinkProps, { ref: ref }),
|
|
41
|
+
return (React.createElement(NextLink, Object.assign({ href: { pathname: href, query: querystring, hash: anchor }, key: "link", locale: false, title: value.title, target: value.target, className: value.class, prefetch: props.prefetch }, htmlLinkProps, { ref: ref }),
|
|
42
42
|
text,
|
|
43
43
|
children));
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
// prevent passing internalLinkMatcher as it is an invalid DOM element prop
|
|
46
|
+
// prevent passing internalLinkMatcher or prefetch as it is an invalid DOM element prop
|
|
47
47
|
const reactLinkProps = Object.assign({}, props);
|
|
48
48
|
delete reactLinkProps.internalLinkMatcher;
|
|
49
|
+
delete reactLinkProps.prefetch;
|
|
49
50
|
return React.createElement(ReactLink, Object.assign({}, reactLinkProps, { ref: ref }));
|
|
50
51
|
});
|
|
51
52
|
Link.displayName = 'NextLink';
|
|
@@ -26,7 +26,84 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
26
26
|
constructor(config) {
|
|
27
27
|
super(config);
|
|
28
28
|
this.config = config;
|
|
29
|
-
|
|
29
|
+
// NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
|
|
30
|
+
// (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
|
|
31
|
+
this.redirectsService = new GraphQLRedirectsService(Object.assign(Object.assign({}, config), { fetch: fetch }));
|
|
32
|
+
this.locales = config.locales;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Gets the Next.js middleware handler with error handling
|
|
36
|
+
* @returns route handler
|
|
37
|
+
*/
|
|
38
|
+
getHandler() {
|
|
39
|
+
return (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
try {
|
|
41
|
+
return this.processRedirectRequest(req, res);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.log('Redirect middleware failed:');
|
|
45
|
+
console.log(error);
|
|
46
|
+
return res || NextResponse.next();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Method returns RedirectInfo when matches
|
|
52
|
+
* @param {NextRequest} req request
|
|
53
|
+
* @param {string} siteName site name
|
|
54
|
+
* @returns Promise<RedirectInfo | undefined> The redirect info or undefined if no redirect is found
|
|
55
|
+
* @protected
|
|
56
|
+
*/
|
|
57
|
+
getExistsRedirect(req, siteName) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const { pathname: targetURL, search: targetQS = '', locale } = this.normalizeUrl(req.nextUrl.clone());
|
|
60
|
+
const normalizedPath = targetURL.replace(/\/*$/gi, '');
|
|
61
|
+
const redirects = yield this.redirectsService.fetchRedirects(siteName);
|
|
62
|
+
const language = this.getLanguage(req);
|
|
63
|
+
const modifyRedirects = structuredClone(redirects);
|
|
64
|
+
let matchedQueryString;
|
|
65
|
+
return modifyRedirects.length
|
|
66
|
+
? modifyRedirects.find((redirect) => {
|
|
67
|
+
var _a;
|
|
68
|
+
if (isRegexOrUrl(redirect.pattern) === 'url') {
|
|
69
|
+
const parseUrlPattern = redirect.pattern.endsWith('/')
|
|
70
|
+
? redirect.pattern.slice(0, -1).split('?')
|
|
71
|
+
: redirect.pattern.split('?');
|
|
72
|
+
return ((parseUrlPattern[0] === normalizedPath ||
|
|
73
|
+
parseUrlPattern[0] === `/${locale}${normalizedPath}`) &&
|
|
74
|
+
areURLSearchParamsEqual(new URLSearchParams((_a = parseUrlPattern[1]) !== null && _a !== void 0 ? _a : ''), new URLSearchParams(targetQS)));
|
|
75
|
+
}
|
|
76
|
+
// Modify the redirect pattern to ignore the language prefix in the path
|
|
77
|
+
// And escapes non-special "?" characters in a string or regex.
|
|
78
|
+
redirect.pattern = escapeNonSpecialQuestionMarks(redirect.pattern.replace(new RegExp(`^[^]?/${language}/`, 'gi'), ''));
|
|
79
|
+
// Prepare the redirect pattern as a regular expression, making it more flexible for matching URLs
|
|
80
|
+
redirect.pattern = `/^\/${redirect.pattern
|
|
81
|
+
.replace(/^\/|\/$/g, '') // Removes leading and trailing slashes
|
|
82
|
+
.replace(/^\^\/|\/\$$/g, '') // Removes unnecessary start (^) and end ($) anchors
|
|
83
|
+
.replace(/^\^|\$$/g, '') // Further cleans up anchors
|
|
84
|
+
.replace(/\$\/gi$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
85
|
+
matchedQueryString = [
|
|
86
|
+
regexParser(redirect.pattern).test(`${normalizedPath}${targetQS}`),
|
|
87
|
+
regexParser(redirect.pattern).test(`/${locale}${normalizedPath}${targetQS}`),
|
|
88
|
+
].some(Boolean)
|
|
89
|
+
? targetQS
|
|
90
|
+
: undefined;
|
|
91
|
+
// Save the matched query string (if found) into the redirect object
|
|
92
|
+
redirect.matchedQueryString = matchedQueryString || '';
|
|
93
|
+
return (!!(regexParser(redirect.pattern).test(targetURL) ||
|
|
94
|
+
regexParser(redirect.pattern).test(`/${req.nextUrl.locale}${targetURL}`) ||
|
|
95
|
+
matchedQueryString) && (redirect.locale ? redirect.locale.toLowerCase() === locale.toLowerCase() : true));
|
|
96
|
+
})
|
|
97
|
+
: undefined;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* @param {NextRequest} req request
|
|
102
|
+
* @param {Response} res response
|
|
103
|
+
* @returns {Promise<NextResponse>} The redirect response.
|
|
104
|
+
*/
|
|
105
|
+
processRedirectRequest(req, res) {
|
|
106
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
30
107
|
const pathname = req.nextUrl.pathname;
|
|
31
108
|
const language = this.getLanguage(req);
|
|
32
109
|
const hostname = this.getHostHeader(req) || this.defaultHostname;
|
|
@@ -123,76 +200,6 @@ export class RedirectsMiddleware extends MiddlewareBase {
|
|
|
123
200
|
});
|
|
124
201
|
return response;
|
|
125
202
|
});
|
|
126
|
-
// NOTE: we provide native fetch for compatibility on Next.js Edge Runtime
|
|
127
|
-
// (underlying default 'cross-fetch' is not currently compatible: https://github.com/lquixada/cross-fetch/issues/78)
|
|
128
|
-
this.redirectsService = new GraphQLRedirectsService(Object.assign(Object.assign({}, config), { fetch: fetch }));
|
|
129
|
-
this.locales = config.locales;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Gets the Next.js middleware handler with error handling
|
|
133
|
-
* @returns route handler
|
|
134
|
-
*/
|
|
135
|
-
getHandler() {
|
|
136
|
-
return (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
137
|
-
try {
|
|
138
|
-
return yield this.handler(req, res);
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
console.log('Redirect middleware failed:');
|
|
142
|
-
console.log(error);
|
|
143
|
-
return res || NextResponse.next();
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Method returns RedirectInfo when matches
|
|
149
|
-
* @param {NextRequest} req request
|
|
150
|
-
* @param {string} siteName site name
|
|
151
|
-
* @returns Promise<RedirectInfo | undefined>
|
|
152
|
-
* @private
|
|
153
|
-
*/
|
|
154
|
-
getExistsRedirect(req, siteName) {
|
|
155
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
-
const { pathname: targetURL, search: targetQS = '', locale } = this.normalizeUrl(req.nextUrl.clone());
|
|
157
|
-
const normalizedPath = targetURL.replace(/\/*$/gi, '');
|
|
158
|
-
const redirects = yield this.redirectsService.fetchRedirects(siteName);
|
|
159
|
-
const language = this.getLanguage(req);
|
|
160
|
-
const modifyRedirects = structuredClone(redirects);
|
|
161
|
-
let matchedQueryString;
|
|
162
|
-
return modifyRedirects.length
|
|
163
|
-
? modifyRedirects.find((redirect) => {
|
|
164
|
-
var _a;
|
|
165
|
-
if (isRegexOrUrl(redirect.pattern) === 'url') {
|
|
166
|
-
const parseUrlPattern = redirect.pattern.endsWith('/')
|
|
167
|
-
? redirect.pattern.slice(0, -1).split('?')
|
|
168
|
-
: redirect.pattern.split('?');
|
|
169
|
-
return ((parseUrlPattern[0] === normalizedPath ||
|
|
170
|
-
parseUrlPattern[0] === `/${locale}${normalizedPath}`) &&
|
|
171
|
-
areURLSearchParamsEqual(new URLSearchParams((_a = parseUrlPattern[1]) !== null && _a !== void 0 ? _a : ''), new URLSearchParams(targetQS)));
|
|
172
|
-
}
|
|
173
|
-
// Modify the redirect pattern to ignore the language prefix in the path
|
|
174
|
-
// And escapes non-special "?" characters in a string or regex.
|
|
175
|
-
redirect.pattern = escapeNonSpecialQuestionMarks(redirect.pattern.replace(new RegExp(`^[^]?/${language}/`, 'gi'), ''));
|
|
176
|
-
// Prepare the redirect pattern as a regular expression, making it more flexible for matching URLs
|
|
177
|
-
redirect.pattern = `/^\/${redirect.pattern
|
|
178
|
-
.replace(/^\/|\/$/g, '') // Removes leading and trailing slashes
|
|
179
|
-
.replace(/^\^\/|\/\$$/g, '') // Removes unnecessary start (^) and end ($) anchors
|
|
180
|
-
.replace(/^\^|\$$/g, '') // Further cleans up anchors
|
|
181
|
-
.replace(/\$\/gi$/g, '')}[\/]?$/i`; // Ensures the pattern allows an optional trailing slash
|
|
182
|
-
matchedQueryString = [
|
|
183
|
-
regexParser(redirect.pattern).test(`${normalizedPath}${targetQS}`),
|
|
184
|
-
regexParser(redirect.pattern).test(`/${locale}${normalizedPath}${targetQS}`),
|
|
185
|
-
].some(Boolean)
|
|
186
|
-
? targetQS
|
|
187
|
-
: undefined;
|
|
188
|
-
// Save the matched query string (if found) into the redirect object
|
|
189
|
-
redirect.matchedQueryString = matchedQueryString || '';
|
|
190
|
-
return (!!(regexParser(redirect.pattern).test(targetURL) ||
|
|
191
|
-
regexParser(redirect.pattern).test(`/${req.nextUrl.locale}${targetURL}`) ||
|
|
192
|
-
matchedQueryString) && (redirect.locale ? redirect.locale.toLowerCase() === locale.toLowerCase() : true));
|
|
193
|
-
})
|
|
194
|
-
: undefined;
|
|
195
|
-
});
|
|
196
203
|
}
|
|
197
204
|
/**
|
|
198
205
|
* When a user clicks on a link generated by the Link component from next/link,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitecore-jss/sitecore-jss-nextjs",
|
|
3
|
-
"version": "22.6.0-canary.
|
|
3
|
+
"version": "22.6.0-canary.11",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -73,9 +73,9 @@
|
|
|
73
73
|
"react-dom": "^18.2.0"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@sitecore-jss/sitecore-jss": "
|
|
77
|
-
"@sitecore-jss/sitecore-jss-dev-tools": "
|
|
78
|
-
"@sitecore-jss/sitecore-jss-react": "
|
|
76
|
+
"@sitecore-jss/sitecore-jss": "22.6.0-canary.11",
|
|
77
|
+
"@sitecore-jss/sitecore-jss-dev-tools": "22.6.0-canary.11",
|
|
78
|
+
"@sitecore-jss/sitecore-jss-react": "22.6.0-canary.11",
|
|
79
79
|
"@vercel/kv": "^0.2.1",
|
|
80
80
|
"prop-types": "^15.8.1",
|
|
81
81
|
"regex-parser": "^2.2.11",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
},
|
|
84
84
|
"description": "",
|
|
85
85
|
"types": "types/index.d.ts",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "05def8420598c33ce7232b7440b92a17ef4f6903",
|
|
87
87
|
"files": [
|
|
88
88
|
"dist",
|
|
89
89
|
"types",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="@types/react" />
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { LinkProps as NextLinkProps } from 'next/link';
|
|
3
4
|
import { LinkProps as ReactLinkProps } from '@sitecore-jss/sitecore-jss-react';
|
|
4
5
|
export type LinkProps = ReactLinkProps & {
|
|
5
6
|
/**
|
|
@@ -7,5 +8,9 @@ export type LinkProps = ReactLinkProps & {
|
|
|
7
8
|
* @default /^\//g
|
|
8
9
|
*/
|
|
9
10
|
internalLinkMatcher?: RegExp;
|
|
11
|
+
/**
|
|
12
|
+
* Next.js Link prefetch.
|
|
13
|
+
*/
|
|
14
|
+
prefetch?: NextLinkProps['prefetch'];
|
|
10
15
|
};
|
|
11
16
|
export declare const Link: React.ForwardRefExoticComponent<Omit<LinkProps, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { GraphQLRedirectsServiceConfig } from '@sitecore-jss/sitecore-jss/site';
|
|
1
|
+
import { GraphQLRedirectsServiceConfig, RedirectInfo } from '@sitecore-jss/sitecore-jss/site';
|
|
2
2
|
import { NextRequest, NextResponse } from 'next/server';
|
|
3
3
|
import { MiddlewareBase, MiddlewareBaseConfig } from './middleware';
|
|
4
|
+
type RedirectResult = RedirectInfo & {
|
|
5
|
+
matchedQueryString?: string;
|
|
6
|
+
};
|
|
4
7
|
/**
|
|
5
8
|
* extended RedirectsMiddlewareConfig config type for RedirectsMiddleware
|
|
6
9
|
*/
|
|
@@ -28,15 +31,20 @@ export declare class RedirectsMiddleware extends MiddlewareBase {
|
|
|
28
31
|
* @returns route handler
|
|
29
32
|
*/
|
|
30
33
|
getHandler(): (req: NextRequest, res?: NextResponse) => Promise<NextResponse>;
|
|
31
|
-
private handler;
|
|
32
34
|
/**
|
|
33
35
|
* Method returns RedirectInfo when matches
|
|
34
36
|
* @param {NextRequest} req request
|
|
35
37
|
* @param {string} siteName site name
|
|
36
|
-
* @returns Promise<RedirectInfo | undefined>
|
|
37
|
-
* @
|
|
38
|
+
* @returns Promise<RedirectInfo | undefined> The redirect info or undefined if no redirect is found
|
|
39
|
+
* @protected
|
|
40
|
+
*/
|
|
41
|
+
protected getExistsRedirect(req: NextRequest, siteName: string): Promise<RedirectResult | undefined>;
|
|
42
|
+
/**
|
|
43
|
+
* @param {NextRequest} req request
|
|
44
|
+
* @param {Response} res response
|
|
45
|
+
* @returns {Promise<NextResponse>} The redirect response.
|
|
38
46
|
*/
|
|
39
|
-
|
|
47
|
+
protected processRedirectRequest(req: NextRequest, res?: NextResponse): Promise<NextResponse>;
|
|
40
48
|
/**
|
|
41
49
|
* When a user clicks on a link generated by the Link component from next/link,
|
|
42
50
|
* Next.js adds special parameters in the route called path.
|
|
@@ -55,3 +63,4 @@ export declare class RedirectsMiddleware extends MiddlewareBase {
|
|
|
55
63
|
*/
|
|
56
64
|
private createRedirectResponse;
|
|
57
65
|
}
|
|
66
|
+
export {};
|