manifold/web/components/linkify.tsx
Marshall Polaris 7debc4925e
De-feedify contract tab contents (#808)
* De-feedify contract bets list

* De-feedify contract comments lists

* Clean up a bunch of duplicated work in the comments list stuff

* Remove wrapper markup from comment replies list

* Fix sort order on comments I broke

* Kill now unhelpful `CommentRepliesList` wrapper component

* More random cleanup

* More cleanup and fix some styling I had broken

* Make bet calculations less wrong

* Keep up to date with master

* Make copy link component copy better URL

* Make highlighted comments align properly

* Make user header left align with content on comments

* Fix some free response UI stuff up
2022-08-30 02:41:47 -07:00

56 lines
1.5 KiB
TypeScript

import clsx from 'clsx'
import { Fragment } from 'react'
import { SiteLink } from './site-link'
// Return a JSX span, linkifying @username, #hashtags, and https://...
// TODO: Use a markdown parser instead of rolling our own here.
export function Linkify(props: {
text: string
className?: string
gray?: boolean
}) {
const { text, className, gray } = props
// Replace "m1234" with "ϻ1234"
// const mRegex = /(\W|^)m(\d+)/g
// text = text.replace(mRegex, (_, pre, num) => `${pre}ϻ${num}`)
// Find instances of @username, #hashtag, and https://...
const regex =
/(?:^|\s)(?:[@#][a-z0-9_]+|https?:\/\/[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_|])/gi
const matches = text.match(regex) || []
const links = matches.map((match) => {
// Matches are in the form: " @username" or "https://example.com"
const whitespace = match.match(/^\s/)
const symbol = match.trim().substring(0, 1)
const tag = match.trim().substring(1)
const href =
{
'@': `/${tag}`,
'#': `/tag/${tag}`,
}[symbol] ?? match.trim()
return (
<>
{whitespace}
<SiteLink
className={gray ? 'text-gray-500' : 'text-indigo-700'}
href={href}
>
{symbol}
{tag}
</SiteLink>
</>
)
})
return (
<span className={clsx(className, 'break-anywhere')}>
{text.split(regex).map((part, i) => (
<Fragment key={i}>
{part}
{links[i]}
</Fragment>
))}
</span>
)
}