Bluesky app fork with some witchin' additions 馃挮
witchsky.app
bluesky
fork
client
1import {isValidDomain} from './url-helpers'
2
3interface DetectedLink {
4 link: string
5}
6type DetectedLinkable = string | DetectedLink
7export function detectLinkables(text: string): DetectedLinkable[] {
8 const re =
9 /((^|\s|\()@[a-z0-9.-]*)|((^|\s|\()https?:\/\/[\S]+)|((^|\s|\()(?<domain>[a-z][a-z0-9]*(\.[a-z0-9]+)+)[\S]*)/gi
10 const segments = []
11 let match
12 let start = 0
13 while ((match = re.exec(text))) {
14 let matchIndex = match.index
15 let matchValue = match[0]
16
17 if (match.groups?.domain && !isValidDomain(match.groups?.domain)) {
18 continue
19 }
20
21 if (/\s|\(/.test(matchValue)) {
22 // HACK
23 // skip the starting space
24 // we have to do this because RN doesnt support negative lookaheads
25 // -prf
26 matchIndex++
27 matchValue = matchValue.slice(1)
28 }
29
30 // strip ending punctuation
31 if (/[.,;!?]$/.test(matchValue)) {
32 matchValue = matchValue.slice(0, -1)
33 }
34 if (/[)]$/.test(matchValue) && !matchValue.includes('(')) {
35 matchValue = matchValue.slice(0, -1)
36 }
37
38 if (start !== matchIndex) {
39 segments.push(text.slice(start, matchIndex))
40 }
41 segments.push({link: matchValue})
42 start = matchIndex + matchValue.length
43 }
44 if (start < text.length) {
45 segments.push(text.slice(start))
46 }
47 return segments
48}