diff --git a/.changeset/spotty-glasses-speak.md b/.changeset/spotty-glasses-speak.md new file mode 100644 index 0000000000..b29aa9368e --- /dev/null +++ b/.changeset/spotty-glasses-speak.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Add support for non external URI's in the Link component to `to` prop. For example `Slack diff --git a/packages/core/src/components/Link/Link.test.tsx b/packages/core/src/components/Link/Link.test.tsx index 23d2728bf6..4efd005a9e 100644 --- a/packages/core/src/components/Link/Link.test.tsx +++ b/packages/core/src/components/Link/Link.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import { wrapInTestApp } from '@backstage/test-utils'; -import { Link } from './Link'; +import { isExternalUri, Link } from './Link'; import { Route, Routes } from 'react-router'; import { act } from 'react-dom/test-utils'; @@ -39,4 +39,31 @@ describe('', () => { }); expect(getByText(testString)).toBeInTheDocument(); }); + + describe('isExternalUri', () => { + it.each([ + [true, 'http://'], + [true, 'https://'], + [true, 'https://some-host'], + [true, 'https://some-host/path#fragment'], + [true, 'https://some-host/path?param1=value'], + [true, 'slack://'], + [true, 'mailto://'], + [true, 'ms-help://'], + [true, 'ms.help://'], + [true, 'ms+help://'], + [false, '//'], + [false, '123://'], + [false, 'abc&xzy://'], + [false, 'http'], + [false, 'https:/a'], + [false, 'path/to'], + [false, 'path/to/something#fragment'], + [false, 'path/to/something?param1=value'], + [false, '/path/to/something'], + [false, '/path/to/something#fragment'], + ])('should be %p when %p', (expected, uri) => { + expect(isExternalUri(uri)).toBe(expected); + }); + }); }); diff --git a/packages/core/src/components/Link/Link.tsx b/packages/core/src/components/Link/Link.tsx index cd74b681db..786d36fe44 100644 --- a/packages/core/src/components/Link/Link.tsx +++ b/packages/core/src/components/Link/Link.tsx @@ -24,6 +24,8 @@ import { LinkProps as RouterLinkProps, } from 'react-router-dom'; +export const isExternalUri = (uri: string) => /^([a-z+.-]+):\/\//.test(uri); + export type LinkProps = MaterialLinkProps & RouterLinkProps & { component?: ElementType; @@ -35,7 +37,7 @@ export type LinkProps = MaterialLinkProps & */ export const Link = React.forwardRef((props, ref) => { const to = String(props.to); - return /^https?:\/\//.test(to) ? ( + return isExternalUri(to) ? ( // External links ) : (