붙여넣기 시 url만 추출 기능 추가
parent
5b7eba9540
commit
e2b22bd8e9
|
|
@ -18,6 +18,23 @@ const isValidUrl = (string: string): boolean => {
|
|||
}
|
||||
};
|
||||
|
||||
// URL 형태로 판단되는 입력: 프로토콜/www. 시작 또는 도메인 형태(naver.me/xxx 등)
|
||||
const isUrlLike = (value: string): boolean => {
|
||||
const trimmed = value.trim();
|
||||
return /^(https?:\/\/|www\.)/i.test(trimmed)
|
||||
|| /^[a-z0-9-]+(\.[a-z0-9-]+)+([/?#]|$)/i.test(trimmed);
|
||||
};
|
||||
|
||||
const sanitizeUrlInput = (value: string): string => {
|
||||
return value.replace(/[^\x00-\x7F]/g, '');
|
||||
};
|
||||
|
||||
// 텍스트 안에 포함된 첫 번째 URL을 추출 (없으면 null)
|
||||
const extractUrl = (text: string): string | null => {
|
||||
const match = text.match(/(https?:\/\/|www\.)[^\s]+/i);
|
||||
return match ? match[0] : null;
|
||||
};
|
||||
|
||||
interface SearchInputFormProps {
|
||||
onAnalyze?: (value: string, type: SearchType) => void;
|
||||
onAutocomplete?: (data: AutocompleteRequest) => void;
|
||||
|
|
@ -142,6 +159,47 @@ const SearchInputForm: React.FC<SearchInputFormProps> = ({
|
|||
}
|
||||
};
|
||||
|
||||
const applyInputChange = (value: string) => {
|
||||
setInputValue(value);
|
||||
setSelectedItem(null);
|
||||
setHighlightedIndex(-1);
|
||||
hideOnInput(value);
|
||||
if (localError) setLocalError('');
|
||||
if (debounceRef.current) clearTimeout(debounceRef.current);
|
||||
if (isValidUrl(value)) {
|
||||
setAutocompleteResults([]);
|
||||
setShowAutocomplete(false);
|
||||
} else {
|
||||
debounceRef.current = setTimeout(() => handleAutocompleteSearch(value), 300);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {
|
||||
const pastedText = e.clipboardData.getData('text');
|
||||
|
||||
// 붙여넣은 텍스트에 URL이 포함되어 있고 URL 외 다른 텍스트도 있으면 URL만 추출해서 입력창에 넣기
|
||||
const extracted = extractUrl(pastedText);
|
||||
if (extracted && extracted !== pastedText.trim()) {
|
||||
e.preventDefault();
|
||||
applyInputChange(sanitizeUrlInput(extracted));
|
||||
return;
|
||||
}
|
||||
|
||||
const input = e.currentTarget;
|
||||
const start = input.selectionStart ?? inputValue.length;
|
||||
const end = input.selectionEnd ?? inputValue.length;
|
||||
const merged = inputValue.slice(0, start) + pastedText + inputValue.slice(end);
|
||||
|
||||
// 붙여넣은 후 완성될 전체 값이 URL 형태일 때만 비영문 문자 제거
|
||||
if (!isUrlLike(merged)) return;
|
||||
|
||||
const sanitized = sanitizeUrlInput(merged);
|
||||
if (sanitized === merged) return;
|
||||
|
||||
e.preventDefault();
|
||||
applyInputChange(sanitized);
|
||||
};
|
||||
|
||||
const handleManualButtonClick = () => {
|
||||
if (onManualButtonClick) {
|
||||
onManualButtonClick();
|
||||
|
|
@ -169,21 +227,8 @@ const SearchInputForm: React.FC<SearchInputFormProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
setInputValue(value);
|
||||
setSelectedItem(null);
|
||||
setHighlightedIndex(-1);
|
||||
hideOnInput(value);
|
||||
if (localError) setLocalError('');
|
||||
if (debounceRef.current) clearTimeout(debounceRef.current);
|
||||
if (isValidUrl(value)) {
|
||||
setAutocompleteResults([]);
|
||||
setShowAutocomplete(false);
|
||||
} else {
|
||||
debounceRef.current = setTimeout(() => handleAutocompleteSearch(value), 300);
|
||||
}
|
||||
}}
|
||||
onChange={(e) => applyInputChange(e.target.value)}
|
||||
onPaste={handlePaste}
|
||||
onFocus={() => {
|
||||
setIsFocused(true);
|
||||
if (autocompleteResults.length > 0) setShowAutocomplete(true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue