1 import React from 'react'
2 import {Link as PrimerLink} from '@primer/react'
3 import {Link as GatsbyLink} from 'gatsby'
4 import omit from '../util/omit'
5
6 import * as styles from './link.module.css'
7
8 import {clsx} from 'clsx'
9
10 const FALLBACK = `http://_${Math.random().toString().slice(2)}._${Math.random().toString().slice(2)}`
11
12 const getLocalPath = href => {
13 if (!href || href.startsWith('#')) {
14 return null
15 }
16
17 try {
18 const url = new URL(href, FALLBACK)
19 if (url.host === 'docs.npmjs.com' || url.origin === FALLBACK) {
20 return `${url.pathname}${url.search}${url.hash}`
21 }
22 } catch {
23 // ignore errors which will just pass along all props to PrimerLink
24 }
25
26 return null
27 }
28
29 const GatsbyLinkWithoutSxProps = React.forwardRef(function GatsbyLinkWithoutSxProps(props, ref) {
30 return <GatsbyLink ref={ref} {...omit(props, 'sx', 'underline', 'hoverColor', 'muted')} />
31 })
32
33 const Link = React.forwardRef(function Link({to, href, showUnderline = false, className, ...props}, ref) {
34 const localPath = getLocalPath(href)
35 const combinedClassName = showUnderline ? clsx(className, styles.showUnderline) : className
36
37 if (to || localPath !== null) {
38 return (
39 <PrimerLink
40 ref={ref}
41 as={GatsbyLinkWithoutSxProps}
42 to={to || localPath}
43 className={combinedClassName}
44 {...props}
45 />
46 )
47 }
48
49 return <PrimerLink ref={ref} href={href} className={combinedClassName} {...props} />
50 })
51
52 export const LinkNoUnderline = React.forwardRef(function LinkNoUnderline({className, ...props}, ref) {
53 return <Link ref={ref} className={clsx(styles.Link, className)} {...props} />
54 })
55
56 export default Link