Files
dns-things/assets/js/punycode.js
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

177 lines
7.4 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// DNS Things - Punycode Module
// Real Punycode conversion functions using punycode.js library
function toPunycode(domain) {
try {
// Check if punycode library is available
if (typeof punycode === 'undefined') {
throw new Error('Punycode library not loaded');
}
// Split domain into parts and convert each part
const parts = domain.split('.');
const convertedParts = parts.map(part => {
// Check if part contains non-ASCII characters
if (/[^\x00-\x7F]/.test(part)) {
return punycode.toASCII(part);
}
return part;
});
return convertedParts.join('.');
} catch (error) {
// Fallback to URL API if punycode library fails
try {
const url = new URL(`http://${domain}`);
return url.hostname;
} catch {
throw new Error('Invalid domain format');
}
}
}
function fromPunycode(domain) {
try {
// Check if domain contains punycode
if (!domain.includes('xn--')) {
return domain; // No punycode to convert
}
// Check if punycode library is available
if (typeof punycode === 'undefined') {
throw new Error('Punycode library not loaded');
}
// Split domain into parts and convert each part
const parts = domain.split('.');
const convertedParts = parts.map(part => {
if (part.startsWith('xn--')) {
try {
return punycode.toUnicode(part);
} catch {
return part; // Return original if conversion fails
}
}
return part;
});
return convertedParts.join('.');
} catch (error) {
throw new Error('Invalid punycode format');
}
}
// Initialize IDN Punycode Converter
function initPunycodeConverter() {
const unicodeInput = document.getElementById('unicode-input');
const punycodeInput = document.getElementById('punycode-input');
const unicodeToPunycodeBtn = document.getElementById('unicode-to-punycode-btn');
const punycodeToUnicodeBtn = document.getElementById('punycode-to-unicode-btn');
const punycodeResult = document.getElementById('punycode-result');
const unicodeResult = document.getElementById('unicode-result');
if (!unicodeInput || !punycodeInput) return;
// Unicode to Punycode conversion
const convertUnicodeToPunycode = () => {
const input = unicodeInput.value.trim();
if (!input) {
punycodeResult.innerHTML = '';
return;
}
try {
const converted = toPunycode(input);
const isConverted = converted !== input;
punycodeResult.innerHTML = `
<div class="p-4 bg-green-50 dark:bg-green-900/30 rounded-lg">
<div class="flex justify-between items-start">
<div class="flex-1">
<h5 class="font-medium text-green-800 dark:text-green-200 mb-2">Punycode Result:</h5>
<div class="font-mono text-sm break-all p-2 bg-white dark:bg-gray-800 rounded border">${converted}</div>
${isConverted ? '<p class="text-xs text-green-600 dark:text-green-400 mt-2">✅ Conversion applied</p>' : '<p class="text-xs text-gray-500 dark:text-gray-400 mt-2"> No conversion needed (ASCII only)</p>'}
</div>
<button onclick="copyToClipboard('${converted}', this)" class="ml-2 p-2 text-green-600 dark:text-green-400 hover:bg-green-100 dark:hover:bg-green-800 rounded" title="Copy to clipboard">
<svg class="w-4 h-4" 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>
</button>
</div>
</div>
`;
} catch (error) {
punycodeResult.innerHTML = `
<div class="p-4 bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300 rounded-lg">
<h5 class="font-medium mb-1">Error:</h5>
<p class="text-sm">${error.message}</p>
</div>
`;
}
};
// Punycode to Unicode conversion
const convertPunycodeToUnicode = () => {
const input = punycodeInput.value.trim();
if (!input) {
unicodeResult.innerHTML = '';
return;
}
try {
const converted = fromPunycode(input);
const isConverted = converted !== input;
unicodeResult.innerHTML = `
<div class="p-4 bg-green-50 dark:bg-green-900/30 rounded-lg">
<div class="flex justify-between items-start">
<div class="flex-1">
<h5 class="font-medium text-green-800 dark:text-green-200 mb-2">Unicode Result:</h5>
<div class="font-mono text-sm break-all p-2 bg-white dark:bg-gray-800 rounded border">${converted}</div>
${isConverted ? '<p class="text-xs text-green-600 dark:text-green-400 mt-2">✅ Conversion applied</p>' : '<p class="text-xs text-gray-500 dark:text-gray-400 mt-2"> No conversion needed (no punycode found)</p>'}
</div>
<button onclick="copyToClipboard('${converted}', this)" class="ml-2 p-2 text-green-600 dark:text-green-400 hover:bg-green-100 dark:hover:bg-green-800 rounded" title="Copy to clipboard">
<svg class="w-4 h-4" 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 2v8a2 2 0 002 2z"></path>
</svg>
</button>
</div>
</div>
`;
} catch (error) {
unicodeResult.innerHTML = `
<div class="p-4 bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300 rounded-lg">
<h5 class="font-medium mb-1">Error:</h5>
<p class="text-sm">${error.message}</p>
</div>
`;
}
};
// Event listeners
unicodeToPunycodeBtn.addEventListener('click', convertUnicodeToPunycode);
punycodeToUnicodeBtn.addEventListener('click', convertPunycodeToUnicode);
// Auto-convert on input (with debounce)
let unicodeTimeout, punycodeTimeout;
unicodeInput.addEventListener('input', () => {
clearTimeout(unicodeTimeout);
unicodeTimeout = setTimeout(convertUnicodeToPunycode, 500);
});
punycodeInput.addEventListener('input', () => {
clearTimeout(punycodeTimeout);
punycodeTimeout = setTimeout(convertPunycodeToUnicode, 500);
});
// Paste support
unicodeInput.addEventListener('paste', () => {
setTimeout(convertUnicodeToPunycode, 100);
});
punycodeInput.addEventListener('paste', () => {
setTimeout(convertPunycodeToUnicode, 100);
});
}