diff options
Diffstat (limited to 'src/lib/strings/url-helpers.ts')
-rw-r--r-- | src/lib/strings/url-helpers.ts | 70 |
1 files changed, 53 insertions, 17 deletions
diff --git a/src/lib/strings/url-helpers.ts b/src/lib/strings/url-helpers.ts index 8a71718c8..70a2b7069 100644 --- a/src/lib/strings/url-helpers.ts +++ b/src/lib/strings/url-helpers.ts @@ -1,8 +1,27 @@ import {AtUri} from '@atproto/api' -import {PROD_SERVICE} from 'lib/constants' +import {BSKY_SERVICE} from 'lib/constants' import TLDs from 'tlds' import psl from 'psl' +export const BSKY_APP_HOST = 'https://bsky.app' +const BSKY_TRUSTED_HOSTS = [ + 'bsky.app', + 'bsky.social', + 'blueskyweb.xyz', + 'blueskyweb.zendesk.com', + ...(__DEV__ ? ['localhost:19006', 'localhost:8100'] : []), +] + +/* + * This will allow any BSKY_TRUSTED_HOSTS value by itself or with a subdomain. + * It will also allow relative paths like /profile as well as #. + */ +const TRUSTED_REGEX = new RegExp( + `^(http(s)?://(([\\w-]+\\.)?${BSKY_TRUSTED_HOSTS.join( + '|([\\w-]+\\.)?', + )})|/|#)`, +) + export function isValidDomain(str: string): boolean { return !!TLDs.find(tld => { let i = str.lastIndexOf(tld) @@ -28,7 +47,7 @@ export function makeRecordUri( export function toNiceDomain(url: string): string { try { const urlp = new URL(url) - if (`https://${urlp.host}` === PROD_SERVICE) { + if (`https://${urlp.host}` === BSKY_SERVICE) { return 'Bluesky Social' } return urlp.host ? urlp.host : url @@ -67,8 +86,25 @@ export function isBskyAppUrl(url: string): boolean { return url.startsWith('https://bsky.app/') } +export function isRelativeUrl(url: string): boolean { + return /^\/[^/]/.test(url) +} + +export function isBskyRSSUrl(url: string): boolean { + return ( + (url.startsWith('https://bsky.app/') || isRelativeUrl(url)) && + /\/rss\/?$/.test(url) + ) +} + export function isExternalUrl(url: string): boolean { - return !isBskyAppUrl(url) && url.startsWith('http') + const external = !isBskyAppUrl(url) && url.startsWith('http') + const rss = isBskyRSSUrl(url) + return external || rss +} + +export function isTrustedUrl(url: string): boolean { + return TRUSTED_REGEX.test(url) } export function isBskyPostUrl(url: string): boolean { @@ -148,6 +184,11 @@ export function feedUriToHref(url: string): string { export function linkRequiresWarning(uri: string, label: string) { const labelDomain = labelToDomain(label) + // We should trust any relative URL or a # since we know it links to internal content + if (isRelativeUrl(uri) || uri === '#') { + return false + } + let urip try { urip = new URL(uri) @@ -156,21 +197,11 @@ export function linkRequiresWarning(uri: string, label: string) { } const host = urip.hostname.toLowerCase() - - if (host === 'bsky.app') { - // if this is a link to internal content, - // warn if it represents itself as a URL to another app - if ( - labelDomain && - labelDomain !== 'bsky.app' && - isPossiblyAUrl(labelDomain) - ) { - return true - } - return false + if (isTrustedUrl(uri)) { + // if this is a link to internal content, warn if it represents itself as a URL to another app + return !!labelDomain && labelDomain !== host && isPossiblyAUrl(labelDomain) } else { - // if this is a link to external content, - // warn if the label doesnt match the target + // if this is a link to external content, warn if the label doesnt match the target if (!labelDomain) { return true } @@ -220,3 +251,8 @@ export function splitApexDomain(hostname: string): [string, string] { hostnamep.domain, ] } + +export function createBskyAppAbsoluteUrl(path: string): string { + const sanitizedPath = path.replace(BSKY_APP_HOST, '').replace(/^\/+/, '') + return `${BSKY_APP_HOST.replace(/\/$/, '')}/${sanitizedPath}` +} |