'use client'; import React, { useState, useEffect } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faKey, faCopy, faCheck, faExclamationTriangle, faInfoCircle, faTrash } from '@fortawesome/free-solid-svg-icons'; import ToolHeader from '@/components/ToolHeader'; import { useLanguage } from '@/context/LanguageContext'; // 添加CSS变量样式 const styles = { card: "card p-4", input: "search-input w-full", secondaryBtn: "btn-secondary", primaryText: "text-primary", secondaryText: "text-secondary", tertiaryText: "text-tertiary", block: "bg-block", codeBlock: "bg-block px-1 rounded", iconButton: "text-tertiary hover:text-purple transition-colors", selectedFlag: "bg-purple-glow/20 text-purple", buttonActive: "px-3 py-1 text-xs rounded-md transition-all bg-gradient-to-r from-[rgb(var(--color-primary))] to-[rgb(var(--color-primary-hover))] text-white shadow-sm shadow-[rgba(var(--color-primary),0.3)]", buttonInactive: "px-3 py-1 text-xs rounded-md transition-all btn-secondary", error: "text-error", highlightBg: "bg-purple-500/30 text-white font-medium", } // 定义匹配项类型 type MatchResult = RegExpExecArray; type MatchResultArray = MatchResult[]; export default function RegexTester() { const { t } = useLanguage(); // 正则表达式输入 const [regexString, setRegexString] = useState(''); const [flags, setFlags] = useState('g'); const [testString, setTestString] = useState(''); // 测试结果 const [matches, setMatches] = useState([]); const [matchCount, setMatchCount] = useState(0); // 高级选项 const [showGroups, setShowGroups] = useState(true); const [regexError, setRegexError] = useState(null); // 复制状态 const [copiedRegex, setCopiedRegex] = useState(false); // 安全处理HTML转义 const escapeHtml = (text: string) => { if (text === undefined || text === null) return ''; return String(text) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }; // 常用正则表达式示例 const examples = [ { name: t('tools.regex_tester.examples.email'), pattern: '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}', flags: 'g', testText: 'test@example.com, invalid-email, another.email@domain.co.uk' }, { name: t('tools.regex_tester.examples.phone'), pattern: '1[3-9]\\d{9}', flags: 'g', testText: t('tools.regex_tester.example_texts.phone') }, { name: t('tools.regex_tester.examples.url'), pattern: 'https?://[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&//=]*)', flags: 'g', testText: t('tools.regex_tester.example_texts.url') }, { name: t('tools.regex_tester.examples.ip'), pattern: '\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b', flags: 'g', testText: t('tools.regex_tester.example_texts.ip') }, { name: t('tools.regex_tester.examples.chinese'), pattern: '[\\u4e00-\\u9fa5]', flags: 'g', testText: t('tools.regex_tester.example_texts.chinese') }, ]; // 当输入改变时更新测试结果 useEffect(() => { testRegex(); }, [regexString, flags, testString, showGroups]); // 测试正则表达式 const testRegex = () => { if (!regexString || !testString) { setMatches([]); setMatchCount(0); setRegexError(null); return; } try { // 验证正则表达式是否有效 new RegExp(regexString, flags); setRegexError(null); if (flags.includes('g')) { // 获取所有匹配 const allMatches: MatchResultArray = []; let match: RegExpExecArray | null; const regexWithGroups = new RegExp(regexString, flags); // 收集所有匹配和捕获组 while ((match = regexWithGroups.exec(testString)) !== null) { allMatches.push(match); // 防止无限循环,如果匹配长度为0,手动增加索引 if (match.index === regexWithGroups.lastIndex) { regexWithGroups.lastIndex++; } } setMatches(allMatches); setMatchCount(allMatches.length); } else { // 单次匹配模式 const regexWithoutG = new RegExp(regexString, flags.replace('g', '')); const execMatch = regexWithoutG.exec(testString); if (execMatch) { setMatches([execMatch]); setMatchCount(1); } else { setMatches([]); setMatchCount(0); } } } catch (error) { console.error(t('tools.regex_tester.regex_error'), error); setRegexError((error as Error).message); setMatches([]); setMatchCount(0); } }; // 复制正则表达式 const copyRegex = () => { const regexText = `/${regexString}/${flags}`; navigator.clipboard.writeText(regexText) .then(() => { setCopiedRegex(true); setTimeout(() => setCopiedRegex(false), 2000); }) .catch(err => console.error(t('tools.regex_tester.copy_failed'), err)); }; // 应用示例 const applyExample = (example: { pattern: string; flags: string; testText: string }) => { setRegexString(example.pattern); setFlags(example.flags); setTestString(example.testText); }; // 清空所有内容 const clearAll = () => { setRegexString(''); setFlags('g'); setTestString(''); setMatches([]); setMatchCount(0); setRegexError(null); }; // 切换标志位 const toggleFlag = (flag: string) => { if (flags.includes(flag)) { setFlags(flags.replace(flag, '')); } else { setFlags(flags + flag); } }; return (
{/* 主内容区 */}
{/* 左侧面板 - 正则表达式输入和选项 */}
{/* 常用示例 */}

{t('tools.regex_tester.examples.title')}

{examples.map((example, index) => ( ))}
{/* 正则选项 */}

{t('tools.regex_tester.options')}

{/* 右侧面板 - 测试区域 */}
{/* 正则表达式输入 */}

{t('tools.regex_tester.regex_expression')}

/
setRegexString(e.target.value)} placeholder={t('tools.regex_tester.enter_regex')} className="search-input pl-7 pr-14" />
/
setFlags(e.target.value)} placeholder="flags" className="absolute right-3 top-[13px] w-8 bg-transparent border-none outline-none text-tertiary" />
{regexError && (
{regexError}
)}
{/* 测试输入 */}

{t('tools.regex_tester.test_text')}

{t('tools.regex_tester.character_count')}: {testString.length}