UNPKG

@newrelic/gatsby-theme-newrelic

Version:

[![Community Project header](https://github.com/newrelic/opensource-website/raw/master/src/images/categories/Community_Project.png)](https://opensource.newrelic.com/oss-category/#community-project)

173 lines (156 loc) 4.33 kB
/* eslint-disable jsx-a11y/anchor-has-content */ import React, { forwardRef } from 'react'; import PropTypes from 'prop-types'; import { useStaticQuery, graphql, Link as GatsbyLink } from 'gatsby'; import useLocale from '../hooks/useLocale'; import { localizePath } from '../utils/localization'; import SignUpLink from './SignUpLink'; import Icon from './Icon'; import useInstrumentedHandler from '../hooks/useInstrumentedHandler'; import { css } from '@emotion/react'; const isHash = (to) => to.startsWith('#'); const isExternal = (to) => to.startsWith('http'); const isNewRelicDomain = (to) => { try { const { hostname } = new URL(to); return hostname === 'newrelic.com' || hostname.endsWith('.newrelic.com'); } catch { return false; } }; const isSignup = (to) => to.startsWith('https://newrelic.com/signup'); const isImageLink = (className) => className === 'gatsby-resp-image-link'; const isRelativePath = (to) => !to.startsWith('http') && to.startsWith('/'); // Prevents our rewrites to our i18n Netlify sites showing external link icons const i18nNetlifySites = [ 'docs-website-kr.netlify.app/kr/', 'docs-website-jp.netlify.app/jp/', 'docs-website-es.netlify.app/es/', 'docs-website-pt.netlify.app/pt/', 'docs-website-fr.netlify.app/fr/', ]; const isI18nNetlifySite = (to) => i18nNetlifySites.some((site) => to.includes(site)); const Link = forwardRef( ( { to, onClick, instrumentation = {}, displayExternalIcon, shouldAutoLocalize = true, isEmbedPageLink = false, ...props }, ref ) => { const locale = useLocale(); const { site: { siteMetadata: { siteUrl }, }, } = useStaticQuery(graphql` query { site { siteMetadata { siteUrl } } } `); const handleExternalLinkClick = useInstrumentedHandler(onClick, { eventName: 'externalLinkClick', category: 'LinkClick', origin: 'gatsbyTheme', href: to, ...instrumentation, }); const handleInternalLinkClick = useInstrumentedHandler(onClick, { eventName: 'internalLinkClick', category: 'LinkClick', origin: 'gatsbyTheme', href: to, ...instrumentation, }); if (to.startsWith(siteUrl)) { to = to.replace(siteUrl, ''); // absolute links to the home page without trailing slash to = to || '/'; } if (isHash(to)) { return <a ref={ref} href={to} {...props} />; } if (isSignup(to)) { return ( <SignUpLink {...props} href={to} onClick={handleExternalLinkClick} instrumentation={instrumentation} ref={ref} /> ); } if ((isExternal(to) || isEmbedPageLink) && !isI18nNetlifySite(to)) { if (isRelativePath(to)) { to = siteUrl + to; } const rel = isNewRelicDomain(to) ? 'noopener' : 'noopener noreferrer'; return ( <> {/* eslint-disable-next-line react/jsx-no-target-blank */} <a {...props} href={to} onClick={handleExternalLinkClick} target="_blank" rel={rel} ref={ref} > {props.children} {displayExternalIcon && ( <Icon name="fe-external-link" css={css` margin-left: 0.25rem; position: relative; top: -1px; `} size="1em" /> )} </a> </> ); } if (isImageLink(props.className)) { return <a {...props} href={to} />; } return ( <GatsbyLink to={ shouldAutoLocalize ? localizePath({ path: to, locale, }) : to } ref={ref} onClick={handleInternalLinkClick} {...props} /> ); } ); Link.propTypes = { to: PropTypes.string.isRequired, onClick: PropTypes.func, instrumentation: PropTypes.object, className: PropTypes.string, children: PropTypes.node, shouldAutoLocalize: PropTypes.bool, displayExternalIcon: PropTypes.bool, isEmbedPageLink: PropTypes.bool, }; export default Link;