const input = document.getElementById('tool-input'); const output = document.getElementById('tool-output'); const logFilter = document.getElementById('log-filter'); function setOutput(value) { output.textContent = value; } function decodeBase64Url(value) { const normalized = value.replace(/-/g, '+').replace(/_/g, '/'); const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, '='); return decodeURIComponent(atob(padded).split('').map((char) => `%${char.charCodeAt(0).toString(16).padStart(2, '0')}`).join('')); } document.getElementById('format-json').addEventListener('click', () => { try { setOutput(JSON.stringify(JSON.parse(input.value), null, 2)); } catch (error) { setOutput(`JSON parse error: ${error.message}`); } }); document.getElementById('decode-jwt').addEventListener('click', () => { try { const parts = input.value.trim().split('.'); if (parts.length < 2) throw new Error('Expected header.payload.signature'); setOutput(JSON.stringify({ header: JSON.parse(decodeBase64Url(parts[0])), payload: JSON.parse(decodeBase64Url(parts[1])) }, null, 2)); } catch (error) { setOutput(`JWT decode error: ${error.message}`); } }); document.getElementById('parse-url').addEventListener('click', () => { try { const url = new URL(input.value.trim()); const params = {}; url.searchParams.forEach((value, key) => { params[key] = value; }); setOutput(JSON.stringify({ protocol: url.protocol, host: url.host, pathname: url.pathname, query: params, hash: url.hash }, null, 2)); } catch (error) { setOutput(`URL parse error: ${error.message}`); } }); document.getElementById('filter-logs').addEventListener('click', () => { const needle = logFilter.value.trim().toLowerCase(); const lines = input.value.split('\n'); const result = needle ? lines.filter((line) => line.toLowerCase().includes(needle)) : lines; setOutput(result.join('\n') || 'No matching lines.'); });