HTML_Beautifier / index.html
Zx444's picture
- Follow Up Deployment
b80a08f verified
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Beautify HTML - Versi Gabungan</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.9/beautify-html.min.js"></script>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center p-6 font-sans">
<div class="w-full max-w-6xl bg-white rounded-xl shadow-xl border border-gray-200">
<!-- Header -->
<div class="bg-gradient-to-r from-blue-600 to-blue-500 text-white px-6 py-4 rounded-t-xl">
<h1 class="text-2xl font-bold">🤖 HTML Beautifier & Cleaner</h1>
<p class="text-sm opacity-90">Versi gabungan Tailwind + gaya ala BeautifyTools</p>
</div>
<!-- Tombol aksi -->
<div class="p-4 flex flex-wrap gap-3 border-b border-gray-200 bg-gray-50">
<button onclick="perbaikiHtml()"
class="px-4 py-2 bg-blue-600 text-white rounded-lg shadow hover:bg-blue-700 transition">
Perbaiki
</button>
<button onclick="beautifyHtml()"
class="px-4 py-2 bg-purple-600 text-white rounded-lg shadow hover:bg-purple-700 transition">
Beautify
</button>
<button onclick="copyOutput()"
class="px-4 py-2 bg-green-600 text-white rounded-lg shadow hover:bg-green-700 transition">
Copy
</button>
<button onclick="reviewOutput()"
class="px-4 py-2 bg-yellow-500 text-white rounded-lg shadow hover:bg-yellow-600 transition">
Preview
</button>
<button onclick="clearInput()"
class="px-4 py-2 bg-red-600 text-white rounded-lg shadow hover:bg-red-700 transition">
Clear
</button>
</div>
<!-- Tabs -->
<div class="px-6 pt-4">
<div class="flex space-x-2 border-b border-gray-200">
<button id="tab-input"
class="tab-btn px-4 py-2 font-medium border-b-2 border-blue-600 text-blue-600 bg-white rounded-t-lg">
Input
</button>
<button id="tab-output"
class="tab-btn px-4 py-2 font-medium border-b-2 border-transparent text-gray-600 hover:text-blue-600">
Hasil Script
</button>
<button id="tab-preview"
class="tab-btn px-4 py-2 font-medium border-b-2 border-transparent text-gray-600 hover:text-blue-600">
Live Preview
</button>
</div>
</div>
<!-- Panels -->
<div class="p-6">
<!-- Input -->
<div id="panel-input" class="tab-panel">
<textarea id="inputHtml"
class="w-full h-72 p-3 border rounded-lg shadow-inner font-mono text-sm focus:ring focus:ring-blue-300"
placeholder="<h1>Halo Dunia"></textarea>
</div>
<!-- Output -->
<div id="panel-output" class="tab-panel hidden">
<textarea id="outputHtml"
class="w-full h-96 p-3 border rounded-lg shadow-inner bg-gray-50 font-mono text-sm"
readonly></textarea>
</div>
<!-- Preview -->
<div id="panel-preview" class="tab-panel hidden">
<iframe id="previewFrame"
class="w-full h-96 border rounded-lg shadow bg-white"></iframe>
</div>
</div>
</div>
<script>
// Tab system
const tabs = ["input", "output", "preview"];
function switchTab(name) {
tabs.forEach(t => {
const btn = document.getElementById(`tab-${t}`);
const panel = document.getElementById(`panel-${t}`);
if (t === name) {
btn.classList.add("border-blue-600","text-blue-600","bg-white","rounded-t-lg");
btn.classList.remove("border-transparent","text-gray-600");
panel.classList.remove("hidden");
} else {
btn.classList.remove("border-blue-600","text-blue-600","bg-white","rounded-t-lg");
btn.classList.add("border-transparent","text-gray-600");
panel.classList.add("hidden");
}
});
}
switchTab("input");
document.getElementById("tab-input").addEventListener("click", () => switchTab("input"));
document.getElementById("tab-output").addEventListener("click", () => switchTab("output"));
document.getElementById("tab-preview").addEventListener("click", () => { ensurePreview(); switchTab("preview"); });
// Logic utama
function perbaikiHtml() {
const input = document.getElementById("inputHtml").value.trim();
const parser = new DOMParser();
const doc = parser.parseFromString(input || "<!DOCTYPE html><html><head></head><body></body></html>", "text/html");
let cleaned = "<!DOCTYPE html>\n" + doc.documentElement.outerHTML;
const needs = [];
if (!doc.querySelector("meta[charset]")) needs.push(" <meta charset='UTF-8'>");
if (!doc.querySelector("meta[name='viewport']")) needs.push(" <meta name='viewport' content='width=device-width, initial-scale=1.0'>");
if (!doc.querySelector("title")) needs.push(" <title>DokumenBaru</title>");
if (needs.length) cleaned = cleaned.replace("</head>", needs.join("\n") + "\n</head>");
document.getElementById("outputHtml").value = html_beautify(cleaned, {
indent_size: 2,
wrap_line_length: 100,
preserve_newlines: true
});
switchTab("output");
}
function beautifyHtml() {
const output = document.getElementById("outputHtml");
if (!output.value.trim()) {
alert("⚠️ Tidak ada hasil untuk Beautify. Klik Perbaiki dulu!");
return;
}
const beautified = html_beautify(output.value, {
indent_size: 2,
wrap_line_length: 100,
preserve_newlines: true
});
output.value = beautified;
switchTab("output");
}
function copyOutput() {
const output = document.getElementById("outputHtml");
if (!output.value.trim()) {
alert("⚠️ Tidak ada hasil untuk dicopy. Klik Perbaiki dulu!");
return;
}
navigator.clipboard.writeText(output.value)
.then(() => alert("✅ Script HTML berhasil dicopy!"))
.catch(() => {
output.select();
document.execCommand("copy");
alert("✅ Script HTML berhasil dicopy (fallback)!");
});
}
function ensurePreview() {
const output = document.getElementById("outputHtml").value.trim();
const iframe = document.getElementById("previewFrame");
if (output) {
iframe.srcdoc = output;
} else {
const raw = document.getElementById("inputHtml").value.trim();
iframe.srcdoc = raw || "<h3 style='font-family:sans-serif'>Tidak ada konten untuk dipreview</h3>";
}
}
function reviewOutput() {
ensurePreview();
switchTab("preview");
}
function clearInput() {
document.getElementById("inputHtml").value = "";
document.getElementById("outputHtml").value = "";
switchTab("input");
}
function downloadOutput() {
const output = document.getElementById("outputHtml").value;
if (!output.trim()) {
alert("⚠️ Tidak ada hasil untuk diunduh.");
return;
}
const blob = new Blob([output], { type: "text/html" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "hasil.html";
a.click();
URL.revokeObjectURL(url);
}
// Auto focus ke textarea input saat load
window.onload = () => document.getElementById("inputHtml").focus();
</script>
</body>
</html>