Українська
terminalГоловнаAcre
memory Client-Side DOM Engine shield Zero Data Retention

HTML Втеча та декодер

Convert special characters, markup tags, and extended Unicode symbols to named, decimal, and hexadecimal HTML entities without accidental DOM execution or XSS exposure.

expand_more
edit_note Input Plain Text or Markup
0 chars | 1 line
Memory Buffer Safe
Auto-transform enabled
terminal Converted Entity Output 0 replaced
0 chars • 0 entities
format_image_left No innerHTML parsing
Syntactic Tags
0
code
Quotes & Apos
0
format_quote
Ampersands
0
alternate_email
Unicode Codepoints
0
translate

Standard HTML5 Entity Cheat Table

Instant reference table for W3C markup delimiters, typography, mathematical sets, and symbols.

filter_alt
Character Named Reference Decimal Code Hex Code W3C Description Quick Insert
& & & & Ampersand delimiter (Critical)
< &lt; &#60; &#x3C; Opening tag delimiter (Critical)
> &gt; &#62; &#x3E; Closing tag delimiter (Critical)
" &quot; &#34; &#x22; Attribute quote enclosure (Critical)
' &apos; &#39; &#x27; Attribute apostrophe delimiter (Critical)
␣ &nbsp; &#160; &#xA0; Non-breaking white space
© &copy; &#169; &#xA9; Copyright symbol
® &reg; &#174; &#xAE; Registered trademark sign
€ &euro; &#8364; &#x20AC; Euro currency symbol
— &mdash; &#8212; &#x2014; Em dash typographic separator
Security Architecture & Specification

Deep-Dive: Escaping Mechanisms in Web Engines

gavel

The Five XML/HTML Critical Characters and XSS Defense

Standard markup lexers treat < and > as syntactic delimiters for DOM element boundaries. When user-supplied text enters an HTML document unescaped, an attacker can break out of string context to execute malicious inline scripts (<script>) or hijack event handlers.

Equally insidious are unescaped quote literals (" and ') inside attribute nodes like value="INPUT", allowing an attacker to inject " onmouseover=".... Escaping the foundational 5 characters neutralizes markup breakout at zero runtime performance penalty.

dialpad

Named vs Numeric Entities: Why Hex Is Universally Portable

While named character references such as &euro; або &trade; are human-legible, XML parsers (including strict SVG and XHTML runtimes) only natively acknowledge five named entities without an explicit DTD schema declaration.

In contrast, numeric entities—both decimal (&#8364;) and hexadecimal (&#x20AC;)—map explicitly to ISO 10646 and Unicode code points. Hexadecimal representation corresponds 1:1 with standard UTF-16 surrogate pairs and UTF-32 hex references, making it the most resilient format across legacy mainframes, XML parsers, and micro-embedded web views.

verified_user

Decoding Entities Without innerHTML To Prevent Client-Side Exploits

A frequent yet disastrous anti-pattern found in developer tools is delegating entity decoding to a phantom browser DOM element via el.innerHTML = input; return el.textContent;. If an unvetted payload includes active elements like <img src=x onerror=alert(1)>, the DOM parser initiates asynchronous execution in memory.

ToolAcre implements an air-gapped synthetic tokenizer. We decode hexadecimal/decimal codepoints via direct native String.fromCodePoint() and resolve named references through a static immutable hash dictionary. The browser DOM tree is never traversed or queried, completely precluding DOM-based execution.

Local Pipeline Architecture

Direct Character-Stream Pipeline

Every string transformation executes synchronously on worker memory. No sockets, no local-storage caching, no analytics probes on payload bodies. Inspect the execution flowchart below to see how raw strings are segmented and resolved.

Raw Stream UTF-8 / Unicode Scope Evaluator Syntax | Diacritics Regex Zero-Backtrack Codepoint Mapper fromCodePoint() Named & Hex Resolvers Sanitized Output Zero Egress
Advertisement
ad_units Developer Cloud Infrastructure • High-Performance Bare Metal Servers
` inside & verify security.\n
', diacritics: 'Café résumé with jalapeño, naïve façade, Noël smörgåsbord, and Crème Brûlée.\nAccented glyphs: à, è, ì, ò, ù, ñ, ç, å, ø, ü, é.', math: 'Financial Summary:\nAccount balance: €4,500.80 & £2,150.00 ≈ ¥350,000.\nFormulas: f(x) ≤ 100 × y ± √2; A ∩ B ≠ ∅; Limit → ∞.', ampersands: 'https://cdn.example.com/api/v2/query?session=89ab2f&locale=en-US&sort=desc&filter=tags\nAT&T, Ben & Jerry\'s, Barnes & Noble & Sons & Co.' }; // Scope match filters const CRITICAL_CHARS = ['&', '<', '>', '"', "'"]; function isCritical(char) { return CRITICAL_CHARS.includes(char); } function isExtended(char) { return char.charCodeAt(0) > 127; } function shouldEncodeChar(char, scope) { if (scope === 'syntax') { return isCritical(char); } else if (scope === 'extended') { return isCritical(char) || isExtended(char); } else { // 'all' return isCritical(char) || isExtended(char) || /[^a-zA-Z0-9\s]/.test(char); } } function encodeCharacter(char, format) { const code = char.codePointAt(0); if (format === 'named' && NAMED_MAP[char]) { return NAMED_MAP[char]; } if (format === 'decimal') { return `&#${code};`; } if (format === 'hex') { return `&#x${code.toString(16).toUpperCase()};`; } // Fallback if named is not mapped return `&#${code};`; } // Safe Decoder Engine (No innerHTML, strictly programmatic codepoints) function decodeEntities(str) { let count = 0; const decoded = str.replace(/&(#x[0-9a-fA-F]+|#[0-9]+|[a-zA-Z]+);/g, (match, body) => { count++; if (body.startsWith('#x') || body.startsWith('#X')) { const hex = body.slice(2); const cp = parseInt(hex, 16); if (!isNaN(cp)) return String.fromCodePoint(cp); } else if (body.startsWith('#')) { const dec = body.slice(1); const cp = parseInt(dec, 10); if (!isNaN(cp)) return String.fromCodePoint(cp); } else { const fullEntity = `&${body};`; if (REVERSE_NAMED[fullEntity]) return REVERSE_NAMED[fullEntity]; } return match; }); return { result: decoded, replacements: count }; } // Safe Encoder Engine function encodeEntities(str, scope, format) { let count = 0; let diffHtml = ''; let result = ''; // Iterate Unicode codepoints correctly for (const char of str) { if (shouldEncodeChar(char, scope)) { const ent = encodeCharacter(char, format); result += ent; count++; // Build visual difference tokens diffHtml += `${escapeForDisplay(ent)}`; } else { result += char; diffHtml += escapeForDisplay(char); } } return { result, replacements: count, diffHtml }; } function escapeForDisplay(text) { return text.replace(/&/g, '&').replace(//g, '>'); } // Core Compute Function function processTransformation() { const input = rawInput.value; // Update stats const chars = input.length; const lines = input ? input.split('\n').length : 1; charCountInput.textContent = `${chars.toLocaleString()} chars`; lineCountInput.textContent = `${lines} ${lines === 1 ? 'line' : 'lines'}`; // Compute metrics const tagsCount = (input.match(/[<>]/g) || []).length; const quoteCount = (input.match(/['"]/g) || []).length; const ampCount = (input.match(/&/g) || []).length; let unicodeCount = 0; for (const c of input) { if (c.charCodeAt(0) > 127) unicodeCount++; } statTags.textContent = tagsCount.toString(); statQuotes.textContent = quoteCount.toString(); statAmps.textContent = ampCount.toString(); statUnicode.textContent = unicodeCount.toString(); if (!input) { rawOutput.value = ''; diffOverlay.innerHTML = ''; diffCounterPill.textContent = '0 replaced'; outputMetaStats.textContent = '0 chars • 0 entities'; return; } if (currentMode === 'encode') { const { result, replacements, diffHtml } = encodeEntities(input, currentScope, currentFormat); rawOutput.value = result; diffOverlay.innerHTML = diffHtml; diffCounterPill.textContent = `${replacements.toLocaleString()} replaced`; outputMetaStats.textContent = `${result.length.toLocaleString()} chars • ${replacements} encoded`; } else { const { result, replacements } = decodeEntities(input); rawOutput.value = result; diffOverlay.innerHTML = escapeForDisplay(result); diffCounterPill.textContent = `${replacements.toLocaleString()} decoded`; outputMetaStats.textContent = `${result.length.toLocaleString()} chars • ${replacements} decoded`; } } // Scope Buttons Handling document.querySelectorAll('.scope-btn').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('.scope-btn').forEach(b => { b.classList.remove('bg-primary', 'text-on-primary', 'shadow-sm'); b.classList.add('bg-surface-container-low', 'text-secondary'); }); btn.classList.add('bg-primary', 'text-on-primary', 'shadow-sm'); btn.classList.remove('bg-surface-container-low', 'text-secondary'); currentScope = btn.dataset.scope; processTransformation(); }); }); // Format Buttons Handling document.querySelectorAll('.format-btn').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('.format-btn').forEach(b => { b.classList.remove('bg-primary', 'text-on-primary', 'shadow-sm'); b.classList.add('bg-surface-container-low', 'text-secondary'); }); btn.classList.add('bg-primary', 'text-on-primary', 'shadow-sm'); btn.classList.remove('bg-surface-container-low', 'text-secondary'); currentFormat = btn.dataset.format; processTransformation(); }); }); // Mode Switch Handling modeEncodeBtn.addEventListener('click', () => { currentMode = 'encode'; modeEncodeBtn.classList.add('bg-surface-container-lowest', 'text-primary', 'shadow-sm'); modeEncodeBtn.classList.remove('text-secondary'); modeDecodeBtn.classList.remove('bg-surface-container-lowest', 'text-primary', 'shadow-sm'); modeDecodeBtn.classList.add('text-secondary'); inputPaneLabel.textContent = 'Input Plain Text or Markup'; outputPaneLabel.textContent = 'Converted Entity Output'; processTransformation(); }); modeDecodeBtn.addEventListener('click', () => { currentMode = 'decode'; modeDecodeBtn.classList.add('bg-surface-container-lowest', 'text-primary', 'shadow-sm'); modeDecodeBtn.classList.remove('text-secondary'); modeEncodeBtn.classList.remove('bg-surface-container-lowest', 'text-primary', 'shadow-sm'); modeEncodeBtn.classList.add('text-secondary'); inputPaneLabel.textContent = 'Input Encoded Entities Markup'; outputPaneLabel.textContent = 'Decoded Plain Text Output'; processTransformation(); }); // Diff Viewer Toggle toggleDiffBtn.addEventListener('click', () => { showDiff = !showDiff; if (showDiff) { rawOutput.classList.add('hidden'); diffOverlay.classList.remove('hidden'); diffToggleText.textContent = 'Show Raw'; toggleDiffBtn.classList.add('bg-primary', 'text-on-primary'); toggleDiffBtn.classList.remove('bg-surface-container', 'text-on-surface'); } else { rawOutput.classList.remove('hidden'); diffOverlay.classList.add('hidden'); diffToggleText.textContent = 'Show Diff'; toggleDiffBtn.classList.remove('bg-primary', 'text-on-primary'); toggleDiffBtn.classList.add('bg-surface-container', 'text-on-surface'); } }); // Clipboard Action copyBtn.addEventListener('click', async () => { if (!rawOutput.value) return; try { await navigator.clipboard.writeText(rawOutput.value); copyBtnText.textContent = 'Copied!'; setTimeout(() => { copyBtnText.textContent = 'Copy'; }, 1800); } catch (e) { rawOutput.select(); document.execCommand('copy'); copyBtnText.textContent = 'Copied!'; setTimeout(() => { copyBtnText.textContent = 'Copy'; }, 1800); } }); // File Snippet Download downloadBtn.addEventListener('click', () => { if (!rawOutput.value) return; const blob = new Blob([rawOutput.value], { type: 'text/html;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `entities-${currentMode}-${Date.now()}.html`; a.click(); URL.revokeObjectURL(url); }); // Clear Buffer clearBtn.addEventListener('click', () => { rawInput.value = ''; rawInput.focus(); processTransformation(); }); // Sample Load sampleSelector.addEventListener('change', (e) => { const val = e.target.value; if (SAMPLES[val]) { rawInput.value = SAMPLES[val]; processTransformation(); } }); // Realtime listener rawInput.addEventListener('input', processTransformation); // Searchable Table Filter const tableFilterInput = document.getElementById('entity-table-filter'); const tableRows = document.querySelectorAll('#entity-table-body tr'); tableFilterInput.addEventListener('input', (e) => { const query = e.target.value.toLowerCase().trim(); tableRows.forEach(row => { const text = row.textContent.toLowerCase(); row.style.display = text.includes(query) ? '' : 'none'; }); }); // Global window insert helper window.insertEntityToInput = function(char) { const start = rawInput.selectionStart || 0; const end = rawInput.selectionEnd || 0; const current = rawInput.value; rawInput.value = current.substring(0, start) + char + current.substring(end); rawInput.focus(); rawInput.selectionStart = rawInput.selectionEnd = start + char.length; processTransformation(); }; // Initialize default test sample on first load rawInput.value = SAMPLES.html; processTransformation(); })();