@sitecore-jss/sitecore-jss-nextjs 22.11.0-canary.2 → 22.11.0-canary.4

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.
@@ -41,12 +41,24 @@ exports.Link = void 0;
41
41
  const react_1 = __importStar(require("react"));
42
42
  const link_1 = __importDefault(require("next/link"));
43
43
  const sitecore_jss_react_1 = require("@sitecore-jss/sitecore-jss-react");
44
+ /**
45
+ * The list of NextLink props to be supported by the Link component.
46
+ */
47
+ const supportedNextLinkProps = [
48
+ 'as',
49
+ 'onNavigate',
50
+ 'passHref',
51
+ 'prefetch',
52
+ 'replace',
53
+ 'scroll',
54
+ 'shallow',
55
+ ];
44
56
  /**
45
57
  * Matches relative URLs that end with a file extension.
46
58
  */
47
59
  const FILE_EXTENSION_MATCHER = /^\/.*\.\w+$/;
48
60
  exports.Link = (0, react_1.forwardRef)((props, ref) => {
49
- const { field, editable = true, children, internalLinkMatcher = /^\//g, showLinkTextWithChildrenPresent } = props, htmlLinkProps = __rest(props, ["field", "editable", "children", "internalLinkMatcher", "showLinkTextWithChildrenPresent"]);
61
+ const { field, editable = true, children, internalLinkMatcher = /^\//g, showLinkTextWithChildrenPresent } = props, rest = __rest(props, ["field", "editable", "children", "internalLinkMatcher", "showLinkTextWithChildrenPresent"]);
50
62
  if (!field ||
51
63
  (!field.editable &&
52
64
  !field.value &&
@@ -66,18 +78,31 @@ exports.Link = (0, react_1.forwardRef)((props, ref) => {
66
78
  const isFileUrl = FILE_EXTENSION_MATCHER.test(href);
67
79
  // determine if a link is a route or not. File extensions are not routes and should not be pre-fetched.
68
80
  if (isMatching && !isFileUrl) {
69
- delete htmlLinkProps.emptyFieldEditingComponent;
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 }, (process.env.TEST
71
- ? { 'data-nextjs-link': true, 'data-nextjs-link-prefetch': props.prefetch }
81
+ delete rest.emptyFieldEditingComponent;
82
+ return (react_1.default.createElement(link_1.default, Object.assign({ href: { pathname: href, query: querystring, hash: anchor }, key: "link", title: value.title, target: value.target, className: value.class }, rest, { locale: false, ref: ref }, (process.env.TEST
83
+ ? {
84
+ 'data-nextjs-link': true,
85
+ 'data-nextjs-link-prefetch': props.prefetch,
86
+ }
72
87
  : {})),
73
88
  text,
74
89
  children));
75
90
  }
76
91
  }
77
- // prevent passing internalLinkMatcher or prefetch as it is an invalid DOM element prop
78
- const reactLinkProps = Object.assign({}, props);
79
- delete reactLinkProps.internalLinkMatcher;
80
- delete reactLinkProps.prefetch;
92
+ const reactLinkProps = sanitizeLinkProps(props);
81
93
  return (react_1.default.createElement(sitecore_jss_react_1.Link, Object.assign({}, reactLinkProps, { ref: ref }, (process.env.TEST ? { 'data-react-link': true } : {}))));
82
94
  });
83
95
  exports.Link.displayName = 'NextLink';
96
+ /**
97
+ * Sanitize props for ReactLink by removing Next.js and internal props to prevent invalid DOM attributes.
98
+ * @param {LinkProps} props - The props the Link component received.
99
+ * @returns sanitized props for ReactLink.
100
+ */
101
+ function sanitizeLinkProps(props) {
102
+ const internalProps = ['internalLinkMatcher'];
103
+ const sanitizedProps = Object.assign({}, props);
104
+ for (const prop of [...supportedNextLinkProps, ...internalProps]) {
105
+ delete sanitizedProps[prop];
106
+ }
107
+ return sanitizedProps;
108
+ }
@@ -278,9 +278,11 @@ class RedirectsMiddleware extends middleware_1.MiddlewareBase {
278
278
  return this.createRedirectResponse(target, res, 301, 'Moved Permanently');
279
279
  case site_1.REDIRECT_TYPE_302:
280
280
  return this.createRedirectResponse(target, res, 302, 'Found');
281
- case site_1.REDIRECT_TYPE_SERVER_TRANSFER:
282
- // rewrite expects a string; unwrap NextURL if needed
283
- return this.rewrite(typeof target === 'string' ? target : target.href, req, res, isExternal);
281
+ case site_1.REDIRECT_TYPE_SERVER_TRANSFER: {
282
+ // rewrite expects a path string; for NextURL extract pathname + search, not full href
283
+ const rewritePath = typeof target === 'string' ? target : `${target.pathname}${target.search}`;
284
+ return this.rewrite(rewritePath, req, res, isExternal);
285
+ }
284
286
  default:
285
287
  // Unknown type: return the input response unchanged
286
288
  return res;
@@ -12,12 +12,24 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import React, { forwardRef } from 'react';
13
13
  import NextLink from 'next/link';
14
14
  import { Link as ReactLink, } from '@sitecore-jss/sitecore-jss-react';
15
+ /**
16
+ * The list of NextLink props to be supported by the Link component.
17
+ */
18
+ const supportedNextLinkProps = [
19
+ 'as',
20
+ 'onNavigate',
21
+ 'passHref',
22
+ 'prefetch',
23
+ 'replace',
24
+ 'scroll',
25
+ 'shallow',
26
+ ];
15
27
  /**
16
28
  * Matches relative URLs that end with a file extension.
17
29
  */
18
30
  const FILE_EXTENSION_MATCHER = /^\/.*\.\w+$/;
19
31
  export const Link = forwardRef((props, ref) => {
20
- const { field, editable = true, children, internalLinkMatcher = /^\//g, showLinkTextWithChildrenPresent } = props, htmlLinkProps = __rest(props, ["field", "editable", "children", "internalLinkMatcher", "showLinkTextWithChildrenPresent"]);
32
+ const { field, editable = true, children, internalLinkMatcher = /^\//g, showLinkTextWithChildrenPresent } = props, rest = __rest(props, ["field", "editable", "children", "internalLinkMatcher", "showLinkTextWithChildrenPresent"]);
21
33
  if (!field ||
22
34
  (!field.editable &&
23
35
  !field.value &&
@@ -37,18 +49,31 @@ export const Link = forwardRef((props, ref) => {
37
49
  const isFileUrl = FILE_EXTENSION_MATCHER.test(href);
38
50
  // determine if a link is a route or not. File extensions are not routes and should not be pre-fetched.
39
51
  if (isMatching && !isFileUrl) {
40
- delete htmlLinkProps.emptyFieldEditingComponent;
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 }, (process.env.TEST
42
- ? { 'data-nextjs-link': true, 'data-nextjs-link-prefetch': props.prefetch }
52
+ delete rest.emptyFieldEditingComponent;
53
+ return (React.createElement(NextLink, Object.assign({ href: { pathname: href, query: querystring, hash: anchor }, key: "link", title: value.title, target: value.target, className: value.class }, rest, { locale: false, ref: ref }, (process.env.TEST
54
+ ? {
55
+ 'data-nextjs-link': true,
56
+ 'data-nextjs-link-prefetch': props.prefetch,
57
+ }
43
58
  : {})),
44
59
  text,
45
60
  children));
46
61
  }
47
62
  }
48
- // prevent passing internalLinkMatcher or prefetch as it is an invalid DOM element prop
49
- const reactLinkProps = Object.assign({}, props);
50
- delete reactLinkProps.internalLinkMatcher;
51
- delete reactLinkProps.prefetch;
63
+ const reactLinkProps = sanitizeLinkProps(props);
52
64
  return (React.createElement(ReactLink, Object.assign({}, reactLinkProps, { ref: ref }, (process.env.TEST ? { 'data-react-link': true } : {}))));
53
65
  });
54
66
  Link.displayName = 'NextLink';
67
+ /**
68
+ * Sanitize props for ReactLink by removing Next.js and internal props to prevent invalid DOM attributes.
69
+ * @param {LinkProps} props - The props the Link component received.
70
+ * @returns sanitized props for ReactLink.
71
+ */
72
+ function sanitizeLinkProps(props) {
73
+ const internalProps = ['internalLinkMatcher'];
74
+ const sanitizedProps = Object.assign({}, props);
75
+ for (const prop of [...supportedNextLinkProps, ...internalProps]) {
76
+ delete sanitizedProps[prop];
77
+ }
78
+ return sanitizedProps;
79
+ }
@@ -272,9 +272,11 @@ export class RedirectsMiddleware extends MiddlewareBase {
272
272
  return this.createRedirectResponse(target, res, 301, 'Moved Permanently');
273
273
  case REDIRECT_TYPE_302:
274
274
  return this.createRedirectResponse(target, res, 302, 'Found');
275
- case REDIRECT_TYPE_SERVER_TRANSFER:
276
- // rewrite expects a string; unwrap NextURL if needed
277
- return this.rewrite(typeof target === 'string' ? target : target.href, req, res, isExternal);
275
+ case REDIRECT_TYPE_SERVER_TRANSFER: {
276
+ // rewrite expects a path string; for NextURL extract pathname + search, not full href
277
+ const rewritePath = typeof target === 'string' ? target : `${target.pathname}${target.search}`;
278
+ return this.rewrite(rewritePath, req, res, isExternal);
279
+ }
278
280
  default:
279
281
  // Unknown type: return the input response unchanged
280
282
  return res;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-jss/sitecore-jss-nextjs",
3
- "version": "22.11.0-canary.2",
3
+ "version": "22.11.0-canary.4",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -72,16 +72,16 @@
72
72
  "react-dom": "^19.1.0"
73
73
  },
74
74
  "dependencies": {
75
- "@sitecore-jss/sitecore-jss": "22.11.0-canary.2",
76
- "@sitecore-jss/sitecore-jss-dev-tools": "22.11.0-canary.2",
77
- "@sitecore-jss/sitecore-jss-react": "22.11.0-canary.2",
75
+ "@sitecore-jss/sitecore-jss": "22.11.0-canary.4",
76
+ "@sitecore-jss/sitecore-jss-dev-tools": "22.11.0-canary.4",
77
+ "@sitecore-jss/sitecore-jss-react": "22.11.0-canary.4",
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": "a2f6bec65f2127ae1aed808c999b47977df371d6",
84
+ "gitHead": "c0455eac6a27d2fa7d9eb1ad721f3985d2292105",
85
85
  "files": [
86
86
  "dist",
87
87
  "types",
@@ -1,15 +1,16 @@
1
1
  import React from 'react';
2
2
  import { LinkProps as NextLinkProps } from 'next/link';
3
3
  import { LinkProps as ReactLinkProps } from '@sitecore-jss/sitecore-jss-react';
4
+ /**
5
+ * The list of NextLink props to be supported by the Link component.
6
+ */
7
+ declare const supportedNextLinkProps: readonly ["as", "onNavigate", "passHref", "prefetch", "replace", "scroll", "shallow"];
4
8
  export type LinkProps = ReactLinkProps & {
5
9
  /**
6
10
  * If `href` match with `internalLinkMatcher` regexp, then it's internal link and NextLink will be rendered
7
11
  * @default /^\//g
8
12
  */
9
13
  internalLinkMatcher?: RegExp;
10
- /**
11
- * Next.js Link prefetch.
12
- */
13
- prefetch?: NextLinkProps['prefetch'];
14
- };
14
+ } & Pick<NextLinkProps, typeof supportedNextLinkProps[number]>;
15
15
  export declare const Link: React.ForwardRefExoticComponent<Omit<LinkProps, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
16
+ export {};