🌐

[react-anchorme] テキスト内にあるURLをaタグ化 またはLinkタグ化

2022/03/07に公開約1,800字

やりたいこと

テキスト (例: ほげ https://hogehoge.com/fuga ふが https://google.com/fuga) の中にあるURLが、

  • 外部Originの場合、別タブを開く

    <a target='_blank' rel='noopener noreferrer'>
      {children}
    </a>
    
  • 内部Originの場合、SPAとして遷移する

    import NextLink from 'next/link'
    
    ...
    
    <NextLink href={href} passHref>
      <a className={className}>
        {children}
      </a>
    </NextLink>
    

を実現したい。

↓ つまり、こう (href以外の属性は省略してます)

ほげ <Link href="fuga">https://hogehoge.com/fuga</Link> ふが <a href="https://google.com/fuga">https://google.com/fuga</a>

こうする

// components/Text.tsx
import Link, { LinkProps } from 'next/link'
import { Anchorme, LinkComponentProps } from 'react-anchorme'
import styles from '@/styles/components/text.module.scss'

export const TextWithUrl: React.VFC<{content: string}> = ({ content }) => {
  const isInternalUrl = (url: string): boolean => {
    // 内部Originとして判別するURL
    const internalUrls = [
      'https://hogehoge.com/',
      'httplocalhost:4000/'
    ] as const

    return internalUrls.some((internalUrl) => url.includes(internalUrl))
  }

  const linkComponent: React.VFC<LinkComponentProps> = ({
    href,
    className = styles['text--link'],
    ...props
  }) => {
    if (isInternalUrl(href)) {
      const url = new URL(href)
      // fuga/piyo?pien=1#paon までを保持
      const asPath = `${url.pathname}${url.search}${url.hash}`
      return (
        <Link href={asPath} passHref>
          <a className={className} {...props} />
        </Link>
      )
    }
    return (
      <a
        href={href}
        className={className}
        {...props}
        target='_blank'
        rel='noreferrer noopener'
      />
    )
  }

  return <Anchorme linkComponent={linkComponent}>{content}</Anchorme>
}

参考元

https://github.com/potty/react-anchorme

Discussion

ログインするとコメントできます