diff --git a/src/lib/moderation/create-sanitized-display-name.ts b/src/lib/moderation/create-sanitized-display-name.ts index 16135b27..5863503f 100644 --- a/src/lib/moderation/create-sanitized-display-name.ts +++ b/src/lib/moderation/create-sanitized-display-name.ts @@ -12,10 +12,6 @@ export function createSanitizedDisplayName( if (profile.displayName != null && profile.displayName !== '') { return sanitizeDisplayName(profile.displayName) } else { - let sanitizedHandle = sanitizeHandle(profile.handle) - if (!noAt) { - sanitizedHandle = `@${sanitizedHandle}` - } - return sanitizedHandle + return sanitizeHandle(profile.handle, noAt ? '' : '@') } } diff --git a/src/lib/strings/bidi.ts b/src/lib/strings/bidi.ts new file mode 100644 index 00000000..790c2b6a --- /dev/null +++ b/src/lib/strings/bidi.ts @@ -0,0 +1,10 @@ +const LEFT_TO_RIGHT_EMBEDDING = '\u202A' +const POP_DIRECTIONAL_FORMATTING = '\u202C' + +/* + * Force LTR directionality in a string. + * https://www.unicode.org/reports/tr9/#Directional_Formatting_Characters + */ +export function forceLTR(str: string) { + return LEFT_TO_RIGHT_EMBEDDING + str + POP_DIRECTIONAL_FORMATTING +} diff --git a/src/lib/strings/handles.ts b/src/lib/strings/handles.ts index bc07b32e..7955e1b2 100644 --- a/src/lib/strings/handles.ts +++ b/src/lib/strings/handles.ts @@ -1,5 +1,7 @@ // 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])?$/ @@ -22,7 +24,9 @@ export function isInvalidHandle(handle: string): boolean { } export function sanitizeHandle(handle: string, prefix = ''): string { - return isInvalidHandle(handle) ? '⚠Invalid Handle' : `${prefix}${handle}` + return isInvalidHandle(handle) + ? '⚠Invalid Handle' + : forceLTR(`${prefix}${handle}`) } export interface IsValidHandle { diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx index 3f855c33..aec787e4 100644 --- a/src/view/com/util/PostMeta.tsx +++ b/src/view/com/util/PostMeta.tsx @@ -32,6 +32,8 @@ interface PostMetaOpts { style?: StyleProp } +const NON_BREAKING_SPACE = '\u00A0' + let PostMeta = (opts: PostMetaOpts): React.ReactNode => { const pal = usePalette('default') const displayName = opts.author.displayName || opts.author.handle @@ -83,7 +85,7 @@ let PostMeta = (opts: PostMetaOpts): React.ReactNode => { type="md" disableMismatchWarning style={[pal.textLight, {flexShrink: 4}]} - text={'\xa0' + sanitizeHandle(handle, '@')} + text={NON_BREAKING_SPACE + sanitizeHandle(handle, '@')} href={profileLink} onBeforePress={onBeforePressAuthor} anchorNoUnderline