붙여넣기 시 url만 추출 기능 추가

main
김성경 2026-07-14 09:22:33 +09:00
parent 5b7eba9540
commit e2b22bd8e9
1 changed files with 60 additions and 15 deletions

View File

@ -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);