diff --git a/packages/editor/src/behaviors/behavior.links.ts b/packages/editor/src/behaviors/behavior.links.ts index ee68fb04..51a0cb00 100644 --- a/packages/editor/src/behaviors/behavior.links.ts +++ b/packages/editor/src/behaviors/behavior.links.ts @@ -1,5 +1,6 @@ import type {EditorSchema} from '../editor/define-schema' import * as selectors from '../selectors' +import {looksLikeUrl} from '../utils/looks-like-url' import {defineBehavior} from './behavior.types' /** @@ -80,12 +81,3 @@ export function createLinkBehaviors(config: LinkBehaviorsConfig) { return linkBehaviors } - -function looksLikeUrl(text: string) { - let looksLikeUrl = false - try { - new URL(text) - looksLikeUrl = true - } catch {} - return looksLikeUrl -} diff --git a/packages/editor/src/utils/looks-like-url.test.ts b/packages/editor/src/utils/looks-like-url.test.ts new file mode 100644 index 00000000..30b7d437 --- /dev/null +++ b/packages/editor/src/utils/looks-like-url.test.ts @@ -0,0 +1,13 @@ +import {expect, test} from 'vitest' +import {looksLikeUrl} from './looks-like-url' + +test(looksLikeUrl.name, () => { + expect(looksLikeUrl('https://example.com')).toBe(true) + expect(looksLikeUrl('http://example.com')).toBe(true) + expect(looksLikeUrl('example.com')).toBe(true) + expect(looksLikeUrl('mailto:foo@example.com')).toBe(true) + expect(looksLikeUrl('tel:+123456789')).toBe(true) + expect(looksLikeUrl('http://example')).toBe(false) + expect(looksLikeUrl('http:example')).toBe(false) + expect(looksLikeUrl('a:b')).toBe(false) +}) diff --git a/packages/editor/src/utils/looks-like-url.ts b/packages/editor/src/utils/looks-like-url.ts new file mode 100644 index 00000000..98c1d77e --- /dev/null +++ b/packages/editor/src/utils/looks-like-url.ts @@ -0,0 +1,31 @@ +export function looksLikeUrl(text: string) { + let looksLikeUrl = false + try { + try { + const url = new URL(text) + + if (!sensibleProtocols.includes(url.protocol)) { + return false + } + + const probablyHasTld = + url.hostname.length > 0 ? url.hostname.includes('.') : true + + looksLikeUrl = probablyHasTld + } catch { + const url = new URL(`https://${text}`) + + if (!sensibleProtocols.includes(url.protocol)) { + return false + } + + const probablyHasTld = + url.hostname.length > 0 ? url.hostname.includes('.') : true + + looksLikeUrl = probablyHasTld + } + } catch {} + return looksLikeUrl +} + +const sensibleProtocols = ['http:', 'https:', 'mailto:', 'tel:']