Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

Select the types of activity you want to include in your feed.

at a876aae44ea07494ebea9727350aa060b81f317b 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}