clean up sanitization
This commit is contained in:
@@ -23,7 +23,7 @@ import {useStores} from 'state/index'
|
||||
import {ActivityIndicator} from 'react-native'
|
||||
import {TagInputEntryButton} from './TagInputEntryButton'
|
||||
import {uniq} from 'lib/strings/helpers'
|
||||
import {sanitizeHashtag} from './util'
|
||||
import {sanitizeHashtag, sanitizeHashtagOnChange} from './util'
|
||||
|
||||
export function TagInput({
|
||||
max = 8,
|
||||
@@ -103,12 +103,14 @@ export function TagInput({
|
||||
)
|
||||
|
||||
const onChangeText = React.useCallback(
|
||||
async (v: string) => {
|
||||
setValue(v)
|
||||
async (value: string) => {
|
||||
const tag = sanitizeHashtagOnChange(value)
|
||||
|
||||
if (v.length > 0) {
|
||||
setValue(tag)
|
||||
|
||||
if (tag.length > 0) {
|
||||
model.setActive(true)
|
||||
await model.search(v)
|
||||
await model.search(tag)
|
||||
|
||||
setSuggestions(model.suggestions)
|
||||
} else {
|
||||
|
||||
@@ -23,7 +23,7 @@ import {useStores} from 'state/index'
|
||||
import {TagInputEntryButton} from './TagInputEntryButton'
|
||||
import {TextInputFocusEventData} from 'react-native'
|
||||
import {uniq} from 'lib/strings/helpers'
|
||||
import {sanitizeHashtag} from './util'
|
||||
import {sanitizeHashtag, sanitizeHashtagOnChange} from './util'
|
||||
|
||||
export function TagInput({
|
||||
max = 8,
|
||||
@@ -153,12 +153,14 @@ export function TagInput({
|
||||
)
|
||||
|
||||
const onChangeText = React.useCallback(
|
||||
async (v: string) => {
|
||||
setValue(v)
|
||||
async (value: string) => {
|
||||
const tag = sanitizeHashtagOnChange(value)
|
||||
|
||||
if (v.length > 0) {
|
||||
setValue(tag)
|
||||
|
||||
if (tag.length > 0) {
|
||||
model.setActive(true)
|
||||
await model.search(v)
|
||||
await model.search(tag)
|
||||
|
||||
setDropdownItems(
|
||||
model.suggestions.map(item => ({
|
||||
@@ -199,9 +201,10 @@ export function TagInput({
|
||||
(!target || !target.id.includes('tag_autocomplete_option'))
|
||||
) {
|
||||
setOpen(false)
|
||||
setValue('')
|
||||
}
|
||||
},
|
||||
[tags, setOpen],
|
||||
[tags, setOpen, setValue],
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
import {TRAILING_PUNCTUATION_REGEX, LEADING_HASH_REGEX} from '@atproto/api'
|
||||
import {
|
||||
HASHTAG_INVALID_CHARACTER_REGEX,
|
||||
TRAILING_PUNCTUATION_REGEX,
|
||||
LEADING_PUNCTUATION_REGEX,
|
||||
LEADING_NUMBER_REGEX,
|
||||
} from '@atproto/api'
|
||||
|
||||
export function sanitizeHashtag(tagString: string) {
|
||||
return tagString
|
||||
.trim()
|
||||
.replace(LEADING_HASH_REGEX, '')
|
||||
/**
|
||||
* Trims leading numbers, all invalid characters, and any trailing punctuation.
|
||||
*/
|
||||
export function sanitizeHashtag(hashtag: string) {
|
||||
return hashtag
|
||||
.replace(LEADING_PUNCTUATION_REGEX, '')
|
||||
.replace(LEADING_NUMBER_REGEX, '')
|
||||
.replace(HASHTAG_INVALID_CHARACTER_REGEX, '')
|
||||
.replace(TRAILING_PUNCTUATION_REGEX, '')
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims leading numbers and all invalid charactes, but ignores trailing
|
||||
* punctuation in case the user intends to use `_` or `-`.
|
||||
*/
|
||||
export function sanitizeHashtagOnChange(hashtag: string) {
|
||||
return hashtag
|
||||
.replace(LEADING_PUNCTUATION_REGEX, '')
|
||||
.replace(LEADING_NUMBER_REGEX, '')
|
||||
.replace(HASHTAG_INVALID_CHARACTER_REGEX, '')
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ export function getHashtagAt(text: string, position: number) {
|
||||
* show autocomplete after a single # is typed
|
||||
* AND the cursor is next to the #
|
||||
*/
|
||||
for (const match of Array.from(text.matchAll(LEADING_HASH_REGEX))) {
|
||||
for (const match of Array.from(
|
||||
text.matchAll(new RegExp(LEADING_HASH_REGEX, 'g')),
|
||||
)) {
|
||||
const {index} = match
|
||||
if (index === undefined) continue
|
||||
if (position >= index && position <= index + 1) {
|
||||
|
||||
Reference in New Issue
Block a user