Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
at main 48 lines 1.3 kB view raw
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}