"use client"; import { useState, useCallback, useId } from "react"; import ToolLayout from "@/components/ToolLayout"; const BASIC_ENTITIES_MAP: Record = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", }; const EXTENDED_ENTITIES_MAP: Record = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", "©": "©", "®": "®", "™": "™", "€": "€", "£": "£", "¥": "¥", "¢": "¢", "§": "§", "°": "°", "±": "±", "«": "«", "»": "»", "•": "•", "…": "…", "—": "—", "–": "–", "“": "“", "”": "”", "‘": "‘", "’": "’", "×": "×", "÷": "÷", "µ": "µ", "¶": "¶", "¼": "¼", "½": "½", "¾": "¾", }; type EncodeMode = "basic" | "extended" | "decimal" | "hex"; export default function HtmlEntitiesPage() { const inputId = useId(); const outputId = useId(); const [input, setInput] = useState(""); const [output, setOutput] = useState(""); const [error, setError] = useState(null); const [copied, setCopied] = useState(false); const [encodeMode, setEncodeMode] = useState("basic"); const [lastAction, setLastAction] = useState<"encode" | "decode" | null>(null); const encodeText = useCallback((text: string, mode: EncodeMode) => { if (!text) { setOutput(""); setError(null); return; } try { let result = ""; if (mode === "basic") { result = text.replace(/[&<>"']/g, (char) => BASIC_ENTITIES_MAP[char] || char); } else if (mode === "extended") { result = text.replace( /[&<>"'©®™€£¥¢§°±«»•…—–“”‘’×÷µ¶¼½¾]/g, (char) => EXTENDED_ENTITIES_MAP[char] || char ); } else if (mode === "decimal") { result = text.replace(/[&<>"']|[^\x20-\x7E\r\n\t]/g, (char) => { const code = char.codePointAt(0); return code !== undefined ? `&#${code};` : char; }); } else if (mode === "hex") { result = text.replace(/[&<>"']|[^\x20-\x7E\r\n\t]/g, (char) => { const code = char.codePointAt(0); return code !== undefined ? `&#x${code.toString(16).toUpperCase()};` : char; }); } setOutput(result); setError(null); setLastAction("encode"); } catch (err) { setError(err instanceof Error ? err.message : "Failed to encode HTML entities."); setOutput(""); } }, []); const decodeText = useCallback((text: string) => { if (!text) { setOutput(""); setError(null); return; } try { const textarea = document.createElement("textarea"); textarea.innerHTML = text; const decoded = textarea.value; setOutput(decoded); setError(null); setLastAction("decode"); } catch (err) { setError(err instanceof Error ? err.message : "Failed to decode HTML entities."); setOutput(""); } }, []); const handleEncode = () => { encodeText(input, encodeMode); }; const handleDecode = () => { decodeText(input); }; const handleCopy = async () => { if (!output) return; try { await navigator.clipboard.writeText(output); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { const textArea = document.createElement("textarea"); textArea.value = output; document.body.appendChild(textArea); textArea.select(); document.execCommand("copy"); document.body.removeChild(textArea); setCopied(true); setTimeout(() => setCopied(false), 2000); } }; const handleSwap = () => { const temp = output; setInput(temp); setOutput(input); setError(null); if (lastAction === "encode") { setLastAction("decode"); } else if (lastAction === "decode") { setLastAction("encode"); } }; const handleClear = () => { setInput(""); setOutput(""); setError(null); setLastAction(null); }; const loadSample = (type: "html" | "symbols" | "entities") => { setError(null); if (type === "html") { const sample = '
\n

Title: "Welcome & Enjoy"

\n

5 > 3 and 2 < 4 are true \'math\' facts!

\n
'; setInput(sample); encodeText(sample, encodeMode); } else if (type === "symbols") { const sample = 'Price: €99.99 / £85.00 © 2026 DevToolbox™ — "Fast & Secure" — 100° angle • ½ cup'; setInput(sample); setEncodeMode("extended"); encodeText(sample, "extended"); } else { const sample = '<div class="card">\n <h2>Hello &amp; Welcome!</h2>\n <p>Price: &euro;50 &copy; 2026</p>\n</div>'; setInput(sample); decodeText(sample); } }; return ( HTML Entity Encode & Decode Online — DevToolbox
{/* Controls Bar */}
{/* Sample buttons */}
Samples:
{/* Encoding Mode Selector */}
Encoding Format:
{/* Error Notification */} {error && (

Error

{error}

)} {/* Two-Column Editor Grid */}
{/* Input Area */}
{input.length} chars