grain.social is a photo sharing platform built on atproto. grain.social
atproto photography appview
57
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: support Unicode characters in hashtag parsing

Hashtag regex only matched ASCII letters, so accented characters like
the á in #Bogotá were excluded. Switch to \p{L} and \p{N} Unicode
classes so hashtags with diacritics, CJK, Cyrillic, etc. are fully
matched and clickable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+3 -3
+1 -1
app/lib/components/atoms/RichText.svelte
··· 10 10 const urlRe = /https?:\/\/[^\s<>[\]()]+/g 11 11 const bareDomainRe = /(?<![/@\w.])([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(\/[^\s<>[\]()]*)?/g 12 12 const mentionRe = /@([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?/g 13 - const hashtagRe = /#([a-zA-Z][a-zA-Z0-9_]*)/g 13 + const hashtagRe = /#(\p{L}[\p{L}\p{N}_]*)/gu 14 14 15 15 function parse(input: string): Segment[] { 16 16 const segments: Segment[] = []
+1 -1
app/lib/components/atoms/RichTextarea.svelte
··· 2 2 const urlRe = /https?:\/\/[^\s<>[\]()]+/g 3 3 const bareDomainRe = /(?<![/@\w])([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(\/[^\s<>[\]()]*)?/g 4 4 const mentionRe = /@([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?/g 5 - const hashtagRe = /#([a-zA-Z][a-zA-Z0-9_]*)/g 5 + const hashtagRe = /#(\p{L}[\p{L}\p{N}_]*)/gu 6 6 7 7 let { 8 8 value = $bindable(''),
+1 -1
app/lib/utils/rich-text.ts
··· 75 75 } 76 76 77 77 // Hashtags 78 - const hashtagRegex = /#([a-zA-Z][a-zA-Z0-9_]*)/g; 78 + const hashtagRegex = /#(\p{L}[\p{L}\p{N}_]*)/gu; 79 79 let hashtagMatch; 80 80 while ((hashtagMatch = hashtagRegex.exec(text)) !== null) { 81 81 const start = hashtagMatch.index;