1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
// Regex from the go implementation
// https://github.com/bluesky-social/indigo/blob/main/atproto/syntax/handle.go#L10
import {forceLTR} from '#/lib/strings/bidi'
const VALIDATE_REGEX =
/^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/
export function makeValidHandle(str: string): string {
if (str.length > 20) {
str = str.slice(0, 20)
}
str = str.toLowerCase()
return str.replace(/^[^a-z0-9]+/g, '').replace(/[^a-z0-9-]/g, '')
}
export function createFullHandle(name: string, domain: string): string {
name = (name || '').replace(/[.]+$/, '')
domain = (domain || '').replace(/^[.]+/, '')
return `${name}.${domain}`
}
export function maxServiceHandleLength(domain: string): number {
return 30 - `.${(domain || '').replace(/^[.]+/, '')}`.length
}
export function isInvalidHandle(handle: string): boolean {
return handle === 'handle.invalid'
}
export function sanitizeHandle(handle: string, prefix = ''): string {
return isInvalidHandle(handle)
? '⚠Invalid Handle'
: forceLTR(`${prefix}${handle}`)
}
export interface IsValidHandle {
handleChars: boolean
hyphenStartOrEnd: boolean
frontLength: boolean
totalLength: boolean
overall: boolean
}
// More checks from https://github.com/bluesky-social/atproto/blob/main/packages/pds/src/handle/index.ts#L72
export function validateServiceHandle(
str: string,
userDomain: string,
): IsValidHandle {
const fullHandle = createFullHandle(str, userDomain)
const results = {
handleChars:
!str || (VALIDATE_REGEX.test(fullHandle) && !str.includes('.')),
hyphenStartOrEnd: !str.startsWith('-') && !str.endsWith('-'),
frontLength: str.length >= 3 && str.length <= 18,
totalLength: fullHandle.length <= 253,
}
return {
...results,
overall: !Object.values(results).includes(false),
}
}
|