@fanboynz/network-scanner 1.0.67 → 1.0.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,713 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Regex Tools - Converter & Validator</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 1000px;
23
+ margin: 0 auto;
24
+ background: rgba(255, 255, 255, 0.95);
25
+ border-radius: 20px;
26
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
27
+ overflow: hidden;
28
+ }
29
+
30
+ .header {
31
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
32
+ color: white;
33
+ padding: 30px;
34
+ text-align: center;
35
+ }
36
+
37
+ .header h1 {
38
+ font-size: 2.5em;
39
+ margin-bottom: 10px;
40
+ animation: fadeInDown 0.5s ease;
41
+ }
42
+
43
+ .header p {
44
+ opacity: 0.9;
45
+ font-size: 1.1em;
46
+ }
47
+
48
+ .tabs {
49
+ display: flex;
50
+ background: #f7f9fc;
51
+ border-bottom: 2px solid #e2e8f0;
52
+ }
53
+
54
+ .tab {
55
+ flex: 1;
56
+ padding: 20px;
57
+ text-align: center;
58
+ cursor: pointer;
59
+ background: transparent;
60
+ border: none;
61
+ font-size: 1.1em;
62
+ font-weight: 600;
63
+ color: #64748b;
64
+ transition: all 0.3s ease;
65
+ position: relative;
66
+ }
67
+
68
+ .tab:hover {
69
+ background: rgba(102, 126, 234, 0.1);
70
+ }
71
+
72
+ .tab.active {
73
+ color: #667eea;
74
+ background: white;
75
+ }
76
+
77
+ .tab.active::after {
78
+ content: '';
79
+ position: absolute;
80
+ bottom: -2px;
81
+ left: 0;
82
+ right: 0;
83
+ height: 3px;
84
+ background: linear-gradient(90deg, #667eea, #764ba2);
85
+ animation: slideIn 0.3s ease;
86
+ }
87
+
88
+ .content {
89
+ padding: 40px;
90
+ min-height: 500px;
91
+ }
92
+
93
+ .tab-content {
94
+ display: none;
95
+ animation: fadeIn 0.3s ease;
96
+ }
97
+
98
+ .tab-content.active {
99
+ display: block;
100
+ }
101
+
102
+ .input-group {
103
+ margin-bottom: 30px;
104
+ }
105
+
106
+ .input-group label {
107
+ display: block;
108
+ margin-bottom: 10px;
109
+ font-weight: 600;
110
+ color: #334155;
111
+ font-size: 1.1em;
112
+ }
113
+
114
+ .input-group input[type="text"],
115
+ .input-group textarea {
116
+ width: 100%;
117
+ padding: 15px;
118
+ border: 2px solid #e2e8f0;
119
+ border-radius: 10px;
120
+ font-size: 1em;
121
+ font-family: 'Consolas', 'Monaco', monospace;
122
+ transition: all 0.3s ease;
123
+ }
124
+
125
+ .input-group input[type="text"]:focus,
126
+ .input-group textarea:focus {
127
+ outline: none;
128
+ border-color: #667eea;
129
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
130
+ }
131
+
132
+ .input-group textarea {
133
+ resize: vertical;
134
+ min-height: 100px;
135
+ }
136
+
137
+ .checkbox-group {
138
+ display: flex;
139
+ align-items: center;
140
+ margin-bottom: 20px;
141
+ }
142
+
143
+ .checkbox-group input[type="checkbox"] {
144
+ width: 20px;
145
+ height: 20px;
146
+ margin-right: 10px;
147
+ cursor: pointer;
148
+ }
149
+
150
+ .checkbox-group label {
151
+ cursor: pointer;
152
+ font-weight: 500;
153
+ color: #475569;
154
+ }
155
+
156
+ .button {
157
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
158
+ color: white;
159
+ border: none;
160
+ padding: 15px 40px;
161
+ border-radius: 10px;
162
+ font-size: 1.1em;
163
+ font-weight: 600;
164
+ cursor: pointer;
165
+ transition: all 0.3s ease;
166
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
167
+ }
168
+
169
+ .button:hover {
170
+ transform: translateY(-2px);
171
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
172
+ }
173
+
174
+ .button:active {
175
+ transform: translateY(0);
176
+ }
177
+
178
+ .output-section {
179
+ margin-top: 40px;
180
+ padding: 25px;
181
+ background: #f8fafc;
182
+ border-radius: 10px;
183
+ border: 2px solid #e2e8f0;
184
+ }
185
+
186
+ .output-section h3 {
187
+ margin-bottom: 15px;
188
+ color: #334155;
189
+ font-size: 1.3em;
190
+ }
191
+
192
+ .output-box {
193
+ background: white;
194
+ padding: 20px;
195
+ border-radius: 8px;
196
+ border: 1px solid #e2e8f0;
197
+ font-family: 'Consolas', 'Monaco', monospace;
198
+ margin-bottom: 20px;
199
+ word-break: break-all;
200
+ transition: all 0.3s ease;
201
+ }
202
+
203
+ .output-box:hover {
204
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
205
+ }
206
+
207
+ .examples-list {
208
+ list-style: none;
209
+ padding: 0;
210
+ }
211
+
212
+ .examples-list li {
213
+ background: white;
214
+ padding: 15px;
215
+ margin-bottom: 10px;
216
+ border-radius: 8px;
217
+ border-left: 4px solid #667eea;
218
+ font-family: 'Consolas', 'Monaco', monospace;
219
+ transition: all 0.3s ease;
220
+ }
221
+
222
+ .examples-list li:hover {
223
+ transform: translateX(5px);
224
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
225
+ }
226
+
227
+ .error {
228
+ background: #fee;
229
+ color: #c00;
230
+ padding: 15px;
231
+ border-radius: 8px;
232
+ border: 1px solid #fcc;
233
+ margin-top: 10px;
234
+ }
235
+
236
+ .success {
237
+ background: #e6fffa;
238
+ color: #047857;
239
+ padding: 15px;
240
+ border-radius: 8px;
241
+ border: 1px solid #6ee7b7;
242
+ margin-top: 10px;
243
+ }
244
+
245
+ @keyframes fadeIn {
246
+ from {
247
+ opacity: 0;
248
+ transform: translateY(10px);
249
+ }
250
+ to {
251
+ opacity: 1;
252
+ transform: translateY(0);
253
+ }
254
+ }
255
+
256
+ @keyframes fadeInDown {
257
+ from {
258
+ opacity: 0;
259
+ transform: translateY(-20px);
260
+ }
261
+ to {
262
+ opacity: 1;
263
+ transform: translateY(0);
264
+ }
265
+ }
266
+
267
+ @keyframes slideIn {
268
+ from {
269
+ transform: scaleX(0);
270
+ }
271
+ to {
272
+ transform: scaleX(1);
273
+ }
274
+ }
275
+
276
+ @media (max-width: 768px) {
277
+ .header h1 {
278
+ font-size: 1.8em;
279
+ }
280
+
281
+ .content {
282
+ padding: 20px;
283
+ }
284
+
285
+ .button {
286
+ width: 100%;
287
+ }
288
+ }
289
+ </style>
290
+ </head>
291
+ <body>
292
+ <div class="container">
293
+ <div class="header">
294
+ <h1>🔍 Regex Tools</h1>
295
+ <p>Convert and Validate Regular Expressions with Ease</p>
296
+ </div>
297
+
298
+ <div class="tabs">
299
+ <button class="tab active" onclick="switchTab('convert')">
300
+ 📝 Convert to JSON
301
+ </button>
302
+ <button class="tab" onclick="switchTab('validate')">
303
+ ✅ Validate Regex
304
+ </button>
305
+ </div>
306
+
307
+ <div class="content">
308
+ <!-- Convert Tab -->
309
+ <div id="convert" class="tab-content active">
310
+ <div class="input-group">
311
+ <label for="standardRegex">Enter Standard Regex Pattern:</label>
312
+ <input type="text" id="standardRegex" placeholder="e.g., ^https?://.*\.example\.com/.*$">
313
+ </div>
314
+
315
+ <button class="button" onclick="convertToJSON()">Convert to JSON</button>
316
+
317
+ <div id="convertOutput"></div>
318
+ </div>
319
+
320
+ <!-- Validate Tab -->
321
+ <div id="validate" class="tab-content">
322
+ <div class="checkbox-group" style="background: #f0f9ff; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #0ea5e9;">
323
+ <input type="checkbox" id="useStandardRegex" onchange="toggleRegexInput()">
324
+ <label for="useStandardRegex"><strong>✓ Check this box to validate Standard Regex</strong> (uncheck for JSON format)</label>
325
+ </div>
326
+
327
+ <div class="input-group">
328
+ <label for="regexToValidate">Enter Regex Pattern:</label>
329
+ <textarea id="regexToValidate" placeholder='⚠️ IMPORTANT: Check the box above if entering standard regex!&#10;&#10;For JSON (box unchecked): {"filterRegex": ["^https?:\\\\/\\\\/.*"]}&#10;For Standard (box checked): ^https?:\\/\\/.*'></textarea>
330
+ </div>
331
+
332
+ <button class="button" onclick="validateRegex()">Validate Regex</button>
333
+
334
+ <div id="validateOutput"></div>
335
+ </div>
336
+ </div>
337
+ </div>
338
+
339
+ <script>
340
+ function switchTab(tabName) {
341
+ // Update tabs
342
+ document.querySelectorAll('.tab').forEach(tab => {
343
+ tab.classList.remove('active');
344
+ });
345
+ event.target.classList.add('active');
346
+
347
+ // Update content
348
+ document.querySelectorAll('.tab-content').forEach(content => {
349
+ content.classList.remove('active');
350
+ });
351
+ document.getElementById(tabName).classList.add('active');
352
+ }
353
+
354
+ function toggleRegexInput() {
355
+ const checkbox = document.getElementById('useStandardRegex');
356
+ const textarea = document.getElementById('regexToValidate');
357
+
358
+ if (checkbox.checked) {
359
+ textarea.placeholder = 'Enter standard regex pattern, e.g., ^https?://.*';
360
+ } else {
361
+ textarea.placeholder = 'Enter JSON regex, e.g., {"pattern": "^https?://.*", "flags": "gi"}';
362
+ }
363
+ textarea.value = '';
364
+ }
365
+
366
+ function generateExamples(regex) {
367
+ const examples = [];
368
+
369
+ try {
370
+ // Get the pattern string
371
+ const pattern = regex.source || regex.pattern || regex.toString();
372
+
373
+ // Helper function to generate random string of specific length
374
+ function generateRandomString(minLen, maxLen) {
375
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-+=';
376
+ const length = maxLen ? Math.floor(Math.random() * (maxLen - minLen + 1)) + minLen : minLen;
377
+ let result = '';
378
+ for (let i = 0; i < length; i++) {
379
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
380
+ }
381
+ return result;
382
+ }
383
+
384
+ if (pattern.includes('http')) {
385
+ // Check for specific domain requirements
386
+ if (pattern.includes('com|org')) {
387
+ // Pattern requires .com or .org domains
388
+ const protocols = pattern.includes('https?') ? ['https://', 'http://'] : ['https://'];
389
+ const domains = ['example', 'test-site', 'web-app', 'api-server', 'my-service'];
390
+ const extensions = ['com', 'org'];
391
+
392
+ for (let i = 0; i < 5; i++) {
393
+ const protocol = protocols[i % protocols.length];
394
+ const domain = domains[i % domains.length];
395
+ const ext = extensions[i % extensions.length];
396
+
397
+ // Build the path part
398
+ let path = '';
399
+
400
+ // Check for specific length requirements in path
401
+ const pathMatch = pattern.match(/\[A-Za-z0-9[^\]]*\]\{(\d+),?(\d*)\}/);
402
+ if (pathMatch) {
403
+ const minLen = parseInt(pathMatch[1]);
404
+ const maxLen = pathMatch[2] ? parseInt(pathMatch[2]) : minLen + 20;
405
+ path = generateRandomString(minLen, maxLen);
406
+ } else {
407
+ path = 'api/v1/users/profile/data';
408
+ }
409
+
410
+ let url = `${protocol}${domain}.${ext}/${path}`;
411
+
412
+ // Add query params if pattern requires them
413
+ if (pattern.includes('\\?')) {
414
+ // Check for minimum length requirements in query
415
+ const queryMatch = pattern.match(/\\\?\.\{(\d+),?(\d*)\}/);
416
+ if (queryMatch) {
417
+ const minLen = parseInt(queryMatch[1]);
418
+ const maxLen = queryMatch[2] ? parseInt(queryMatch[2]) : minLen + 10;
419
+ url += '?' + generateRandomString(minLen, maxLen);
420
+ } else if (pattern.match(/\?\.\{(\d+),/)) {
421
+ // Handle any {n,} pattern after ?
422
+ const match = pattern.match(/\?\.\{(\d+),/);
423
+ const minLen = parseInt(match[1]);
424
+ url += '?param=' + generateRandomString(Math.max(minLen - 6, 1), minLen + 15);
425
+ } else {
426
+ url += '?param=value&key=data';
427
+ }
428
+ } else if (pattern.includes('&.{')) {
429
+ // Handle &.{n,} case
430
+ const ampMatch = pattern.match(/&\.\{(\d+),/);
431
+ if (ampMatch) {
432
+ const minLen = parseInt(ampMatch[1]);
433
+ url += '&' + generateRandomString(minLen, minLen + 15);
434
+ }
435
+ }
436
+
437
+ examples.push(url);
438
+ }
439
+ } else {
440
+ // General URL patterns
441
+ const protocols = pattern.includes('https?') ? ['http://', 'https://'] : ['https://'];
442
+ const urls = [
443
+ 'www.example.com/path/to/resource',
444
+ 'subdomain.test.com/api/endpoint',
445
+ 'example.org/page/section/item',
446
+ 'demo.net/products/category',
447
+ 'sample.io/user/profile/settings'
448
+ ];
449
+
450
+ urls.forEach((url, i) => {
451
+ if (i < 5) {
452
+ let fullUrl = protocols[i % protocols.length] + url;
453
+
454
+ // Check for length requirements
455
+ const lengthMatch = pattern.match(/\{(\d+),?(\d*)\}/);
456
+ if (lengthMatch && !pattern.includes('\\?')) {
457
+ const minLen = parseInt(lengthMatch[1]);
458
+ const maxLen = lengthMatch[2] ? parseInt(lengthMatch[2]) : minLen + 10;
459
+ fullUrl += '/' + generateRandomString(minLen, maxLen);
460
+ }
461
+
462
+ examples.push(fullUrl);
463
+ }
464
+ });
465
+ }
466
+
467
+ // Test all generated examples against the regex
468
+ const validExamples = [];
469
+ for (const example of examples) {
470
+ try {
471
+ // Reset regex lastIndex in case of global flag
472
+ regex.lastIndex = 0;
473
+ if (regex.test(example)) {
474
+ validExamples.push(example);
475
+ }
476
+ } catch (e) {
477
+ console.error('Error testing example:', e);
478
+ }
479
+ }
480
+
481
+ // If we don't have enough valid examples, try more specific ones with proper lengths
482
+ if (validExamples.length < 5) {
483
+ const moreSpecific = [];
484
+ for (let i = 0; i < 10; i++) {
485
+ const protocol = i % 2 === 0 ? 'https://' : 'http://';
486
+ const domain = ['test-api', 'web-server', 'my-app', 'demo-site', 'api-gateway'][i % 5];
487
+ const ext = i % 2 === 0 ? 'com' : 'org';
488
+
489
+ // Generate path with proper length if specified
490
+ let path = 'Path_';
491
+ const pathMatch = pattern.match(/\[A-Za-z0-9[^\]]*\]\{(\d+),?(\d*)\}/);
492
+ if (pathMatch) {
493
+ const minLen = parseInt(pathMatch[1]);
494
+ const maxLen = pathMatch[2] ? parseInt(pathMatch[2]) : minLen + 20;
495
+ path = generateRandomString(minLen, maxLen);
496
+ } else {
497
+ path += generateRandomString(10, 30);
498
+ }
499
+
500
+ let url = `${protocol}${domain}.${ext}/${path}`;
501
+
502
+ // Add query with proper length if needed
503
+ if (pattern.includes('\\?')) {
504
+ const queryMatch = pattern.match(/\\\?\.\{(\d+),?(\d*)\}/);
505
+ if (queryMatch) {
506
+ const minLen = parseInt(queryMatch[1]);
507
+ url += '?q=' + generateRandomString(Math.max(minLen - 2, 1), minLen + 10);
508
+ } else if (pattern.match(/\?\.\{(\d+),/)) {
509
+ const match = pattern.match(/\?\.\{(\d+),/);
510
+ const minLen = parseInt(match[1]);
511
+ url += '?' + generateRandomString(minLen, minLen + 15);
512
+ } else {
513
+ url += '?param=' + generateRandomString(10, 20);
514
+ }
515
+ } else if (pattern.includes('&.{')) {
516
+ const ampMatch = pattern.match(/&\.\{(\d+),/);
517
+ if (ampMatch) {
518
+ const minLen = parseInt(ampMatch[1]);
519
+ url += '&' + generateRandomString(minLen, minLen + 15);
520
+ }
521
+ }
522
+
523
+ moreSpecific.push(url);
524
+ }
525
+
526
+ for (const url of moreSpecific) {
527
+ regex.lastIndex = 0;
528
+ if (regex.test(url) && validExamples.length < 5) {
529
+ validExamples.push(url);
530
+ }
531
+ }
532
+ }
533
+
534
+ return validExamples.length > 0 ? validExamples.slice(0, 5) : [
535
+ 'Pattern is very specific - generating custom examples...',
536
+ 'Try: https://example.com/Page_Name/path?query=value12345',
537
+ 'Try: http://test.org/API_endpoint/data?param=longvalue123',
538
+ 'Manual testing recommended for this pattern',
539
+ 'Validation successful'
540
+ ];
541
+ } else if (pattern.includes('@')) {
542
+ examples.push(
543
+ 'user@example.com',
544
+ 'john.doe@company.org',
545
+ 'admin+tag@subdomain.example.com',
546
+ 'contact@business.co.uk',
547
+ 'support123@service.io'
548
+ );
549
+ } else if (pattern.includes('\\d')) {
550
+ // Check for length requirements
551
+ const lengthMatch = pattern.match(/\{(\d+),?(\d*)\}/);
552
+ if (lengthMatch) {
553
+ const minLen = parseInt(lengthMatch[1]);
554
+ const maxLen = lengthMatch[2] ? parseInt(lengthMatch[2]) : minLen + 10;
555
+ for (let i = 0; i < 5; i++) {
556
+ examples.push(generateRandomString(minLen, maxLen));
557
+ }
558
+ } else {
559
+ examples.push(
560
+ '12345',
561
+ '2024-01-15',
562
+ 'ID-9876-XY',
563
+ 'Version 3.14.159',
564
+ 'Order #00425'
565
+ );
566
+ }
567
+ } else if (pattern.includes('\\w')) {
568
+ // Check for length requirements
569
+ const lengthMatch = pattern.match(/\{(\d+),?(\d*)\}/);
570
+ if (lengthMatch) {
571
+ const minLen = parseInt(lengthMatch[1]);
572
+ const maxLen = lengthMatch[2] ? parseInt(lengthMatch[2]) : minLen + 10;
573
+ for (let i = 0; i < 5; i++) {
574
+ examples.push(generateRandomString(minLen, maxLen));
575
+ }
576
+ } else {
577
+ examples.push(
578
+ 'HelloWorld',
579
+ 'user_name_123',
580
+ 'CamelCaseExample',
581
+ );
582
+ }
583
+ } else {
584
+ // Check for any length requirements in the pattern
585
+ const lengthMatch = pattern.match(/\{(\d+),?(\d*)\}/);
586
+ if (lengthMatch) {
587
+ const minLen = parseInt(lengthMatch[1]);
588
+ const maxLen = lengthMatch[2] ? parseInt(lengthMatch[2]) : minLen + 15;
589
+ for (let i = 0; i < 5; i++) {
590
+ examples.push(generateRandomString(minLen, maxLen));
591
+ }
592
+ } else {
593
+ // Generic examples
594
+ examples.push(
595
+ 'example text',
596
+ 'Sample String 123',
597
+ 'test-data-here',
598
+ 'Another_Example',
599
+ 'final.test.value'
600
+ );
601
+ }
602
+ }
603
+
604
+ // Filter examples that actually match the regex
605
+ const validExamples = examples.filter(ex => {
606
+ try {
607
+ regex.lastIndex = 0;
608
+ return regex.test(ex);
609
+ } catch {
610
+ return false;
611
+ }
612
+ });
613
+
614
+ return validExamples.length > 0 ? validExamples.slice(0, 5) : [
615
+ 'No automatic examples could be generated.',
616
+ 'The pattern may be too specific.',
617
+ 'Try testing with your own strings.',
618
+ 'Enter test strings manually.',
619
+ 'Pattern validation successful.'
620
+ ];
621
+ } catch (error) {
622
+ console.error('Error in generateExamples:', error);
623
+ return ['Error generating examples'];
624
+ }
625
+ }
626
+
627
+ function convertToJSON() {
628
+ const standardRegex = document.getElementById('standardRegex').value;
629
+ const outputDiv = document.getElementById('convertOutput');
630
+
631
+ if (!standardRegex) {
632
+ outputDiv.innerHTML = '<div class="error">Please enter a regex pattern</div>';
633
+ return;
634
+ }
635
+
636
+ try {
637
+ // Remove surrounding quotes if present
638
+ let cleanPattern = standardRegex.trim();
639
+ if ((cleanPattern.startsWith('"') && cleanPattern.endsWith('"')) ||
640
+ (cleanPattern.startsWith("'") && cleanPattern.endsWith("'"))) {
641
+ cleanPattern = cleanPattern.slice(1, -1);
642
+ }
643
+
644
+ // Test if the regex is valid first (using the cleaned pattern)
645
+ const testRegex = new RegExp(cleanPattern);
646
+
647
+ // For JSON string format: the input pattern stays as is
648
+ // JSON.stringify will handle the escaping
649
+ const jsonOutput = {
650
+ filterRegex: [cleanPattern]
651
+ };
652
+
653
+ // Generate examples
654
+ const examples = generateExamples(testRegex);
655
+
656
+ outputDiv.innerHTML = `
657
+ <div class="output-section">
658
+ <h3>📋 JSON Output:</h3>
659
+ <div class="output-box">${JSON.stringify(jsonOutput, null, 2)}</div>
660
+
661
+ <h3>✨ Example Matches:</h3>
662
+ <ul class="examples-list">
663
+ ${examples.map(ex => `<li>${escapeHtml(ex)}</li>`).join('')}
664
+ </ul>
665
+
666
+ <div class="success">✅ Regex successfully converted to JSON format!</div>
667
+ </div>
668
+ `;
669
+ } catch (error) {
670
+ outputDiv.innerHTML = `<div class="error">❌ Invalid regex pattern: ${escapeHtml(error.message)}</div>`;
671
+ }
672
+ }
673
+
674
+ function validatandard ? 'Standard Regex' : 'JSON Regex'}
675
+ </div>
676
+
677
+ <h3>✨ Example Matches:</h3>
678
+ <ul class="examples-list">
679
+ ${examples.map(ex => `<li>${escapeHtml(ex)}</li>`).join('')}
680
+ </ul>
681
+
682
+ <div class="success">✅ Regex is valid!</div>
683
+ </div>
684
+ `;
685
+ } catch (error) {
686
+ if (error instanceof SyntaxError && !useStandard) {
687
+ outputDiv.innerHTML = `<div class="error">❌ Invalid JSON syntax: ${escapeHtml(error.message)}<br><br>Expected format: {"filterRegex": ["your-regex-pattern"]} or "your-regex-pattern"</div>`;
688
+ } else {
689
+ outputDiv.innerHTML = `<div class="error">❌ Invalid regex: ${escapeHtml(error.message)}</div>`;
690
+ }
691
+ }
692
+ }
693
+
694
+ function escapeHtml(text) {
695
+ const div = document.createElement('div');
696
+ div.textContent = text;
697
+ return div.innerHTML;
698
+ }
699
+
700
+ // Add enter key support
701
+ document.getElementById('standardRegex').addEventListener('keypress', function(e) {
702
+ if (e.key === 'Enter') convertToJSON();
703
+ });
704
+
705
+ document.getElementById('regexToValidate').addEventListener('keypress', function(e) {
706
+ if (e.key === 'Enter' && !e.shiftKey) {
707
+ e.preventDefault();
708
+ validateRegex();
709
+ }
710
+ });
711
+ </script>
712
+ </body>
713
+ </html>