Skip to content

Commit 02a86ae

Browse files
committed
Refactor login in link
- Revalidate if the link is external in the `onClick`
1 parent 7672bed commit 02a86ae

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

packages/gitbook/src/components/Header/HeaderLogo.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export async function HeaderLogo(props: HeaderLogoProps) {
2121
return (
2222
<Link
2323
href={linker.toAbsoluteURL(linker.toPathInSite(''))}
24-
target="_self"
2524
className={tcls('group/headerlogo', 'min-w-0', 'shrink', 'flex', 'items-center')}
2625
>
2726
{customization.header.logo ? (

packages/gitbook/src/components/primitives/Link.tsx

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@ export const LinkSettingsContext = React.createContext<{
4040
externalLinksTarget: SiteExternalLinksTarget.Self,
4141
});
4242

43+
/**
44+
* Get the target and rel props for a link based on the provided props and context.
45+
*/
46+
function getTargetProps(
47+
props: Pick<LinkProps, 'href' | 'rel' | 'target'>,
48+
context: {
49+
externalLinksTarget: SiteExternalLinksTarget;
50+
isExternal: boolean;
51+
}
52+
) {
53+
const target =
54+
props.target ??
55+
(context.isExternal && context.externalLinksTarget === SiteExternalLinksTarget.Blank
56+
? '_blank'
57+
: undefined);
58+
// Automatically set rel if target is _blank, or use the specified rel.
59+
const rel = props.rel ?? (target === '_blank' ? 'noopener noreferrer' : undefined);
60+
return { target, rel };
61+
}
62+
4363
/**
4464
* Low-level Link component that handles navigation to external urls.
4565
* It does not contain any styling.
@@ -52,46 +72,50 @@ export const Link = React.forwardRef(function Link(
5272
const { externalLinksTarget } = React.useContext(LinkSettingsContext);
5373
const trackEvent = useTrackEvent();
5474
const forwardedClassNames = useClassnames(classNames || []);
55-
56-
// Use a real anchor tag for external links,s and a Next.js Link for internal links.
57-
// If we use a NextLink for external links, Nextjs won't rerender the top-level layouts.
58-
const isExternal = URL.canParse ? URL.canParse(props.href) : props.href.startsWith('http');
75+
const isExternal = isExternalLink(href);
76+
const { target, rel } = getTargetProps(props, { externalLinksTarget, isExternal });
5977

6078
const onClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
79+
const isExternal = isExternalLink(href, window.location.origin);
80+
6181
if (insights) {
62-
trackEvent(insights, undefined, {
63-
immediate: isExternal,
64-
});
82+
trackEvent(insights, undefined, { immediate: isExternal });
6583
}
6684

67-
if (
68-
isExternalLink(href, window.location.origin) &&
69-
// When the page is embedded in an iframe, for security reasons other urls cannot be opened.
70-
// In this case, we open the link in a new tab.
71-
(window.self !== window.top ||
72-
// If the site is configured to open links in a new tab
73-
externalLinksTarget === SiteExternalLinksTarget.Blank)
74-
) {
85+
const isInIframe = window.self !== window.top;
86+
87+
// When the page is embedded in an iframe
88+
// for security reasons other urls cannot be opened.
89+
if (isInIframe && isExternal) {
90+
event.preventDefault();
91+
window.open(href, '_blank', 'noopener noreferrer');
92+
} else {
93+
// The external logic server-side is limited
94+
// so we use the client-side logic to determine the real target
95+
// by default the target is "_self".
96+
const { target = '_self' } = getTargetProps(props, {
97+
externalLinksTarget,
98+
isExternal,
99+
});
75100
event.preventDefault();
76-
window.open(href, '_blank');
101+
window.open(href, target, rel);
77102
}
78103

79104
domProps.onClick?.(event);
80105
};
81106

82107
// We test if the link is external, without comparing to the origin
83108
// as this will be rendered on the server and it could result in a mismatch.
84-
if (isExternalLink(href)) {
109+
if (isExternal) {
85110
return (
86111
<a
87112
ref={ref}
88113
className={tcls(...forwardedClassNames, className)}
89114
{...domProps}
90115
href={href}
91116
onClick={onClick}
92-
{...(externalLinksTarget === SiteExternalLinksTarget.Blank && !domProps.target
93-
? { target: '_blank', rel: 'noopener noreferrer' }
94-
: {})}
117+
target={target}
118+
rel={rel}
95119
>
96120
{children}
97121
</a>

0 commit comments

Comments
 (0)