Files
dns-things/index.html
dwindown e5195ba1f1 Initial commit: DNS Things - Comprehensive DNS utility website
Features implemented:
- Modular JavaScript architecture (theme.js, dns-tools.js, whois.js, punycode.js, ip-tools.js, main.js)
- Responsive design with dark/light theme toggle
- DNS Lookup and Reverse DNS Lookup tools
- Whois Lookup functionality
- IDN Punycode Converter with full Unicode support
- Comprehensive IP Address Tools (validation, IPv4-to-IPv6 mapping, IPv6 compression/expansion)
- Dynamic tab descriptions that change based on active tool
- Mobile-responsive horizontal scrollable tabs
- Copy-to-clipboard functionality for all results
- Clean footer with dynamic year
- IPv4-mapped IPv6 address explanation with clear warnings

Technical improvements:
- Separated concerns with modular JS files
- Fixed browser compatibility issues with punycode library
- Implemented proper error handling and user feedback
- Added comprehensive input validation
- Optimized for mobile devices with touch-friendly UI
2025-08-01 23:13:52 +07:00

293 lines
24 KiB
HTML

<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DNS Things</title>
<script src="https://cdn.tailwindcss.com"></script>
<!-- Punycode library for proper IDN conversion -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/punycode/2.3.1/punycode.min.js"></script>
<!-- Custom CSS -->
<link rel="stylesheet" href="assets/css/main.css">
<script>
tailwind.config = {
darkMode: 'class',
}
</script>
<style>
/* Simple transition for theme change */
body, .bg-white, .bg-gray-800, .text-gray-800, .text-white, .bg-gray-50, .bg-gray-700 {
transition: background-color 0.3s ease, color 0.3s ease;
}
.nav-link {
padding: 0.75rem;
border-radius: 0.375rem;
font-size: 0.875rem;
font-weight: 500;
color: #374151;
transition: background-color 0.15s ease-in-out;
}
.nav-link:hover {
background-color: #e5e7eb;
}
.dark .nav-link {
color: #d1d5db;
}
.dark .nav-link:hover {
background-color: #374151;
}
</style>
</head>
<body class="bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-200">
<!-- Header -->
<header class="fixed top-0 left-0 right-0 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm shadow-md z-50">
<nav class="container mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex-shrink-0">
<a href="#" class="text-2xl font-bold text-gray-800 dark:text-white">DNS Things</a>
</div>
<div class="hidden md:flex items-center space-x-4">
<a href="#your-ip" class="nav-link">Your IP</a>
<a href="#dns-lookup" class="nav-link">DNS Tools</a>
<button id="theme-toggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200">
<svg id="theme-toggle-light-icon" class="w-6 h-6 hidden" fill="currentColor" viewBox="0 0 20 20"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 5.05a1 1 0 00-1.414 1.414l.707.707a1 1 0 001.414-1.414l-.707-.707zM3 11a1 1 0 100-2H2a1 1 0 100 2h1z"></path></svg>
<svg id="theme-toggle-dark-icon" class="w-6 h-6 hidden" fill="currentColor" viewBox="0 0 20 20"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path></svg>
</button>
</div>
</div>
</nav>
</header>
<main class="pt-16">
<!-- Hero Section: Your IP -->
<section id="your-ip" class="py-16 md:py-20">
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 md:grid-cols-10 gap-8 items-start">
<div class="hidden md:flex md:col-span-4 items-start justify-center mt-12">
<img src="/assets/img/hero.webp" class="w-full h-auto max-w-md" alt="DNS Things">
</div>
<div class="w-full md:col-span-6 p-8 space-y-6 bg-white rounded-xl shadow-lg dark:bg-gray-800">
<div class="text-center">
<h1 class="text-4xl font-bold text-gray-800 dark:text-white">Your IP Address</h1>
<p class="text-gray-500 dark:text-gray-400">Your public IP addresses</p>
</div>
<div class="space-y-4">
<div class="p-4 bg-gray-50 rounded-lg dark:bg-gray-700">
<div class="flex justify-between items-center mb-1">
<label for="ipv4" class="text-sm font-medium text-gray-700 dark:text-gray-300">IPv4 Address</label>
<button data-copy-target="ipv4" class="copy-btn p-1 rounded-md hover:bg-gray-200 dark:hover:bg-gray-600"><span class="copy-icon"><svg class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg></span><span class="copy-feedback hidden text-sm text-green-600 dark:text-green-400">Copied!</span></button>
</div>
<div id="ipv4" class="p-2 w-full text-lg font-mono text-blue-600 bg-blue-100 rounded-md dark:bg-blue-900 dark:text-blue-300 break-all">loading...</div>
</div>
<div class="p-4 bg-gray-50 rounded-lg dark:bg-gray-700">
<div class="flex justify-between items-center mb-1">
<label for="ipv6" class="text-sm font-medium text-gray-700 dark:text-gray-300">IPv6 Address</label>
<button data-copy-target="ipv6" class="copy-btn p-1 rounded-md hover:bg-gray-200 dark:hover:bg-gray-600"><span class="copy-icon"><svg class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg></span><span class="copy-feedback hidden text-sm text-green-600 dark:text-green-400">Copied!</span></button>
</div>
<div id="ipv6" class="p-2 w-full text-lg font-mono text-purple-600 bg-purple-100 rounded-md dark:bg-purple-900 dark:text-purple-300 break-all">loading...</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- DNS Tools Section -->
<section id="dns-lookup" class="py-20 bg-white dark:bg-gray-800">
<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-12">
<h2 class="text-4xl font-bold text-gray-800 dark:text-white">DNS Tools</h2>
<p class="text-lg text-gray-500 dark:text-gray-400 mt-2">Various DNS utilities to help you analyze domains and IPs</p>
</div>
<div class="flex flex-col md:flex-row gap-8">
<!-- Vertical Tabs -->
<div class="w-full md:w-1/3 lg:w-1/4">
<div class="flex flex-col space-y-2 p-2 bg-gray-50 dark:bg-gray-700 rounded-lg">
<button class="tab-btn active p-3 text-left rounded-md font-medium text-indigo-600 dark:text-indigo-400 bg-white dark:bg-gray-800 shadow" data-tab="dns-lookup-tab">
DNS Lookup
</button>
<button class="tab-btn p-3 text-left rounded-md font-medium text-gray-600 dark:text-gray-300 hover:bg-white hover:dark:bg-gray-800/50" data-tab="reverse-dns-tab">
Reverse DNS Lookup
</button>
<button class="tab-btn p-3 text-left rounded-md font-medium text-gray-600 dark:text-gray-300 hover:bg-white hover:dark:bg-gray-800/50" data-tab="whois-tab">
Whois Lookup
</button>
<button class="tab-btn p-3 text-left rounded-md font-medium text-gray-600 dark:text-gray-300 hover:bg-white hover:dark:bg-gray-800/50" data-tab="punycode-tab">
IDN Punycode
</button>
<button class="tab-btn p-3 text-left rounded-md font-medium text-gray-600 dark:text-gray-300 hover:bg-white hover:dark:bg-gray-800/50" data-tab="ip-tools-tab">
IP Tools
</button>
</div>
</div>
<!-- Tab Content -->
<div class="w-full md:w-2/3 lg:w-3/4">
<!-- DNS Lookup Tab -->
<div id="dns-lookup-tab" class="tab-content active">
<h3 class="text-2xl font-semibold mb-4 text-gray-800 dark:text-white">DNS Lookup</h3>
<form id="dns-form" class="flex flex-col sm:flex-row gap-4">
<input type="text" id="domain-input" placeholder="e.g., google.com" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="submit" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Check DNS</button>
</form>
<div id="dns-results-container" class="mt-6"></div>
<div id="dns-loader" class="hidden text-center mt-8">
<p class="text-gray-600 dark:text-gray-300">Loading DNS records...</p>
</div>
</div>
<!-- Reverse DNS Tab -->
<div id="reverse-dns-tab" class="tab-content hidden">
<h3 class="text-2xl font-semibold mb-4 text-gray-800 dark:text-white">Reverse DNS Lookup</h3>
<form id="reverse-dns-form" class="flex flex-col sm:flex-row gap-4">
<input type="text" id="ip-input" placeholder="e.g., 8.8.8.8" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="submit" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Lookup</button>
</form>
<div id="reverse-dns-results" class="mt-6"></div>
<div id="reverse-dns-loader" class="hidden text-center mt-8">
<p class="text-gray-600 dark:text-gray-300">Looking up reverse DNS...</p>
</div>
</div>
<!-- Whois Lookup Tab -->
<div id="whois-tab" class="tab-content hidden">
<h3 class="text-2xl font-semibold mb-4 text-gray-800 dark:text-white">Whois Lookup</h3>
<form id="whois-form" class="flex flex-col sm:flex-row gap-4">
<input type="text" id="whois-input" placeholder="e.g., google.com" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="submit" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Lookup</button>
</form>
<div id="whois-results" class="mt-6"></div>
<div id="whois-loader" class="hidden text-center mt-8">
<p class="text-gray-600 dark:text-gray-300">Looking up domain information...</p>
</div>
</div>
<!-- IDN Punycode Converter Tab -->
<div id="punycode-tab" class="tab-content hidden">
<h3 class="text-2xl font-semibold mb-4 text-gray-800 dark:text-white">IDN Punycode Converter</h3>
<!-- Unicode to Punycode -->
<div class="mb-8">
<h4 class="text-lg font-medium mb-3 text-gray-800 dark:text-white">Unicode to Punycode</h4>
<div class="flex flex-col sm:flex-row gap-4">
<input type="text" id="unicode-input" placeholder="e.g., 中国.com, россия.рф, العربية.com" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="button" id="unicode-to-punycode-btn" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Convert</button>
</div>
<div id="punycode-result" class="mt-4"></div>
</div>
<!-- Punycode to Unicode -->
<div class="mb-6">
<h4 class="text-lg font-medium mb-3 text-gray-800 dark:text-white">Punycode to Unicode</h4>
<div class="flex flex-col sm:flex-row gap-4">
<input type="text" id="punycode-input" placeholder="e.g., xn--fiqs8s.com, xn--e1afmkfd.xn--p1ai" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="button" id="punycode-to-unicode-btn" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Convert</button>
</div>
<div id="unicode-result" class="mt-4"></div>
</div>
<!-- Examples -->
<div class="p-4 bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-lg">
<h4 class="font-medium mb-2">📚 Examples</h4>
<div class="text-sm space-y-1">
<div><strong>Chinese:</strong> 中国.com → xn--fiqs8s.com</div>
<div><strong>Russian:</strong> россия.рф → xn--e1afmkfd.xn--p1ai</div>
<div><strong>Arabic:</strong> العربية.com → xn--mgbqf7g0ndx.com</div>
<div><strong>Japanese:</strong> 日本.com → xn--wgbl6a.com</div>
</div>
</div>
</div>
<!-- IP Tools Tab -->
<div id="ip-tools-tab" class="tab-content hidden">
<h3 class="text-2xl font-semibold mb-4 text-gray-800 dark:text-white">IP Address Tools</h3>
<!-- IP Validation -->
<div class="mb-8">
<h4 class="text-lg font-medium mb-3 text-gray-800 dark:text-white">IP Address Validation</h4>
<div class="flex flex-col sm:flex-row gap-4">
<input type="text" id="ip-validate-input" placeholder="e.g., 192.168.1.1, 2001:db8::1" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="button" id="ip-validate-btn" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Validate</button>
</div>
<div id="ip-validate-result" class="mt-4"></div>
</div>
<!-- IPv4 to IPv6 Mapping -->
<div class="mb-8">
<h4 class="text-lg font-medium mb-3 text-gray-800 dark:text-white">IPv4 to IPv6 Mapping</h4>
<div class="flex flex-col sm:flex-row gap-4">
<input type="text" id="ipv4-to-ipv6-input" placeholder="e.g., 192.168.1.1" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="button" id="ipv4-to-ipv6-btn" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Convert</button>
</div>
<div id="ipv4-to-ipv6-result" class="mt-4"></div>
</div>
<!-- IPv6 Compression/Expansion -->
<div class="mb-8">
<h4 class="text-lg font-medium mb-3 text-gray-800 dark:text-white">IPv6 Compression/Expansion</h4>
<div class="flex flex-col sm:flex-row gap-4">
<input type="text" id="ipv6-compress-input" placeholder="e.g., 2001:0db8:0000:0000:0000:0000:0000:0001" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="button" id="ipv6-compress-btn" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Process</button>
</div>
<div id="ipv6-compress-result" class="mt-4"></div>
</div>
<!-- IP to Binary/Decimal -->
<div class="mb-8">
<h4 class="text-lg font-medium mb-3 text-gray-800 dark:text-white">IP to Binary/Decimal</h4>
<div class="flex flex-col sm:flex-row gap-4">
<input type="text" id="ip-binary-input" placeholder="e.g., 192.168.1.1" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="button" id="ip-binary-btn" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Convert</button>
</div>
<div id="ip-binary-result" class="mt-4"></div>
</div>
<!-- Subnet Calculator -->
<div class="mb-6">
<h4 class="text-lg font-medium mb-3 text-gray-800 dark:text-white">Subnet Calculator</h4>
<div class="flex flex-col sm:flex-row gap-4">
<input type="text" id="subnet-input" placeholder="e.g., 192.168.1.0/24" class="flex-1 px-4 py-3 rounded-lg bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" autocomplete="off" spellcheck="false" autocorrect="off" autocapitalize="off">
<button type="button" id="subnet-btn" class="bg-indigo-600 text-white font-bold px-6 py-3 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 whitespace-nowrap">Calculate</button>
</div>
<div id="subnet-result" class="mt-4"></div>
</div>
<!-- Examples -->
<div class="p-4 bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-lg">
<h4 class="font-medium mb-2">🔧 Examples</h4>
<div class="text-sm space-y-1">
<div><strong>IPv4:</strong> 192.168.1.1, 10.0.0.1, 172.16.0.1</div>
<div><strong>IPv6:</strong> 2001:db8::1, ::1, fe80::1</div>
<div><strong>CIDR:</strong> 192.168.1.0/24, 10.0.0.0/8</div>
<div><strong>IPv6 Full:</strong> 2001:0db8:0000:0000:0000:0000:0000:0001</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 py-6">
<p class="text-center text-sm text-gray-500">
&copy; <span id="current-year">2025</span> Dewe Toolsites - DNS Things.
</footer>
<!-- JavaScript Files -->
<script src="assets/js/theme.js"></script>
<script src="assets/js/dns-tools.js"></script>
<script src="assets/js/whois.js"></script>
<script src="assets/js/punycode.js"></script>
<script src="assets/js/ip-tools.js"></script>
<script src="assets/js/main.js"></script>
</body>
</html>