Przeglądaj źródła

正则表达式工具优化

zxlie 5 miesięcy temu
rodzic
commit
80580591c9
3 zmienionych plików z 127 dodań i 1 usunięć
  1. 54 0
      apps/regexp/index.css
  2. 17 1
      apps/regexp/index.html
  3. 56 0
      apps/regexp/index.js

+ 54 - 0
apps/regexp/index.css

@@ -565,3 +565,57 @@ pre {
     padding: 0 3px;
     padding: 0 3px;
     font-weight: normal;
     font-weight: normal;
 }
 }
+
+.visual-debugger-form select#visualRegexPreset {
+    min-width: 180px;
+    max-width: 260px;
+    padding: 0.5rem 0.8rem;
+    border: 1.5px solid #3498db;
+    border-radius: 4px;
+    font-size: 1rem;
+    background: #f8f9fa;
+    transition: border-color 0.2s;
+    margin-right: 0.5rem;
+}
+.visual-debugger-form select#visualRegexPreset:focus {
+    border-color: #2563eb;
+    background: #fff;
+}
+
+.visual-flags-group {
+    display: flex;
+    align-items: center;
+    gap: 0.5rem;
+    margin-left: 0.5rem;
+}
+.flag-btn {
+    display: flex;
+    align-items: center;
+    background: #f8f9fa;
+    border: 1.5px solid #3498db;
+    border-radius: 4px;
+    padding: 0.2rem 0.7rem;
+    font-size: 1rem;
+    cursor: pointer;
+    transition: background 0.2s, border-color 0.2s;
+    margin-right: 0.2rem;
+    user-select: none;
+    position: relative;
+}
+.flag-btn input[type="checkbox"] {
+    margin-right: 3px;
+}
+.flag-btn:hover {
+    background: #e6f0fa;
+    border-color: #2563eb;
+}
+.flag-btn input[type="checkbox"]:checked + span,
+.flag-btn input[type="checkbox"]:checked {
+    font-weight: bold;
+    color: #2563eb;
+}
+.flag-desc {
+    color: #888;
+    font-size: 0.92em;
+    margin-left: 0.5rem;
+}

+ 17 - 1
apps/regexp/index.html

@@ -23,8 +23,24 @@
             <section class="regex-visual-debugger">
             <section class="regex-visual-debugger">
                 <h2>正则表达式可视化调试</h2>
                 <h2>正则表达式可视化调试</h2>
                 <div class="visual-debugger-form">
                 <div class="visual-debugger-form">
+                    <select id="visualRegexPreset">
+                        <option value="">自定义/选择常用正则</option>
+                        <!-- 动态插入所有内置正则 -->
+                    </select>
                     <input type="text" id="visualRegex" placeholder="请输入正则表达式,如:^\\d{3}-\\d{8}$" />
                     <input type="text" id="visualRegex" placeholder="请输入正则表达式,如:^\\d{3}-\\d{8}$" />
-                    <input type="text" id="visualFlags" placeholder="标志(可选,如:gim)" maxlength="5" />
+                    <div class="visual-flags-group">
+                        <label class="flag-btn" title="g:全局匹配(查找所有匹配项)">
+                            <input type="checkbox" value="g" /> g
+                        </label>
+                        <label class="flag-btn" title="i:忽略大小写">
+                            <input type="checkbox" value="i" /> i
+                        </label>
+                        <label class="flag-btn" title="m:多行模式(^$作用于每行)">
+                            <input type="checkbox" value="m" /> m
+                        </label>
+                        <span class="flag-desc">常用标志:g=全局 i=忽略大小写 m=多行</span>
+                    </div>
+                    <input type="text" id="visualFlags" placeholder="标志(可选,如:gim)" maxlength="5" style="display:none;" />
                 </div>
                 </div>
                 <textarea id="visualTestText" rows="4" placeholder="请输入要测试的文本"></textarea>
                 <textarea id="visualTestText" rows="4" placeholder="请输入要测试的文本"></textarea>
                 <div class="visual-debugger-actions">
                 <div class="visual-debugger-actions">

+ 56 - 0
apps/regexp/index.js

@@ -678,6 +678,7 @@ function highlightMatchesV2(text, regex) {
 
 
 document.addEventListener('DOMContentLoaded', function() {
 document.addEventListener('DOMContentLoaded', function() {
     // 可视化调试相关
     // 可视化调试相关
+    const visualRegexPreset = document.getElementById('visualRegexPreset');
     const visualRegexInput = document.getElementById('visualRegex');
     const visualRegexInput = document.getElementById('visualRegex');
     const visualFlagsInput = document.getElementById('visualFlags');
     const visualFlagsInput = document.getElementById('visualFlags');
     const visualTestText = document.getElementById('visualTestText');
     const visualTestText = document.getElementById('visualTestText');
@@ -685,6 +686,51 @@ document.addEventListener('DOMContentLoaded', function() {
     const visualResult = document.getElementById('visualResult');
     const visualResult = document.getElementById('visualResult');
     const visualErrorMsg = document.getElementById('visualErrorMsg');
     const visualErrorMsg = document.getElementById('visualErrorMsg');
 
 
+    // 动态填充下拉框
+    if (visualRegexPreset) {
+        for (const key in regexDatabase) {
+            if (regexDatabase[key].patterns && regexDatabase[key].patterns.javascript) {
+                const option = document.createElement('option');
+                option.value = key;
+                option.textContent = regexDatabase[key].title;
+                option.setAttribute('data-regex', regexDatabase[key].patterns.javascript);
+                visualRegexPreset.appendChild(option);
+            }
+        }
+        // 标志按钮组与隐藏input联动
+        const flagCheckboxes = document.querySelectorAll('.visual-flags-group input[type="checkbox"]');
+        function updateFlagsInputFromCheckbox() {
+            let flags = '';
+            flagCheckboxes.forEach(cb => { if (cb.checked) flags += cb.value; });
+            visualFlagsInput.value = flags;
+            doVisualTest();
+        }
+        flagCheckboxes.forEach(cb => {
+            cb.addEventListener('change', updateFlagsInputFromCheckbox);
+        });
+        // input变化时同步按钮状态(如选择内置正则时)
+        function updateCheckboxFromFlagsInput() {
+            const flags = visualFlagsInput.value;
+            flagCheckboxes.forEach(cb => { cb.checked = flags.includes(cb.value); });
+        }
+        // 修改下拉选择逻辑,选择后同步按钮状态
+        visualRegexPreset.addEventListener('change', function() {
+            const selectedKey = this.value;
+            if (!selectedKey) return;
+            const patternRaw = regexDatabase[selectedKey].patterns.javascript;
+            const match = patternRaw.match(/^\/(.*)\/(\w*)$/);
+            if (match) {
+                visualRegexInput.value = match[1];
+                visualFlagsInput.value = match[2];
+            } else {
+                visualRegexInput.value = patternRaw;
+                visualFlagsInput.value = '';
+            }
+            updateCheckboxFromFlagsInput();
+            if (typeof doVisualTest === 'function') doVisualTest();
+        });
+    }
+
     function doVisualTest() {
     function doVisualTest() {
         let pattern = visualRegexInput.value.trim();
         let pattern = visualRegexInput.value.trim();
         let flags = visualFlagsInput.value.trim();
         let flags = visualFlagsInput.value.trim();
@@ -703,6 +749,13 @@ document.addEventListener('DOMContentLoaded', function() {
             visualErrorMsg.style.visibility = 'visible';
             visualErrorMsg.style.visibility = 'visible';
             return;
             return;
         }
         }
+        // 新增:如果测试文本为空,直接返回,不做匹配
+        if (!testText) {
+            visualResult.innerHTML = '';
+            visualErrorMsg.textContent = '';
+            visualErrorMsg.style.visibility = 'hidden';
+            return;
+        }
         let regex;
         let regex;
         try {
         try {
             regex = new RegExp(pattern, flags);
             regex = new RegExp(pattern, flags);
@@ -738,4 +791,7 @@ document.addEventListener('DOMContentLoaded', function() {
 
 
     // textarea内容变化时自动调试
     // textarea内容变化时自动调试
     visualTestText.addEventListener('input', doVisualTest);
     visualTestText.addEventListener('input', doVisualTest);
+
+    // 页面加载时同步一次
+    updateCheckboxFromFlagsInput();
 });
 });