about summary refs log tree commit diff
path: root/src/lib/strings.ts
diff options
context:
space:
mode:
authorJoão Ferreiro <ferreiro@pinkroom.dev>2022-11-28 16:56:05 +0000
committerJoão Ferreiro <ferreiro@pinkroom.dev>2022-11-28 16:56:05 +0000
commitc5f3200d6b561af94ec98259e731d9e090719df0 (patch)
tree1847500a3041ed9d1642e12c6f01e3581b8aafb6 /src/lib/strings.ts
parent5ea750599d08229d4b5b10d0e724ca14c73735f5 (diff)
parentb9c9895c45158b3db52e07114ad4305d85e803ea (diff)
downloadvoidsky-c5f3200d6b561af94ec98259e731d9e090719df0.tar.zst
Merge branch 'main' into upload-image
Diffstat (limited to 'src/lib/strings.ts')
-rw-r--r--src/lib/strings.ts21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/lib/strings.ts b/src/lib/strings.ts
index 032eec566..fb9d15b29 100644
--- a/src/lib/strings.ts
+++ b/src/lib/strings.ts
@@ -1,6 +1,7 @@
 import {AtUri} from '../third-party/uri'
 import {Entity} from '../third-party/api/src/client/types/app/bsky/feed/post'
 import {PROD_SERVICE} from '../state'
+import TLDs from 'tlds'
 
 export const MAX_DISPLAY_NAME = 64
 export const MAX_DESCRIPTION = 256
@@ -57,6 +58,14 @@ export function ago(date: number | string | Date): string {
   }
 }
 
+export function isValidDomain(str: string): boolean {
+  return !!TLDs.find(tld => {
+    let i = str.lastIndexOf(tld)
+    if (i === -1) return false
+    return str.charAt(i - 1) === '.' && i === str.length - tld.length
+  })
+}
+
 export function extractEntities(
   text: string,
   knownHandles?: Set<string>,
@@ -85,10 +94,14 @@ export function extractEntities(
   {
     // links
     const re =
-      /(^|\s)((https?:\/\/[\S]+)|([a-z][a-z0-9]*(\.[a-z0-9]+)+[\S]*))(\b)/dg
+      /(^|\s)((https?:\/\/[\S]+)|((?<domain>[a-z][a-z0-9]*(\.[a-z0-9]+)+)[\S]*))(\b)/dg
     while ((match = re.exec(text))) {
       let value = match[2]
       if (!value.startsWith('http')) {
+        const domain = match.groups?.domain
+        if (!domain || !isValidDomain(domain)) {
+          continue
+        }
         value = `https://${value}`
       }
       ents.push({
@@ -110,7 +123,7 @@ interface DetectedLink {
 type DetectedLinkable = string | DetectedLink
 export function detectLinkables(text: string): DetectedLinkable[] {
   const re =
-    /((^|\s)@[a-z0-9\.-]*)|((^|\s)https?:\/\/[\S]+)|((^|\s)[a-z][a-z0-9]*(\.[a-z0-9]+)+[\S]*)/gi
+    /((^|\s)@[a-z0-9\.-]*)|((^|\s)https?:\/\/[\S]+)|((^|\s)(?<domain>[a-z][a-z0-9]*(\.[a-z0-9]+)+)[\S]*)/gi
   const segments = []
   let match
   let start = 0
@@ -118,6 +131,10 @@ export function detectLinkables(text: string): DetectedLinkable[] {
     let matchIndex = match.index
     let matchValue = match[0]
 
+    if (match.groups?.domain && !isValidDomain(match.groups?.domain)) {
+      continue
+    }
+
     if (/\s/.test(matchValue)) {
       // HACK
       // skip the starting space