import React, { Fragment } from 'react' import PropTypes from 'prop-types' import { Link as GatsbyLink } from 'gatsby' import { OutboundLink } from 'gatsby-plugin-google-analytics' import classNames from 'classnames' import Icon from './icon' import classes from '../styles/link.module.sass' import { isString } from './util' const internalRegex = /(http(s?)):\/\/(prodi.gy|spacy.io|irl.spacy.io|explosion.ai|course.spacy.io)/gi const Whitespace = ({ children }) => ( // Ensure that links are always wrapped in spaces <> {children} ) function getIcon(dest) { if (/(github.com)/.test(dest)) return 'code' if (/^\/?api\/architectures#/.test(dest)) return 'network' if (/^\/?api/.test(dest)) return 'docs' if (/^\/?models\/(.+)/.test(dest)) return 'package' return null } export default function Link({ children, to, href, onClick, activeClassName, hidden = false, hideIcon = false, ws = false, forceExternal = false, className, ...other }) { const dest = to || href const external = forceExternal || /(http(s?)):\/\//gi.test(dest) const icon = getIcon(dest) const withIcon = !hidden && !hideIcon && !!icon const sourceWithText = withIcon && isString(children) const linkClassNames = classNames(classes.root, className, { [classes.hidden]: hidden, [classes.nowrap]: (withIcon && !sourceWithText) || icon === 'network', [classes.withIcon]: withIcon, }) const Wrapper = ws ? Whitespace : Fragment const content = ( <> {sourceWithText ? {children} : children} {withIcon && } ) if (!external) { if ((dest && /^#/.test(dest)) || onClick) { return ( {children} ) } return ( {content} ) } const isInternal = internalRegex.test(dest) const rel = isInternal ? null : 'noopener nofollow noreferrer' return ( {content} ) } export const OptionalLink = ({ to, href, children, ...props }) => { const dest = to || href return dest ? ( {children} ) : ( children || null ) } Link.propTypes = { children: PropTypes.node.isRequired, to: PropTypes.string, href: PropTypes.string, onClick: PropTypes.func, activeClassName: PropTypes.string, hidden: PropTypes.bool, hideIcon: PropTypes.bool, ws: PropTypes.bool, className: PropTypes.string, }