diff --git a/ui/src/album/AlbumDetails.js b/ui/src/album/AlbumDetails.js
index 165522117..c22805879 100644
--- a/ui/src/album/AlbumDetails.js
+++ b/ui/src/album/AlbumDetails.js
@@ -33,6 +33,7 @@ import {
import config from '../config'
import { intersperse } from '../utils'
import AlbumExternalLinks from './AlbumExternalLinks'
+import AnchorMe from '../common/AnchorMe'
const useStyles = makeStyles(
(theme) => ({
@@ -116,7 +117,7 @@ const AlbumComment = ({ record }) => {
const formatted = useMemo(() => {
return lines.map((line, idx) => (
-
+
))
diff --git a/ui/src/common/AnchorMe.js b/ui/src/common/AnchorMe.js
new file mode 100644
index 000000000..dadd06ef3
--- /dev/null
+++ b/ui/src/common/AnchorMe.js
@@ -0,0 +1,73 @@
+import React, { useCallback, useMemo } from 'react'
+import { Link } from '@material-ui/core'
+import { makeStyles } from '@material-ui/core/styles'
+import PropTypes from 'prop-types'
+
+const useStyles = makeStyles(
+ (theme) => ({
+ link: {
+ textDecoration: 'none',
+ color: theme.palette.primary.main,
+ },
+ }),
+ { name: 'RaLink' }
+)
+
+const AnchorMe = ({ text, ...rest }) => {
+ const classes = useStyles()
+ const linkify = useCallback((text) => {
+ const urlRegex =
+ /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])/gi
+ return [...text.matchAll(urlRegex)]
+ }, [])
+
+ const parse = useCallback(() => {
+ const matches = linkify(text)
+ if (matches.length === 0) return text
+
+ const elements = []
+ let lastIndex = 0
+ matches.forEach((match, index) => {
+ // Push text located before matched string
+ if (match.index > lastIndex) {
+ elements.push(text.substring(lastIndex, match.index))
+ }
+
+ const href = match[0]
+ // Push Link component
+ elements.push(
+
+ {href}
+
+ )
+
+ lastIndex = match.index + href.length
+ })
+
+ // Push remaining text
+ if (text.length > lastIndex) {
+ elements.push(
+
+ )
+ }
+
+ return elements.length === 1 ? elements[0] : elements
+ }, [linkify, text, rest, classes.link])
+
+ const parsedText = useMemo(() => parse(), [parse])
+
+ return <>{parsedText}>
+}
+
+AnchorMe.propTypes = {
+ text: PropTypes.string,
+}
+
+export default React.memo(AnchorMe)