From cf1fae5837240a4deb7c5b4927e1ddd9bdeebb24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Fri, 11 Jul 2025 16:25:37 +0200 Subject: [PATCH] Fix using CMD or CTRL to open in a new tab (#3466) --- .../src/components/primitives/Link.tsx | 27 ++----------------- packages/gitbook/src/components/utils/link.ts | 23 ++++++++++++++++ 2 files changed, 25 insertions(+), 25 deletions(-) create mode 100644 packages/gitbook/src/components/utils/link.ts diff --git a/packages/gitbook/src/components/primitives/Link.tsx b/packages/gitbook/src/components/primitives/Link.tsx index de8397bdb..0550867ea 100644 --- a/packages/gitbook/src/components/primitives/Link.tsx +++ b/packages/gitbook/src/components/primitives/Link.tsx @@ -6,6 +6,7 @@ import React from 'react'; import { tcls } from '@/lib/tailwind'; import { SiteExternalLinksTarget } from '@gitbook/api'; import { type TrackEventInput, useTrackEvent } from '../Insights'; +import { isExternalLink } from '../utils/link'; import { type DesignTokenName, useClassnames } from './StyleProvider'; // Props from Next, which includes NextLinkProps and all the things anchor elements support. @@ -89,7 +90,7 @@ export const Link = React.forwardRef(function Link( if (isInIframe && isExternalWithOrigin) { event.preventDefault(); window.open(href, '_blank', 'noopener noreferrer'); - } else if (isExternal) { + } else if (isExternal && !event.ctrlKey && !event.metaKey) { // The external logic server-side is limited // so we use the client-side logic to determine the real target // by default the target is "_self". @@ -177,27 +178,3 @@ export const LinkOverlay = React.forwardRef(function LinkOverlay( ); }); - -/** - * Check if a link is external, compared to an origin. - */ -function isExternalLink(href: string, origin: string | null = null) { - if (!URL.canParse) { - // If URL.canParse is not available, we quickly check if it looks like a URL - return href.startsWith('http'); - } - - if (!URL.canParse(href)) { - // If we can't parse the href, we consider it a relative path - return false; - } - - if (!origin) { - // If origin is not provided, we consider the link external - return true; - } - - // If the url points to the same origin, we consider it internal - const parsed = new URL(href); - return parsed.origin !== origin; -} diff --git a/packages/gitbook/src/components/utils/link.ts b/packages/gitbook/src/components/utils/link.ts new file mode 100644 index 000000000..f20c22d3d --- /dev/null +++ b/packages/gitbook/src/components/utils/link.ts @@ -0,0 +1,23 @@ +/** + * Check if a link is external, compared to an origin. + */ +export function isExternalLink(href: string, origin: string | null = null) { + if (!URL.canParse) { + // If URL.canParse is not available, we quickly check if it looks like a URL + return href.startsWith('http'); + } + + if (!URL.canParse(href)) { + // If we can't parse the href, we consider it a relative path + return false; + } + + if (!origin) { + // If origin is not provided, we consider the link external + return true; + } + + // If the url points to the same origin, we consider it internal + const parsed = new URL(href); + return parsed.origin !== origin; +}